Difference between revisions of "RPM Packager"

From ADempiere
Jump to: navigation, search
This Wiki is read-only for reference purposes to avoid broken links.
Line 18: Line 18:
 
=Preface=
 
=Preface=
 
<div><div class="titlepage"><div><div></div></div></div><p>The Spec File to build the Adempiere RPM was developed and tested on Fedora 13.</p><p>The Fedora Packaging Guidelines have been followed, with some exceptions:</p><p>
 
<div><div class="titlepage"><div><div></div></div></div><p>The Spec File to build the Adempiere RPM was developed and tested on Fedora 13.</p><p>The Fedora Packaging Guidelines have been followed, with some exceptions:</p><p>
;Version and Release Numbering :Version information should be in the form: <pre class="programlisting">majorVersion.minorVersion-buildNumber.patchNumber[.releaseTag]</pre> So if upstream releases its product as adempiere351a, it should be packaged as: <pre class="programlisting">adempiere-3.5-1.X.a</pre> (where 1 is the build number and X is the packager's "patch level", which is incremented on each build).<br/><br/>However, upstream maintains the build number as part of the version number, and it does not follow the convention of 0=pre-release, 1=release, &gt;1=post-release. For RPM's version control method, it therefore makes more sense to use the revision in the Mercurial repository as build number.<br/><br/>We also want to have automatic patch-level numbering, and the build date seems most suitable for that purpose.<br/><br/>Therefore, our version numbering will have following syntax: <pre class="programlisting">majorVersion.minorVersion.buildNumber-hgRevision.buildDate[.releaseTag]</pre> which would result in following package names: <pre class="programlisting">adempiere331 -&gt; adempiere-3.3.1-1943.buildDate
+
;Version and Release Numbering :Version information should be in the form: <pre class="programlisting">majorVersion.minorVersion-buildNumber.patchNumber[.releaseTag]</pre> So if upstream releases its product as adempiere351a, it should be packaged as: <pre class="programlisting">adempiere-3.5-1.X.a</pre> (where 1 is the build number and X is the packager's "patch level", which is incremented on each build).<br/><br/>However, upstream maintains the build number as part of the version number, and it does not follow the convention of 0=pre-release, 1=release, &gt;1=post-release. For RPM's version control method, it therefore makes more sense to use the revision in the Mercurial repository as build number.<br/><br/>We also want to have automatic patch-level numbering, and the build date seems most suitable for that purpose.<br/><br/>Therefore, our version numbering will have following syntax: <pre class="programlisting">majorVersion.minorVersion.buildNumber-hgRevision.buildDate[.releaseTag]</pre> which would result in following package names:  
adempiere354a -&gt; adempiere-3.5.4-5276.buildDate.a
+
<pre class="programlisting">
adempiere360lts -&gt; adempiere-3.6.0-6510.buildDate.lts</pre>  
+
adempiere331 -&gt; adempiere-3.3.1-1943.buildDate
 +
adempiere354a -&gt; adempiere-3.5.4-5276.buildDate.a
 +
adempiere360lts -&gt; adempiere-3.6.0-6510.buildDate.lts
 +
</pre>  
 
;Pre-built Binaries and Libraries :All binaries and libraries in Fedora packages must be built from source code. The source package is not allowed to contain pre-built binaries and libraries.<br/><br/>However, Adempiere comes with various *.jar archives containing pre-built *.class files.<br/><br/>Some of them are simply used as tools in the build-chain and would easily be replaceable with open-source Fedora libraries.<br/><br/>Others are used in the final product such as the jdbc-drivers for database connections. They would be more difficult to replace, although it would certainly be possible.<br/><br/>Since we are going to build Adempiere packages for our own use and not for distribution with Fedora, we will gracefully ignore this requirement for the time being.  
 
;Pre-built Binaries and Libraries :All binaries and libraries in Fedora packages must be built from source code. The source package is not allowed to contain pre-built binaries and libraries.<br/><br/>However, Adempiere comes with various *.jar archives containing pre-built *.class files.<br/><br/>Some of them are simply used as tools in the build-chain and would easily be replaceable with open-source Fedora libraries.<br/><br/>Others are used in the final product such as the jdbc-drivers for database connections. They would be more difficult to replace, although it would certainly be possible.<br/><br/>Since we are going to build Adempiere packages for our own use and not for distribution with Fedora, we will gracefully ignore this requirement for the time being.  
 
; Spec File Legibility :All efforts have been made to keep the Spec File legible, whereby priority has been given to legibility in terms of humanly readable over being able to read and understand the algorithms.<br/><br/>Normally the user would only have to set or modify parameters at the beginning of the file (marked &#8220;SETTINGS&#8221;), add his sources and patches to the preamble (marked &#8220;your custom sources come here&#8221; and &#8220;your custom patches come here&#8221;), and install or apply them in the %prep section (marked &#8220;install your sources here&#8221; and &#8220;apply your patches here&#8221;). Everything else should just work.<br/><br/>Many different parameters can be used in the Spec File, and commenting them all in place would result in a very long settings section where important or conflicting parameters could easily be overlooked. Instead, the parameters are explained with their default values in the appendix of this manual. All parameters have sensible default values, so even if no parameters are set the Spec File will still produce an installable and runnable package.<br/><br/>Macros used by the build and installation scripts are defined and evaluated in a section titled &#8220;INITIALIZATION&#8221;, which comes between the settings and the preamble. Inside the scripts, the function and contents of those macros can be understood intuitively by their names, and as most people will not want to get into the detailed algorithms of how they were defined, the definitions are written in a way that keeps the Spec File nice and tidy and easily readable by humans. For debugging purposes, it is recommendable to expand those macros to multiple lines where necessary for easier understanding of conditions, loops, etc.<br/><br/>A lot of regular expressions are used in combination with grep, sed, and awk in the macro definitions. They are not further explained, as commenting one line of code with twenty lines of explanation would make the Spec File difficult to read as a whole.<br/><br/>Since all sub packages use exactly the same installation scripts (behavior is tweaked for each sub package by just setting some variables at the beginning of the scripts), rather than writing the scripts again and again, they have been included as source files which will be dynamically expanded when the packages are built.<br/><br/>The SOURCES directory easily becomes very messy when numerous source files and patches are scattered about. For this reason, the files distributed with the Source-RPM are prefixed with sXXX_ (for sources) and pXXX_ (for patches), where XXX corresponds to the patch or source number in the Spec File. Users are encouraged to name their sources and patches following the same scheme, starting with number 100.  
 
; Spec File Legibility :All efforts have been made to keep the Spec File legible, whereby priority has been given to legibility in terms of humanly readable over being able to read and understand the algorithms.<br/><br/>Normally the user would only have to set or modify parameters at the beginning of the file (marked &#8220;SETTINGS&#8221;), add his sources and patches to the preamble (marked &#8220;your custom sources come here&#8221; and &#8220;your custom patches come here&#8221;), and install or apply them in the %prep section (marked &#8220;install your sources here&#8221; and &#8220;apply your patches here&#8221;). Everything else should just work.<br/><br/>Many different parameters can be used in the Spec File, and commenting them all in place would result in a very long settings section where important or conflicting parameters could easily be overlooked. Instead, the parameters are explained with their default values in the appendix of this manual. All parameters have sensible default values, so even if no parameters are set the Spec File will still produce an installable and runnable package.<br/><br/>Macros used by the build and installation scripts are defined and evaluated in a section titled &#8220;INITIALIZATION&#8221;, which comes between the settings and the preamble. Inside the scripts, the function and contents of those macros can be understood intuitively by their names, and as most people will not want to get into the detailed algorithms of how they were defined, the definitions are written in a way that keeps the Spec File nice and tidy and easily readable by humans. For debugging purposes, it is recommendable to expand those macros to multiple lines where necessary for easier understanding of conditions, loops, etc.<br/><br/>A lot of regular expressions are used in combination with grep, sed, and awk in the macro definitions. They are not further explained, as commenting one line of code with twenty lines of explanation would make the Spec File difficult to read as a whole.<br/><br/>Since all sub packages use exactly the same installation scripts (behavior is tweaked for each sub package by just setting some variables at the beginning of the scripts), rather than writing the scripts again and again, they have been included as source files which will be dynamically expanded when the packages are built.<br/><br/>The SOURCES directory easily becomes very messy when numerous source files and patches are scattered about. For this reason, the files distributed with the Source-RPM are prefixed with sXXX_ (for sources) and pXXX_ (for patches), where XXX corresponds to the patch or source number in the Spec File. Users are encouraged to name their sources and patches following the same scheme, starting with number 100.  

Revision as of 19:41, 18 September 2011

RPM User Manual
Adempiere RPM Packager
by Stefan Christians
2011-08-02

This program is part of Adempiere ERP Bazaar
http://www.adempiere.org

Copyright © Stefan Christians
Copyright © Contributors

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

Contributors: Stefan Christians
Sponsors: K.K. Alice

Adempiere is a registered trademark of Adempiere, Inc.
All other company or product names are mentioned for identification purposes only, and may be trademarks of their respective owners.


Packaging and Distributing Adempiere on RedHat-like Systems

This source package includes the Spec File and tools to download, customize, compile, configure, distribute, install, and run Adempiere on RedHat-like systems which use RPM as their package manager.


Preface

The Spec File to build the Adempiere RPM was developed and tested on Fedora 13.

The Fedora Packaging Guidelines have been followed, with some exceptions:

Version and Release Numbering 
Version information should be in the form:
majorVersion.minorVersion-buildNumber.patchNumber[.releaseTag]
So if upstream releases its product as adempiere351a, it should be packaged as:
adempiere-3.5-1.X.a
(where 1 is the build number and X is the packager's "patch level", which is incremented on each build).

However, upstream maintains the build number as part of the version number, and it does not follow the convention of 0=pre-release, 1=release, >1=post-release. For RPM's version control method, it therefore makes more sense to use the revision in the Mercurial repository as build number.

We also want to have automatic patch-level numbering, and the build date seems most suitable for that purpose.

Therefore, our version numbering will have following syntax:
majorVersion.minorVersion.buildNumber-hgRevision.buildDate[.releaseTag]
which would result in following package names:
	adempiere331 -> adempiere-3.3.1-1943.buildDate
	adempiere354a -> adempiere-3.5.4-5276.buildDate.a
	adempiere360lts -> adempiere-3.6.0-6510.buildDate.lts
Pre-built Binaries and Libraries 
All binaries and libraries in Fedora packages must be built from source code. The source package is not allowed to contain pre-built binaries and libraries.

However, Adempiere comes with various *.jar archives containing pre-built *.class files.

Some of them are simply used as tools in the build-chain and would easily be replaceable with open-source Fedora libraries.

Others are used in the final product such as the jdbc-drivers for database connections. They would be more difficult to replace, although it would certainly be possible.

Since we are going to build Adempiere packages for our own use and not for distribution with Fedora, we will gracefully ignore this requirement for the time being.
Spec File Legibility 
All efforts have been made to keep the Spec File legible, whereby priority has been given to legibility in terms of humanly readable over being able to read and understand the algorithms.

Normally the user would only have to set or modify parameters at the beginning of the file (marked “SETTINGS”), add his sources and patches to the preamble (marked “your custom sources come here” and “your custom patches come here”), and install or apply them in the %prep section (marked “install your sources here” and “apply your patches here”). Everything else should just work.

Many different parameters can be used in the Spec File, and commenting them all in place would result in a very long settings section where important or conflicting parameters could easily be overlooked. Instead, the parameters are explained with their default values in the appendix of this manual. All parameters have sensible default values, so even if no parameters are set the Spec File will still produce an installable and runnable package.

Macros used by the build and installation scripts are defined and evaluated in a section titled “INITIALIZATION”, which comes between the settings and the preamble. Inside the scripts, the function and contents of those macros can be understood intuitively by their names, and as most people will not want to get into the detailed algorithms of how they were defined, the definitions are written in a way that keeps the Spec File nice and tidy and easily readable by humans. For debugging purposes, it is recommendable to expand those macros to multiple lines where necessary for easier understanding of conditions, loops, etc.

A lot of regular expressions are used in combination with grep, sed, and awk in the macro definitions. They are not further explained, as commenting one line of code with twenty lines of explanation would make the Spec File difficult to read as a whole.

Since all sub packages use exactly the same installation scripts (behavior is tweaked for each sub package by just setting some variables at the beginning of the scripts), rather than writing the scripts again and again, they have been included as source files which will be dynamically expanded when the packages are built.

The SOURCES directory easily becomes very messy when numerous source files and patches are scattered about. For this reason, the files distributed with the Source-RPM are prefixed with sXXX_ (for sources) and pXXX_ (for patches), where XXX corresponds to the patch or source number in the Spec File. Users are encouraged to name their sources and patches following the same scheme, starting with number 100.
Tags 
The Packager and Vendor tags are used in spite of the guideline's recommendation not to do so. They are used for identification and documentation purposes to differentiate between the original distribution and patched versions.

The BuildRoot tag is present for compatibility with other RedHat-like systems.
Requirements 
Adempiere requires Java to run. As of Adempiere 3.6.0, JDK 1.6 is required.

Actually any Java distribution can be used, and the original Sun Java software is most tested and reliable for Adempiere. But since it is not distributed as an RPM, and theoretically can be installed at any location, it is virtually impossible to check for it as a build or target requirement.

Therefore the openJDK distribution is listed as requirement for both compiling the source and installing the RPM on a target machine. The user is still free to use any Java distribution he wants, but openJDK must at least be installed.
Documentation 
Adempiere mainly uses online documentation. Text files such as README in the source code are often meaningless. However, all pdf files found in the source after compiling are copied into the documentation folder for all sub packages, regardless in which sub package they were found and without distinguishing whether they are for users, administrators or developers.
Users and Groups 
If the adempiere user or group already exists on the target system, an attempt is made to change the uid and gid to those defined in the Spec File, and to move the home directory to the location defined in the Spec File.

Introduction

Platform Independence

Adempiere is written in Java and as such strives to run on any operating system which is supported by Java. In effect it means that Adempiere can run on any modern operating system such as Windows, Mac OS X, Solaris, and Linux.

To install Adempiere, you download the binary package as zip-file from sourceforge, drop it somewhere into the directory tree, unzip the file, run RUN_setup.sh, and you have Adempiere installed and configured. The procedure is the same on any operating system.

While this platform independence is remarkable, it comes at a cost: The software can not be optimized for any particular system. Particularly on Linux machines, there are several issues which shall be examined in more detail.

Linux Issues

The Filesystem Hierarchy Standard

Linux follows the Filesystem Hierarchy Standard (FHS) which defines where what kind of files should be located.

According to the FHS, we would expect Adempiere to install its files in the following directories:

configuration files/etc/adempiere/
executable binaries/usr/bin/
libraries and resources/usr/lib/adempiere/
documentation/usr/share/doc/adempiere/
data and variable state files/var/lib/adempiere/
log files/var/log

But instead all files are just installed in one big chunk with its own sub-directory tree originating wherever you extracted the zip-file.

For such cases the FHS provides the /opt directory, where add-on packages may install all static files in their own subdirectory.1

Technically, even when using the /opt hierarchy, configuration files should actually still be located in /etc/opt/adempiere, and data and variable state files in /var/opt/adempiere. Executables should be placed in /opt/adempiere/bin. And a restriction exists that no files should exist outside the /opt, /var/opt, and /etc/opt hierarchies (except for those which must reside in specific locations to function properly).

But would strictly following the FHS standard really make sense?

Configuration Files

The rational for having all host-specific configuration files under a single directory is that users can easily predict their location. Hardcore Linux users much prefer tweaking settings in a configuration file by hand rather than being guided through a lengthy setup program.

But Adempiere does not expect anybody to modify its settings from outside and rather insists that RUN_setup.sh is used for that purpose. Programs under Linux expect that their configurations could have been changed any time, so they adjust themselves to the configured settings after those have been loaded and checked for sanity. Adempiere works the other way round: RUN_setup.sh checks the configuration parameters for sanity, adjusts all programs and libraries to the configured settings, and then saves those settings quasi as a saved-state file. When the programs are started, they load their last state from the configuration file and continue from there. Should you modify anything manually from outside of RUN_setup.sh, things will get seriously messed up.

In addition, the configuration files are all located near the executables and binaries where they are being used, which is not bad for testing and debugging.

Under these considerations, it probably makes sense to keep the configuration files where they are and not to move them to /etc/opt/adempiere.

But there is an issue with user-based configuration files for running the client, which are placed as visible files into the current working directory. These should be modified to be located in user's home directories as hidden files (filenames preceded with a .).

Executable Binaries

Having all executables in one directory makes it easy to include that directory in a user's path so that all commands for a particular package are always available.

In the case of Adempiere, there actually are no binaries but only Java classes which are called from shell scripts, and for ordinary users actually only one such script (RUN_Adempiere.sh) is required to start the client. And that would normally not be executed from a command line anyway, but rather from a menu on the desktop.

For administrators, although arguably it is sometimes difficult to understand why a particular script is to be found in ADEMPIERE_HOME, while another is in ADEMPIERE_HOME/utils, those are actually the only directories with interesting scripts to run. Furthermore, many of the scripts in the utils subdirectory actually require a certain structure of helper files and directory trees under them, which would be broken if they were to be moved to a separate bin directory.

Executables are thefore best left where they are.

Libraries and Resources

Libraries and resources are exactly the kind of files to be placed under /opt/adempiere, and the vendor is free to create any structure he wishes under his own subdirectory. So this is FHS compliant, and nothing needs to be changed.

Documentation

Adempiere mainly uses online documentation for users and a wiki for adminstrators and developers.

However, there is some documentation available in the source code which is not found in the binary distribution. Some of those files might be interesting for administrators or developers and should therefore be placed in /usr/share/doc/adempiere where they can easily be found.

Data and Variable State Files

Adempiere does not keep its own data files but rather stores all data in an external database such as Oracle or postgreSQL.

Log Files

Although the FHS states that no files should exist outside of the /opt, /var/opt, and /etc/opt hierarchies, it probably makes sense to cover log files with the “files which must reside in specific locations to function properly” exception.

Out of the box, Adempiere's log files are scattered over its subdirectories, often with duplicate and redundant information.

These log files can grow very big over time. If, as would be good practice, a separate partition is mounted on /opt/adempiere, that partion could easily get filled up with logs. It would be much better to use the operating system's logging facilities with all its advantages (for example, file rotation or remote logging) than clogging up the Adempiere partition.

Exceptional Files

Other files which would need to reside in specific locations to function properly would include ;/etc/rc.d/init.d/adempiere :An init script to start and stop the application server. ;/etc/sysconfig/adempiere :Configuration file for the init script. ;/etc/profile.d/adempiere.sh :A short script to set the ADEMPIERE_HOME variable system-wide for all users. ;/usr/share/applications/adempiere.desktop :A descriptive file to add a menu item for starting the client on the users' desktop. ;/var/log/adempiere :As previously explained, a central log file used by the system logger to collect and manage all logs in one place.

Such files are very specific to RedHat-like systems and are not included in the vanilla Adempiere distribution.

Running as Daemon

The standard Adempiere distribution comes with the RUN_Server2.sh and RUN_Server2Stop.sh commands to start respectively stop the application server.2

The scripts are designed to run in the foreground dumping log information to the console from which they were started. The administrator is supposed to follow the state of the server by examinig the log messages on the console. Thus the server would be started on one console and left running, and to stop it a new console would need to be opened from which the stop command would be initiated. The administrator would then have to switch back to the original console to verify from the log messages that the server has really stopped.

While such procedure is acceptable for development purposes, it definitely does not scale well for production environments.

Apart from being impractical, under Linux another issue arises that the server would be running with the privileges and limitations of the user who started it, which could be any user or even root, raising very valid security concerns.

It would be much better to have a designated adempiere user for no other purpose than running the server, being able to start and stop the server with service adempiere start or service adempiere stop like any other daemon, and configuring startup and shutdown behavior with chkconfig.

Desktop Integration

Any user who wants to run the server or client must have the ADEMPIERE_HOME environment variable set to the correct location. That means ADEMPIERE_HOME should be set system-wide on both server and client machines.

And for users who want to run the client, having an item in their desktop menu is surely more comfortable than having to open a console and typing $ADEMPIERE_HOME/RUN_Adempiere.sh.

Package Management

On RedHat-like systems, software installation, upgrading, and uninstallation should be managed by RPM. This ensures consistent deployment and allows for centralized management of clients and servers.

How the Adempiere Source-RPM works

Preparation

The Adempiere source code is downloaded from the Mercurial repository at SourceForge.net, and file formats (end-of line difference between Windows and Linux) and file permissions (scripts should be executable) are corrected.

The standard building behavior is modified so that build results are not e-mailed to anybody, building stops after compilation and does not proceed to actual file installation, and generation of the distributable zip-file (the binary package which is distributed by Adempiere) is suppressed.

If required, some quick fixes are applied to solve known issues which need to be addressed before compiling.

Then a copy of the whole source tree is made. The idea is that two different products should be compiled, one from the pristine source which was downloaded, and one from a source containing additions and patches for customizations. Help and support will generally only be available for the original product, not for any extended or customized versions. By having an RPM with the pristine code available, problems can be replicated in the original product before filing support requests or bug reports.

Standard patches (those distributed with this Source-RPM) are applied.

After that, the packager has the opportunity to add his own sources and patches for customizations or local extensions or bugfixes. (Although it would of course be much nicer if the packager would contribute his bugfixes back to the Adempiere project instead of just silently applying them to his local copy).

Building

First the orginal source is compiled to build the pristine package.

Then the customized source is compiled to build the server subpackage.

Any pdf files found in the original or customized source after compilation are extracted as documentation files.

If requested, the server is "pre-configured". All parameters which would normally be set after installation when executing RUN_setup.sh can already be configured now, resulting in a server package which can run out of the box when it is installed on the target machine. This makes the administrator's life very easy, but of course it also means that the resulting RPM is location-specific and can not be distributed publicly.

The server is then configured to send its log messages to the system logger rather than using local files.

The client code is extracted from the server package and modified so that the user's properties file is a hidden file in his home directory.

As a last step, the documentation for the Source-RPM (this text!) is generated.

Packaging

The build results are installed in a root file system as they should appear on the target system when they get installed.

In addition to the compiled code, some support files are installed for additonal Linux-specific functionality:

A file is dropped into /etc/profile.d to set the ADEMPIERE_HOME environment variable on a system-wide level.

An “init” script and its configuration file are installed to allow starting up or shutting down or otherwise controlling the server with the service adempiere start or service adempiere stop or chkconfig adempiere commands.

A desktop file is dropped into /usr/share/applications to include the Adempiere client in the users' desktop menu.

Documentation files are placed into the /usr/share/doc directory.

RPM packages are built from this root filesystem (one for client, one for server, one for the pristine product), which can be distributed and installed on other machines.

Installation on the Target System

When the Adempiere packages are installed on the target machines, their behavior differs depending on the kind of package (client, server, pristine) and the type of installation (installation, upgrade, removal).

Installation

StepClientServerPristine
pre-install---create adempiere user---
create user home directory
configure rsyslog
installinstall files
post-installcreate ADEMPIERE_HOME symbolic link---
---autostart server on system boot---

Upgrade

StepClientServerPristine
pre-install---create adempiere user---
create user home directory
configure rsyslog
installinstall new files
post-installcreate ADEMPIERE_HOME symbolic link---
---autostart server on system boot---
pre-uninstall---
uninstallremove old files
post-uninstall---restart server---

Removal

StepClientServerPristine
pre-uninstall---stop server---
unconfigure autostart of server on system boot if no other server packages are installed
remove ADEMPIERE_HOME symbolic link if it points to this installation
uninstallremove old files
post-uninstallremove installation directory
unconfigure rsyslog if no more server installations exist
unconfigure system-wide setting of ADEMPIERE_HOME if no more server or client installations exist
remove desktop menu entry if no more server or client installations exist
remove ADEMPIERE_HOME symbolic link if no more server or client installations exist
remove user home directory and documentation if no other installations exist
create ADEMPIERE_HOME symbolic link to newest server or client if any server or client installations exist


[1] Which means that according to the FHS, Adempiere should always be installed in /opt/adempiere.

[2] The 2 is presumabely a remnant from the days before Adempiere

forked from Compiere, where these scripts where used to control the new version 2 server, as opposed to RUN_Server.sh and RUN_ServerStop.sh controlling

the old version 1 server, which has since been lost.

Preparing the Package Building Environment

Required Development Tools

Install the tools required for building the Adempiere RPM. (This needs to be done as root).

# yum install rpm-build rpmdevtools gnupg mercurial java-1.6.0-openjdk-devel desktop-file-utils docbook5-style-xsl libxslt fop

RPM Build Tree

Create the RPM build tree in your home directory.

$ rpmdev-setuptree

This command creates the following directory tree required by rpmbuild and configures your build settings in ~/.rpmmacros

rpmbuild
+-- BUILD
+-- RPMS
+-- SOURCES
+-- SPECS
+-- SRPMS
			

You can move the generated rpmbuild directory to any place you like, but then you must adjust the %_topdir setting in ~/.rpmmacros to point to that location.

Digital Signature

For security reasons, the packages you build should be digitally signed. The digital signature allows users to verify that the package has been built by you, a trusted source, and has not been tampered with since then.

First, generate a public/private key pair with the gpg --gen-key command:

<code class="prompt">$ </code><span class="command"><strong>gpg --gen-key</strong></span>
gpg (GnuPG) 1.4.10; Copyright (C) 2008 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
	(1) RSA and RSA (default)
	(2) DSA and Elgamal
	(3) DSA (sign only)
	(4) RSA (sign only)
Your selection? <strong><code>1</code></strong>
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) <strong><code>2048</code></strong>
Requested keysize is 2048 bits
Please specify how long the key should be valid.
				0 = key does not expire
			<n>  = key expires in n days
			<n>w = key expires in n weeks
			<n>m = key expires in n months
			<n>y = key expires in n years
Key is valid for? (0) <strong><code>0</code></strong>
Key does not expire at all
Is this correct? (y/N) <strong><code>y</code></strong>

You need a user ID to identify your key; the software constructs the user
ID from the Real Name, Comment and Email Address in this form:
		"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

Real name: <strong><code>www.mycompany.com</code></strong>
Email address: <strong><code>devnull@mycompany.com</code></strong>
Comment: <strong><code>rpm signature</code></strong>

You selected this USER-ID:
		"www.mycompany.com (rpm signature) <devnull@mycompany.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? <strong><code>O</code></strong>
You need a Passphrase to protect your secret key.

Enter passphrase: <strong><code>secret passphrase</code></strong>
Repeat passphrase: <strong><code>secret passphrase</code></strong>

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
.+++++
........+++++
..+++++
gpg: key F9D8EE90 marked as ultimately trusted
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, classic trust model
gpg: depth: 0  valid:   2  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 2u
pub   2048R/F9D8EE90 2010-10-17
			Key fingerprint = 983D 704A 024A 861F 9FCB  5CA2 4875 7B66 F9D8 EE90
uid   www.mycompany.com (rpm signature) <devnull@mycompany.com>
sub   2048R/496CD9ED 2010-10-17
			

Next, the public key needs to be extracted:

$ gpg --export --armor www.mycompany.com > MYCOMPANY-RPM-GPG-KEY

This file needs to be publicly distributed so that users can verify the signature of the RPM packages which you built and signed.

Finally, you need to configure rpmbuild to use the signature you just created by adding the %_signature and %_gpg_name macros to the .rpmmacros file in your home directory. The file should now look something like this:

%_topdir /home/<em>username</em>/rpmbuild %_signature gpg %_gpg_name www.mycompany.com (rpm signature) <devnull@mycompany.com> … …

Using the Adempiere SRPM

Installing the Source-RPM

Once your package building environment has been set up, you can download and unpack the Adempiere source RPM:

The source files will have been installed in ~/rpmbuild/SOURCES, and the specification file ("Spec" file) in ~/rpmbuild/SPECS/adempiere.spec

Configuring the Build Process

Build behavior is controlled by various parameters which are set at the beginning of the Spec File. See Appendix A for a detailed description.

Adding Customizations

Additional sources and patches can be added to the SOURCES directory to apply extensions and customizations to the Adempiere source code.

As new files are added, the SOURCES directory quickly gets very messy. For this reason, the files distributed with the Source-RPM are prefixed with sXXX_ (for sources) and pXXX_ (for patches), where XXX corresponds to the patch or source number in the Spec File. Users are encouraged to name their sources and patches following the same naming scheme.

Sources and patches must be listed in the Spec File using the Source<number>: filename and Patch<number>: filename pragmas.

Source and patch numbers 0-99 are reserved for the maintainer of the Adempiere source RPM, so you may add source files and patches starting with number 100.

…
…
# Sources
# -------

# standard sources
…
…

# your custom sources come here
# (start with number 100)
Source100:	s100_MMyModel.java
Source101:	s101_myScript.sh


# Patches
# -------

# standard patches
…
…

# your custom patches come here
# (start with number 100)
Patch100:	p100_myPatch1.patch
Patch101:	p101_myPatch2.patch
…
…
			

The sources and patches thus defined in the Spec File's preamble must be installed or applied in the %prep section, which is usually done with the install shell command and %patch macro.

… … %prep … … cd $rpmBuildDir/source/custom

  1. standard patches
  2. ----------------

… …

  1. install your sources here
  2. -------------------------

install -pD -m0644 %{SOURCE100} base/src/org/adempiere/model/MMyModel.java install -pD -m0755 %{SOURCE101} utils/myScript.sh

  1. apply your patches here
  2. -----------------------

%patch -P100 -p1 %patch -P101 -p1 … …

The install command works like cp, with the addition that it will create all leading components in the path to the target file if they are missing (-D option), preserve the source file's timestamp (-p option), and set the permission mode of the target file (-m option).

The %patch macro invokes the patch command to apply patches to the source. The patch file number is specified with the -P (upper case P) option, and the -p (lower case p) option tells the patch command how many leading slashes and directories are to be omitted from filenames in the patch file. This will be explained in the next chapter.

For building Adempiere packages, the %patch macro has been extended to accept following additional parameters:

-F fuzz factor

Use the given fuzz factor

-d directory

change to directory before doing anything

-a filename

Apply patch only if filename exists.

If filename starts with a /, it describes an absolute path, otherwise it is relative to RPM_BUILD_DIR.

-x regular expression

requires -a.

Apply patch only if regular expression exists in filename.

If regular expression starts with a !, apply patch only if regular expression does not exist in filename.

Building the RPM packages

Packages are generated using the rpmbuild --sign -b… /path/to/adempiere.spec command, where the --sign option will sign the package using the gpg-signature we created earlier, and the stage up to which the packages are built is defined with the -b… switch:

-bp

build up to "prep" phase only, which means downloading the source and applying patches.

-bc

build up to "build" phase only, which means compiling the source.

-bi

build up to "install" phase only, the resulting files are installed in a directory structure as they would be on the target machine.

-bb

build binary packages (adempiere-….noarch.rpm, adempiere-server-….noarch.rpm, adempiere-client-….noarch.rpm).

-bs

build source package (adempiere-….srpm).

-ba

build all packages (both binary and source).

rpmbuild --sign -ba ~/rpmbuild/SPECS/adempiere.spec

The resulting RPM packages can be found in ~/rpmbuild/RPMS/noarch, and the source RPM in ~/rpmbuild/SRPMS.

When using --sign, rpmbuild will prompt you for a passphrase. Enter the same phrase which was used when the gpg key was generated.

Creating Patches

Patches are text files generated by the diff tool which compares files or directories and records the differences in a certain format. Those differences can then be re-applied to the original source using patch.

To create a patch file, you therefore need the original source and a copy. You can program your changes by editing, adding, or deleting files in the copy. Then use diff to compare the original source with the changes you made in the copy and record those changes in a patch file.

Normally you would want to add your changes to source files to which all previous patches have already been applied. You can obtain the patched source code by using the -bp option with rpmbuild, which downloads the code and applies all patches.

$ rpmbuild -bp ~/rpmbuild/SPECS/adempiere.spec

Then you can copy the source directory to new locations, one ending on .orig and the other ending on .new.

$ cp -r ~/rpmbuild/BUILD/adempiere-…/source/custom adempiere.orig

$ cp -r ~/rpmbuild/BUILD/adempiere-…/source/custom adempiere.new

Start hacking your heart out and make any changes you want in adempiere.new. 3 When you are done, go back to the parent directory and run diff to compare adempiere.orig with adempiere.new

$ diff -durNbB adempiere.orig adempiere.new > myPatch.patch

These are the options used in above diff command: ;-d :forces diff to search for smaller sets of changes than it normally would ;-u :generates unified output format, which is required by patch ;-r :recursively compare subdirectories ;-N :if a file is only found in one directory, treat it as present but empty in the other directory ;-b :ignores changes only in whitespace ;-B :ignores changes only in blank lines

The resulting patch file can be added to the SOURCES directory and listed in the Spec File as previously explained.

Note that when the patch file was created, you were in the parent directory which contains the source directory tree. But when the patch is being applied by rpmbuild, you will actually be inside the source directory tree. Therefore, the first directory component of filenames generated by diff must be ignored when running the patch command. This is achieved by passing -p1 to patch.



[3]

Be careful not to actually compile the code! You only want to save changes made to the source code. But if you compile the code, many new files will be created which do not exist in the original source, and diff would regard all of those files as additions you made to the source.

Distributing RPM Packages

Installing with RPM

The binary packages generated by rpmbuild can now be installed on target machines using the rpm command. Before doing so, the public GPG key must be loaded into the rpm database. Both must be done as root.

# rpm --import MYCOMPANY-RPM-GPG-KEY

# rpm --ivH adempiere-server-….noarch.rpm

or

# rpm --ivH adempiere-client-….noarch.rpm

But of course it would be much more efficient to have a central repository from which client machines can use tools like yum for automatic installation and upgrading.

Distributing the server package through a central yum repository might not be such a good idea, especially if it was built using pre-configured settings. That would enable anybody to download the server package and access critical information such us database passwords. And anyway, servers should always be upgraded manually.

Creating a YUM Repository

A web server is needed to distribute packages from a yum repository. The httpd server can be installed using yum, and for our purposes it can be started out of the box without having to configure it. Below commands have to be run as root.

# yum install httpd createrepo

# service httpd start

Create an adempiere directory under /var/www/html, and copy the GPG public key and the RPM packages to be distributed into it. Make sure that everybody has read permissions for those files.

$ mkdir -p /var/www/html/adempiere

$ cp MYCOMPANY-RPM-GPG-KEY /var/www/html/adempiere/

$ cp adempiere-….noarch.rpm /var/www/html/adempiere/

$ chmod o+x /var/www/html/adempiere

$ chmod -R o+r /var/www/html/adempiere

Create the repository by executing createrepo . (the last dot is important!) inside /var/www/html/adempiere

$ cd /var/www/html/adempiere

$ createrepo .

Your yum repository is now up and running and can be accessed from client machines.

For distributing upgrades, simply drop the new RPM files into the repository and run createrepo . again.

Installing with YUM

Before being able to use your new Adempiere repository, client machines must be aware that it exists. As root, create a file adempiere.repo in /etc/yum.repos.d with following contents:

[adempiere]
name=Adempiere
baseurl=http://<em>address.of.your.web.server</em>/adempiere
enabled=1
			

And of course the public key for signature verification must be imported into the RPM database (needs to be done as root):

Now yum can be used to install, upgrade, or remove your Adempiere packages:

# yum install adempiere-client

or

# yum upgrade adempiere-client

or

# yum remove adempiere-client

If the client machine has daily run of yum enabled, it will automatically upgrade to the newest package published in the adempiere repository.

Configuration Parameters

General Settings

name

The name of the resulting package

default: adempiere

example: %global name adempiere

company

The name of the packager (your company)

default: custom

example: %global company Some Company, Inc.

Compile Settings

applyQuickFix

whether quick fixes should be applied

Sometimes the source does not compile and some quick fixes or workarounds must be applied. The script SOURCES/s041_quickFix.sh is called to apply such workarounds.

values: 0 = do not apply quick Fixes1 = apply quick Fixes

default: 1

example: %global applyQuickFix 1

Version Settings

version

the Adempiere version to download and compile

values: current, head = download newest files of the current Adempiere versionrelease = download original files of the current Adempiere version as it was originally releasedprevious = download newest files of the previous Adempiere version (just before it changed to the current version)version = specific Adempiere version to download

Note that versions are relative to the current branch (see hgBranch) in the Mercurial repository.

When comparing the Adempiere version with tags in the Mercurial repository, both are converted to lower-case, all non-alphanumeric characters are stripped, and any "adempiere" or "release" prepending the version number are removed. Thus release-2.5.3b-initial becomes 253binitial, adempiere340-trunk-frozen becomes 340trunkfrozen, and Adempiere360LTS becomes 360lts.

default: current

example: %global version 360lts

Alternatively, it is possible to directly specify a Mercurial revision. In this case it is assumed that you know what you are doing, and no further sanity checks are performed. This also overrides any settings in the hgBranch parameter.

tip = download the current Mercurial tiphgrevision = download specific Mercurial revision

Prefixing the version information with hg will prevent such transformation and it will be treated as literal string.

Mercurial Settings

Mercurial is needed to download the source code as well as gather information on the version.

hgOptions

general options to use with the hg command

default: --noninteractive --encoding utf8

example: %global hgOptions --quiet --noninteractive --encoding utf8

hgRepository

URL of the source code repository

default: http://adempiere.hg.sourceforge.net:8000/hgroot/adempiere/adempiere

example: %global hgRepository http://adempiere.hg.sourceforge.net/hgroot/adempiere/adempiere

hgBranch

Named branch in the source code repository

values: master = the main stable branch containing official releasesdevelopment = the main development branch with newest features and bugfixesrelease/name = temporary branch with "frozen" code of the next release candidatehotfix/name = temporary branch for fixing bugs found in live production version of master branchname = any other named branch

default: master

example: %global hgBranch master

hgVersionFile

the file from which to read version information

default: base/src/org/compiere/Adempiere.java

example: %global hgVersionFile base/src/org/compiere/Adempiere.java

Adempiere User Settings

OS level environment settings for the 'adempiere' user

userDir

the home directory of the adempiere user

(this will be the parent directory of ADEMPIERE_HOME)

default: /opt/adempiere

example: %global userDir /opt/adempiere

adempiereHome

the location of ADEMPIERE_HOME

If starting with a /, it is the absolute path to ADEMPIERE_HOME. Otherwise it will be a subdirectory under %{userDir}.

Note that %{adempiereHome} will not actually be a directory, but a symbolic link.

The package will be installed under %{userDir} with version information, for example /opt/adempiere/adempiere360lts for the pristine package/opt/adempiere/server360lts for the server package/opt/adempiere/client360lts for the client package

Then a symbolic link will be created from the package directory to %{adempiereHome}, for example ln -s /opt/adempiere/server360lts /opt/adempiere/adempiere

This way it is possible to have different packages and versions installed on the same machine, and by changing the symbolic link you can choose which version to run.

default: adempiere

example: %global adempiereHome /opt/adempiere/adempiere

userName

the name of the adempiere user

default: adempiere

example: %global userName adempiere

userID

the user ID number for the adempiere user

If the requested user ID is already taken, the next available system ID will be used.

values: 200 <= x < 500

default: 215

example: %global userID 215

groupName

the adempiere user's private group name

default: same as %{userName}

example: %global groupName adempiere

groupID

the primary group ID number for the adempiere user

If the requested group ID is already taken, the next available system ID will be used.

values: 200 <= x < 500

default: 215

example: %global groupID 215

Pristine Package Settings

The pristine package is the release as distributed by Adempiere without any extensions or patches. It can be used for testing before filing support requests or bug reports.

It contains both server and client, and it is not pre-configured.

buildPristine

whether to build the pristine package

values: 0 = do not build the pristine package1 = build the pristine package

default: 0

example: %global buildPristine 0

Client Package Settings

The client package is installed on remote machines.

It includes desktop menu entries for connection to the server.

The client package is a custom release to which patches and extensions are applied.

buildClient

whether to build the client package

values: 0 = do not build the client package1 = build the client package

default: 1

example: %global buildClient 1

Server Package Settings

The server package is the live server. It also includes its own client.

The server package is a custom release to which patches and extensions are applied.

buildServer

whether to build the server package

values: 0 = do not build the server package1 = build the server package

default: 1

example: %global buildServer 1

preconfigureServer

whether to pre-configure the server so that it will run out of the box without executing ./RUN_Setup.sh

values: 0 = do not pre-configure the server package1 = pre-configure the server package

default: 0

example: %global preconfigureServer 0

Server Configuration Parameters

These parameters are used for pre-configuring the server

Certificate Configuration

serverFQDN

The fully qualified domain name of the server

This string is used to identify the application server as well generate default entries for mail and database server.

default: localhost.localdomain

example: %global serverFQDN myAppServer.mydomain.com

keystore

the server's keystore file (relative to ADEMPIERE_HOME)

default: keystore/myKeystore

example: %global keystore keystore/myKeystore

keystorePass

the password for the server's keystore

default: adempiere

example: %global keystorePass adempiere

keystoreCN

The CN (common name) component of the DN (distinguished name) for the server's keystore.

default: name portion of serverFQDN

example: %global keystoreCN myAppServer

keystoreOU

The OU (organizational unit) component of the DN (distinguished name) for the server's keystore.

default: name of currently logged-in user

example: %global keystoreOU myName

keystoreO

The O (organization) component of the DN (distinguished name) for the server's keystore.

default: AdempiereUser

example: %global keystoreO AdempiereUser

keystoreL

The L (location) component of the DN (distinguished name) for the server's keystore.

default: myTown

example: %global keystoreL myTown

keystoreST

The ST (state) component of the DN (distinguished name) for the server's keystore.

default: myState

example: %global keystoreST myState

keystoreC

The C (country) component of the DN (distinguished name) for the server's keystore.

default: country from system's LANG setting in /etc/sysconfig/i18n

example: %global keystoreC US

keystoreCodeAlias

the certificate alias for code signing on the server

Note that although this is a configurable parameter, the alias 'adempiere' is hardcoded in some source files, so it might be a bad idea to change it.

default: adempiere

example: %global keystoreCodeAlias adempiere

keystoreWebAlias

the certificate alias for secure web connections to the server

Note that although this is a configurable parameter, the alias 'adempiere' is hardcoded in some source files, so it might be a bad idea to change it.

default: adempiere

example: %global keystoreWebAlias adempiere

Java Configuration

javaType

the Java type installed on the server

Note that ibm is not implemented yet, and there are still some issues with openJDK.

values: sun, mac, ibm, OpenJDK

default: OpenJDK

example: %global javaType OpenJDK

javaHome

the Java path on the server

default: /usr/lib/jvm/java-openjdk

example: %global javaHome /usr/lib/jvm/java-openjdk

javaOptions

options with which to start the virtual machine under which Adempiere is run

(see Java documentation)

default: -Xms64M -Xmx512M

example: %global javaOptions -Xms64M -Xmx512M

Application Server Configuration

serverType

the type of application server

values: jboss, glassfish

default: jboss

example: %global serverType jboss

deployDir

the application server deployment directory (relative to ADEMPIERE_HOME)

default: jboss/server/adempiere/deploy for JBossglassfish/glassfish/domains/domain1 for Glassfish

example: %global deployDir jboss/server/adempiere/deploy

jnpPort

the JNP port (whatever that is)

default: 1099 for JBoss3700 for Glassfish

example: %global jnpPort 1099

webPort

the TCP port to be used by the application server for HTTP

default: 8888

example: %global webPort 8888

sslPort

the TCP port to be used by the application server for HTTPS

default: 8443

example: %global sslPort 8443

logFacility

which facility to use for the system logger

values: local0 … local7

default: local1

example: %global logFacility local1

logLevel

the minimum severity level for messages to be logged

values: DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY

default: INFO

example: %global logLevel INFO

Database Configuration

dbServer

the name of the database server

default: name portion of %{serverFQDN} (assuming that Adempiere is installed on the same machine as the database)

example: %global dbServer myDatabaseServer

dbType

the type of database (database vendor)

values: oracle, oracleXE, postgresql

default: postgresql

example: %global dbType postgresql

dbPort

the database port

default: 5432 for PostgreSQL1521 for Oracle

example: %global dbPort 1521

dbName

the name of the database

default: adempiere for PostgreSQLorcl for Oraclexe for OracleXE

example: %global dbName adempiere

dbUrl

the url for the jdbc driver to connect to the database

default: jdbc:postgresql://%{dbServer}:%{dbPort}/%{dbName} for PostgreSQLjdbc:oracle:thin:@//%{dbServer}:%{dbPort}/%{dbName} for Oracle

example: %global dbUrl jdbc:postgresql://myDatabaseServer:5432/adempiere

dbUser

the name of the adempiere database user

default: adempiere

example: %global dbUser adempiere

dbPassword

the password of the adempiere database user

default: adempiere

example: %global dbPassword adempiere

dbSystemUser

the user name of the database system administrator

default: postgres for PostgreSQLsystem for Oracle

example: %global dbSystemUser postgres

dbSystemPassword

the password of the database system administrator

default: postgres for PostgreSQLmanager for Oracle

example: %global dbSystemPassword postgres

oracleHome

When using Oracle, the adempiere user needs to have access to the Oracle client on the local machine.

This is the ORACLE_HOME environment variable pointing to the oracle product directory.

To keep the adempiere packages independent of the installed Oracle version, if the Oracle product directory contains a version in its name, it is recommended to create symbolic link from the Oracle product directory to a version-free name such as /opt/oracle/oracle at the time of Oracle installation.

This can be done with the command

# ln -s /opt/oracle/product/10.2.01 /opt/oracle/oracle

default: /opt/oracle/oracle

example: %global oracleHome /opt/oracle/product/10.2.01

oracleTnsAdmin

When using Oracle, the adempiere user needs to have access to the Oracle client on the local machine.

This is the TNS_ADMIN environment variable pointing to the location where Oracle Net Services look for configuration files.

default: %{oracleHome}/network/admin

example: %global oracleTnsAdmin /opt/oracle/product/10.2.01/network/admin

FTP Configuration

ftpServer

name of the FTP server

default: name portion of %{serverFQDN}

example: %global ftpServer myAppServer

ftpPrefix

the FTP prefix to use

(no idea what this does)

default: my

example: %global ftpPrefix my

ftpUser

the FTP user

default: anonymous

example: %global ftpUser anonymous

ftpPassword

the FTP user's password

default: user@host.com

example: %global ftpPassword user@host.com

E-Mail Configuration

mailServer

the mail server to use

default: mailserver.(domain portion of %{serverFQDN})

example: %global mailServer mailserver.mydomain.com

mailAddress

the default administrative mail address to use

It can be overwritten on client level

default: adempiere@(domain portion of %{serverFQDN})

example: %global mailAddress adempiere@mydomain.com

mailUser

the user of the default mail account

default: adempiere

example: %global mailUser adempiere

mailPassword

the password of the default mail account

default: adempiere

example: %global mailPassword adempiere

Corporate Format Settings

Some sites may want to enforce their own corporate formats, i.e. no matter what locale the user is working in or what language a business partner has defined, always the same decimal point, date format, and paper size are used, regardless of what the locale conventions are.

(And the locale conventions are often wrong in Java, anyway).

This is technically a patch, but as the target file may change frequently, it would be very cumbersome to always keep the patch file up to date.

It has therefore been incorporated as a script in the %prep section.

useCorporateFormat

whether to apply the corporate format patch

Note that this changes the locale conventions for the complete installation and thus affects all clients.

values: 0 = do not use corporate formats1 = use corporate formats

default: 0

example: %global useCorporateFormat 0

formatDecimal

whether to use a point as decimal separator

values: 0 = use a comma as decimal separator1 = use a point as decimal separator

default: 1

example: %global formatDecimal 1

formatDate

the date format to use

The formats are probably described somewhere in Java documentation. Have a look at looks/src/org/compiere/util/Language.java for examples.

default: yyyy-MM-dd

example: %global formatDate yyyy-MM-dd

formatPaper

the paper size to use.

The formats are probably described somewhere in Java documentation. Have a look at looks/src/org/compiere/util/Language.java for examples.

values: ISO.A4, NA.LETTER

default: ISO.A4

example: %global formatPaper ISO.A4