179 | | It's a common practice that the program sources to build the RPM packages are taken from a tarball (referred to by the `Source:` keyword in the `.spec` file) which is provided by the program vendor and then stored in the source RPM. It works fine when the packages are built from the vendor sources w/o any modifications but this is rarely a case on OS/2. On OS/2, we don't push our patches upstream (for many reasons) and instead host our own repositories for programs that we support where we manage our patches (many of the programs are located here: http://trac.netlabs.org/ports/). |
180 | | |
181 | | Given this, using the tarball approach on OS/2 requires to pull a set of patches from our own source repository and apply it to the vendor's tarball to make the program work on OS/2 each time a new change is made. This requires a lot of manual work and is very inconvenient when dealing with a large number of packages. For this reason, it is strongly recommended to write `.spec` files that download the sources directly from the source repositories rather than use tarballs and patch files. This may be achieved with a very simple block of commands. |
182 | | |
183 | | Note that one should not worry too much about the network speed and traffic issues when using this approach since the sources are downloaded only once for each given repository revision; any subsequent attempt to build a package form the same revision will simply use the source ZIP created when the revision is fetched for the first time w/o involving any network connection. There is also a possibility to use local working copies to fetch the sources from instead of online repositories (see below). |
| 179 | It's a common practice to take the source code for building a set of RPM packages for a program from a tarball file (referred to by the `Source:` keyword in the `.spec` file) which is provided by the program vendor. This works fine when the packages are built from unmodified vendor sources but this is rarely a case on OS/2. This is mainly because we don't push our patches upstream (for many reasons) and instead host our own repositories for software that we support (many of the software is located here: http://trac.netlabs.org/ports/). |
| 180 | |
| 181 | Given this, using the tarball approach on OS/2 requires to pull a set of patches from our own source repository and apply it to the vendor's tarball to make the program work on OS/2 each time a new change is made and a new RPM version is to be released. This requires a lot of manual work which very inconvenient and time consuming, especially when dealing with a large number of packages. For this reason, it is strongly recommended to write `.spec` files that download the sources directly from the source repositories rather than use tarballs and patch files. This may be easily achieved with a couple of RPM macros that we added to RPM for OS/2 specifically for this purpose. The following instructions apply to both porting the existing `.spec` files to OS/2 and creating new ones. |
| 182 | |
| 183 | Note that you should not worry too much about the network speed and traffic issues when using these macros since the sources are downloaded only once for each given repository revision; any subsequent attempt to build a package form the same revision will simply use the source ZIP created when the revision is fetched for the first time w/o involving any network connection. This ZIP is also stored in a SRPM file as usual, so a rebuild of the package may be done without accessing the repository as long as the SRPM file for the given set of packages is available. There is also a possibility to use local working copies to fetch the sources from instead of online repositories (see below). |
| 184 | |
| 185 | ==== %scm_source ==== |
| 186 | |
| 187 | This macro is intended as a replacement for the standard `Source:` tag. The format is as follows: |
| 188 | {{{ |
| 189 | %scm_source SCM URL REV |
| 190 | }}} |
| 191 | where SCM is the type of the source code management system (currently supported ones are `svn`, `git` and `github`), URL is the full URL of the source code repository for the given program and REV is the revision to use. |
| 192 | |
| 193 | ==== %scm_setup ==== |
| 194 | |
| 195 | This macro is intended as a replacement for the standard `%setup` macro that starts a `%prep` section. |
| 196 | |
| 197 | The format is as simple as: |
| 198 | {{{ |
| 199 | %scm_setup |
| 200 | }}} |
| 201 | |
| 202 | Further sections describe the supported SCM types in detail. |
187 | | The snippets below assume our http://trac.netlabs.org/ports/ source repository layout. They are taken from this real-life [http://trac.netlabs.org/rpm/browser/spec/trunk/SPECS/libtool.spec?rev=471 spec file]. |
188 | | |
189 | | Paste this block after the main keyword block and before the `%description` field for the main package: |
190 | | {{{ |
191 | | %define svn_url http://svn.netlabs.org/repos/ports/libtool/trunk |
192 | | %define svn_rev 891 |
193 | | |
194 | | Source: %{name}-%{version}%{?svn_rev:-r%{svn_rev}}.zip |
195 | | |
196 | | BuildRequires: gcc make subversion zip |
197 | | }}} |
198 | | |
199 | | Paste this block instead of the usual `%prep / %setup / %patch` sequence: |
200 | | {{{ |
201 | | %prep |
202 | | %if %{?svn_rev:%(sh -c 'if test -f "%{_sourcedir}/%{name}-%{version}-r%{svn_rev}.zip" ; then echo 1 ; else echo 0 ; fi')}%{!?svn_rev):0} |
203 | | %setup -q |
204 | | %else |
205 | | %setup -n "%{name}-%{version}" -Tc |
206 | | svn export %{?svn_rev:-r %{svn_rev}} %{svn_url} . --force |
207 | | rm -f "%{_sourcedir}/%{name}-%{version}%{?svn_rev:-r%{svn_rev}}.zip" |
208 | | (cd .. && zip -SrX9 "%{_sourcedir}/%{name}-%{version}%{?svn_rev:-r%{svn_rev}}.zip" "%{name}-%{version}") |
209 | | %endif |
210 | | }}} |
211 | | |
212 | | In order to use the working copy instead of the URL (useful for creating test packages during development) modify the first snippet to something like this (note `%` replaced with `#`, not with `#%` — this is because rpmbuild evaluates macros even if they are in comment lines): |
213 | | {{{ |
214 | | %define svn_url D:/Coding/ports/libtool/trunk |
215 | | #define svn_rev 891 |
216 | | }}} |
217 | | |
218 | | Note the commented out `svn_rev` variable — this causes the local changes from the working copy to be picked up. If `svn_rev` is not commented out then the specified revision w/o any local modifications will be used (the same way as when giving an URL; the only difference is that no network connection is required given that the specified revision is already contained in the working copy). |
| 206 | An example: |
| 207 | {{{ |
| 208 | %scm_source svn http://svn.netlabs.org/repos/ports/which/trunk 733 |
| 209 | }}} |
| 210 | This will check out revision 733 of program `which` from the trunk of the our main OS/2 repository. |
| 211 | |
| 212 | Note that for testing purposes you may use a local working copy of the SVN repository by specifying something like ` D:/Coding/ports/which/trunk` instead of the URL. You may also omit the revision number if you want your local changes to be used instead of a clean revision. But please never distribute RPM packages built this way as it's generally impossible to rebuild them on another machine which breaks RPM repository consistency and our deployment rules. Also note that if you omit the revision number, no source ZIP file will be created by `%scm_source` so the source code will be checked out each time you build an RPM and an attempt to run the full build cycle that creates an SRPM file will fail. |
222 | | Projects that use git may be handled similarly but they have their own specifics. There is currently no real-life example of such a project in our repositories but let's assume there is a project called `foobar` with a remote repository at `git://mygitserver.com`. |
223 | | |
224 | | Paste this block after the main keyword block and before the `%description` field for the main package: |
225 | | {{{ |
226 | | %define git_url git://mygitserver.com/foobar.git |
227 | | %define git_rev mytag |
228 | | |
229 | | Source: %{name}-%{git_rev}.zip |
230 | | |
231 | | BuildRequires: gcc make git zip |
232 | | }}} |
233 | | |
234 | | Paste this block instead of the usual `%prep / %setup / %patch` sequence: |
235 | | {{{ |
236 | | %prep |
237 | | %if %(sh -c 'if test -f "%{_sourcedir}/%{name}-%{git_rev}.zip" ; then echo 1 ; else echo 0 ; fi') |
238 | | %setup -q |
239 | | %else |
240 | | %setup -n "%{name}-%{version}" -Tc |
241 | | rm -f "%{_sourcedir}/%{name}-%{git_rev}.zip" |
242 | | git archive --format zip --output "%{_sourcedir}/%{name}-%{git_rev}.zip" --prefix "%{name}-%{version}/" --remote "%{git_url}" "%{git_rev}" |
243 | | unzip "%{name}-%{git_rev}.zip" -d .. |
244 | | %endif |
245 | | }}} |
246 | | |
247 | | Note that you may use your local clone instead of the remote repository as well as with SVN to save some traffic. The URL in this case should be something like `file://D:/Coding/foobar`. |
248 | | |
249 | | === Github === |
250 | | |
251 | | If a project is hosted at [http://github.com github], we will need to use `curl` instead of `git archive` because github does not support the `archive` command and instead provides a special URL for downloading ZIPs of the tree at any given commit or tag. The snippets below are based on this real-life [http://trac.netlabs.org/rpm/browser/spec/trunk/SPECS/libkai.spec?rev=576 spec file]. |
252 | | |
253 | | Paste this block after the main keyword block and before the `%description` field for the main package: |
254 | | {{{ |
255 | | %define github_name kai |
256 | | %define github_url https://github.com/komh/%{github_name}/archive |
257 | | %define github_rev kai-%{version} |
258 | | |
259 | | Source: %{github_name}-%{github_rev}.zip |
260 | | |
261 | | BuildRequires: gcc make curl zip |
262 | | }}} |
263 | | |
264 | | Paste this block instead of the usual `%prep / %setup / %patch` sequence: |
265 | | {{{ |
266 | | %prep |
267 | | %if %(sh -c 'if test -f "%{_sourcedir}/%{github_name}-%{github_rev}.zip" ; then echo 1 ; else echo 0 ; fi') |
268 | | %setup -n "%{github_name}-%{github_rev}" -q |
269 | | %else |
270 | | %setup -n "%{github_name}-%{github_rev}" -Tc |
271 | | rm -f "%{_sourcedir}/%{github_name}-%{github_rev}.zip" |
272 | | curl -sSL "%{github_url}/%{github_rev}.zip" -o "%{_sourcedir}/%{github_name}-%{github_rev}.zip" |
273 | | unzip "%{_sourcedir}/%{github_name}-%{github_rev}.zip" -d .. |
274 | | %endif |
275 | | }}} |
276 | | |
277 | | Note that due to github naming specifics (and especially if the github's project name doesn't match the RPM package name, (like `kai` vs `libkai` in the example above), the source ZIP will have a name that differs from the usual `%{name}-%{version}` scheme (in the example above it will be `kai-kai-1.1.4.zip` rather than `libkai-1.1.4.zip`). |
278 | | |
279 | | You could use your local clone instead of the remote repository here as well but in this case magic github URLs for downloading ZIPs won't work so you will have to use the `git archive` command as in the [#Git] section above which is not very practical because you will have to make a lot of temporary changes to your `.spec` file which you will have to revert before committing it to the SPEC repo. |
| 216 | An example: |
| 217 | {{{ |
| 218 | %scm_source git git://mygitserver.com/foobar.git mytag |
| 219 | }}} |
| 220 | This will check out a commit named `mytag` from the `foobar`'s repository (you may use any supported Git commit identifier instead of tags, of course). |
| 221 | |
| 222 | You may also omit the revision specification at all in which case it will checkout the HEAD commit. Note, however, that as well as in case of SVN, packages with a missing revision specification must not be distributed No ZIP files are created for them, so a clean checkout will happen each time and SRPM creation will fail. |
| 223 | |
| 224 | Using local clones of git repositories for test builds is also possible, the URL in this case will be something like `file://D:/Coding/foobar`. |
| 225 | |
| 226 | === !GitHub === |
| 227 | |
| 228 | An example: |
| 229 | {{{ |
| 230 | %scm_source github https://github.com/komh/kai kai-%{version} |
| 231 | }}} |
| 232 | This will checkout a commit named `kai-%{version}` from the GitHub-hosted project `kai` which is owned the user named `komh`. Any valid Git commit identifier may be used. Note that you cannot omit the commit specification in case of GitHub. |
| 233 | |
| 234 | You may use local clones of GitHub projects for test builds but in this case you should use the `git` SCM type as described in the [#Git] section above. |