forked from fedora-java/howto
-
Notifications
You must be signed in to change notification settings - Fork 0
/
introduction_for_developers.txt
221 lines (182 loc) · 8.32 KB
/
introduction_for_developers.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
Packaging Java software has specifics which we will try to cover in this section
aimed at Java developers who are already familiar with Java language, JVM,
classpath handling, Maven, pom.xml file structure and dependencies.
Instead we will focus on basic packaging tools and relationships between Java
and RPM world. One of the most important questions is: What is the reason to
package software in RPM (or other distribution-specific formats). There are
several reasons for it, among others:
- Unified way of installation of software for users of distribution regardless
of upstream projects
- Verification of authenticity of software packages by signing them
- Simplified software updates
- Automatic handling of dependencies for users
- Common filesystem layout across distribution enforced by packaging standards
- Ability to administer, monitor and query packages installed on several
machines through unified interfaces
- Distribution of additional metadata with the software itself such as
licenses used, homepage for the project, changelogs and other information
that users or administrators can find useful
==== Example RPM Project
RPM uses `spec` files as recipes for building software packages. We
will use it to package example project created in previous section. If
you didn't read it you don't need to; the file listing is available here
and the rest is not necessary for this section.
.Directory listing
[source,shell]
------
Makefile
src
src/org
src/org/fedoraproject
src/org/fedoraproject/helloworld
src/org/fedoraproject/helloworld/output
src/org/fedoraproject/helloworld/output/Output.java
src/org/fedoraproject/helloworld/input
src/org/fedoraproject/helloworld/input/Input.java
src/org/fedoraproject/helloworld/HelloWorld.java
------
We packed the project directory into file `helloworld.tar.gz`.
.Example spec file
[source,spec,numbered]
------
include::rpm_project/helloworld.spec[]
------
RPM `spec` files contain several basic sections:
Header, which contains: ::
* Package metadata such as its name, version, release,
license...
* A `Summary` with basic one-line summary of package contents
* Package source URLs denoted with `Source0` to `SourceN` directives
** Source files can then be referenced by `%SOURCE0` to
`%SOURCEn`, which expand to actual paths to given files
** In practice, the source URL shouldn't point to a file in our
filesystem, but to an upstream release on the web
* Patches - using `Patch0` to `PatchN`
* Project dependencies
** Build dependencies specified by `BuildRequires`, which need to be
determined manually.
** Run time dependencies will be detected automatically. If it fails,
you have to specify them with `Requires`.
** More information on this topic can be found in
<<dependency_handling,Dependency handling>> section.
Description::
* Few sentences about the project and its uses. It will be displayed
by package management software.
Prep section::
* Unpacks the sources using `setup -q` or manually if needed
* If a source file doesn't need to be extracted, it can be copied
to build directory by `cp -p %SOURCE0 .`
* Apply patches with `%patchX`, where X is the number of patch you
want to apply. (You usually need the patch index, so it would be:
`%patch0 -p1`)
Build section::
* Contains project compilation instructions. Usually consists of
calling the projects build system such as Ant, Maven or Make.
Optional `%check` section::
* Runs projects integration tests. Unit test are usually run in
`%build` section, so if there are no integration tests available,
this section is omitted
Install section::
* Copies built files that are supposed to be installed into
`%{buildroot}` directory, which represents target filesystem's root
Files section::
* Lists all files, that should be installed from `%{buildroot}` to
target system.
* Documentation files are prefixed by `%doc` and are
taken from build directory instead of buildroot
* Directories that this package should own are prefixed with `%dir`
Changelog::
* Contains changes to this spec file (not upstream)
* Has prescribed format. To prevent mistakes in format, it is
advised to use tool such as `rpmdev-bumpspec` from package rpmdevtools to
append new changelog entries instead of editing it by hand
To build RPM from link:rpm_project/helloworld.spec[this `spec` file] save it in
your current directory and run `rpmbuild`:
[source,shell]
------
$ rpmbuild -bb helloworld.spec
------
If everything worked OK, this should produce RPM file
`~/rpmbuild/RPMS/x86_64/helloworld-1.0-1.fc18.x86_64.rpm`. You can use
`rpm -i` or `dnf install` commands to install this package and it
will add `/usr/share/java/helloworld.jar` and `/usr/bin/helloworld`
wrapper script to your system. Please note that this specfile is
simplified and lacks some additional parts, such as license
installation.
[NOTE]
======
Paths and filenames might be slightly different depending on your architecture
and distribution. Output of the commands will tell you exact paths
======
As you can see to build RPM files you can use `rpmbuild` command. It has several
other options, which we will cover later on.
Except building binary RPMs (`-bb`), `rpmbuild` can also be told to:
- build only source RPMs (SRPMs), the packages containing source files
which can be later build to RPMs (option `-bs`)
- build all, both binary and source RPMs (option `-ba`)
See `rpmbuild`'s manual page for all available options.
[[querying_repositories]]
==== Querying repositories
Fedora comes with several useful tools which can provide great
assistance in getting information from RPM repositories.
`dnf repoquery` is a tool for querying information from RPM repositories.
Maintainer of Java packages might typically query the repository for
information like "which package contains Maven artifact
`groupId:artifactId`".
.Find out which package provides given artifact
[source,shell]
------
$ dnf repoquery --whatprovides 'mvn(commons-io:commons-io)'
apache-commons-io-1:2.4-9.fc19.noarch
------
The example above shows that one can get to `commons-io:commons-io`
artifact by installing `apache-commons-io` package.
By default, `dnf repoquery` uses all enabled repositories in DNF
configuration, but it is possible to explicitly specify any other
repository. For example following command will query only Rawhide
repository:
[source,shell]
------
$ dnf repoquery --available --disablerepo \* --enablerepo rawhide --whatprovides 'mvn(commons-io:commons-io)'
apache-commons-io-1:2.4-10.fc20.noarch
------
Sometimes it may be useful to just list all the artifacts provided by
given package:
[source,shell]
------
$ dnf repoquery --provides apache-commons-io
apache-commons-io = 1:2.4-9.fc19
jakarta-commons-io = 1:2.4-9.fc19
mvn(commons-io:commons-io) = 2.4
mvn(org.apache.commons:commons-io) = 2.4
osgi(org.apache.commons.io) = 2.4.0
------
Output above means that package `apache-commons-io` provides two Maven
artifacts: previously mentioned `commons-io:commons-io` and
`org.apache.commons:commons-io`. In this case the second one is just an
alias for same JAR file. See section about <<aliases,artifact aliases>>
for more information on this topic.
Another useful tool is `rpm`. It can do a lot of stuff, but most
importantly it can replace `dnf repoquery` if one only needs to query local
RPM database. Only installed packages, or local `.rpm` files, can be
queried with this tool.
Common use case could be checking which Maven artifacts provide locally
built packages.
[source,shell]
------
$ rpm -qp --provides simplemaven-1.0-2.fc21.noarch.rpm
mvn(com.example:simplemaven) = 1.0
mvn(simplemaven:simplemaven) = 1.0
simplemaven = 1.0-2.fc21
------
==== Quiz for Java Developers
1. How would you build a binary RPM if you were given a source RPM?
2. What is most common content of Source0 `spec` file tag?
3. What is the difference between `Version` and `Release` tags?
4. How would you apply a patch in RPM?
5. Where on filesystem should JAR files go?
6. What is the format of RPM changelog or what tool would you use to produce it?
7. How would you install an application that needs certain layout (think
ANT_HOME) while honoring distribution filesystem layout guidelines?
8. How would you generate script for running a application with main class
org.project.MainClass which depends on commons-lang jar?