Depending on the complexity of a component there might be very little to alter or there might be lots of changes required to move from the old LCFG build tools to the new system. The intention is that in the majority of cases the work required will be minimal.
Throughout these examples the presumption is that you have the following packages installed and the versions are the same or newer:
perl-LCFG-Build-Tools-0.0.38-1/noarch perl-LCFG-Build-PkgSpec-0.0.23-1/noarch perl-LCFG-Build-VCS-0.0.21-1/noarch
You can download these as RPMs from the LCFG website (listed in the "Development Packages" section). You can also install them as standard Perl packages by fetching them from CPAN.
Here is the really good news, if your component looks like that described in the "Anatomy of a Component Package" page then there really is very little to do. It boils down to:
$ cd lcfg-foo $ lcfg-cfg2meta $ cvs add lcfg.yml [edit specfile with your favourite editor, see below] [edit ChangeLog with your favourite editor] $ cvs commit -m "Converted to new build tools" $ lcfg-reltool microversion $ lcfg-reltool devrpm
That is it! You've got yourself an RPM generated with the new build tools system. Good examples of this are the file and auth components.
It is not apparent from this simple example but the package will now be built using a tool called CMake. In this simple case all the necessary files to run CMake are generated just before the source is packed into the gzipped tar file. To actually use CMake to build the RPM you need to make some small modifications to the specfile.
Firstly, you should really add a build-requirement on the cmake package. In the future we intend to build packages inside a chroot using a tool such as mock. The chroot will not have CMake installed by default so you must specify that it is required. You want a line like:
BuildRequires: cmake >= 2.6.0, /etc/rpm/macros.cmake, lsb
Secondly, you need to modify the
%build
section to look like:
%build %cmake -DPERL_INSTALLDIRS:STRING=vendor make
Here we are relying on a macro to hide all the magic incantantations
necessary to drive CMake properly. That is why there is a build
requirement on the file /etc/rpm/macros.cmake
, it is not
essential but it makes things a lot simpler.
Thirdly, you need to alter the
%install
section to pass the DESTDIR
option
rather than PREFIX
. It should now look something
like:
%install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT %{_fixperms} $RPM_BUILD_ROOT/*
Finally, if you want the component changelog to be
added to the specfile you now need to add a %changelog
section. The new build tools will not just blindly append it to the
end of the specfile for you. You need this:
%changelog @LCFG_CHANGELOG@
A complete example which shows the various changes which are required is the specfile for the LCFG client component.
It is too good to be true, right? There's always a catch isn't there? As with everything, "it depends".
You need to check through all your files for macros
(i.e. @FOO@
) and ensure they are all supported by the new
build tools. A full list of macros along
with descriptions and values is available. If you've been fairly
conservative with your macro usage then you'll be fine, if you have
had some extra variables defined in your config.mk
you
can either hardwire the values throughout your files or breakout the
CMake, see below for more details.
You also need to check your specfile
, this is the
place where problems are most likely to strike. Primarily this is
because the list of macros available for filling-out the template has
been restricted to aid platform-independence. To help with this
process, when the specfile template is completed the tools print out a
list of any unknown macros to STDERR. Part of the output will be
something like:
LCFG: Successfully exported the source tree. Unknown macro FOO Unknown macro BAR Unknown macro BAZ LCFG: Successfully translated template files. LCFG: Successfully generated source tar file. LCFG: Successfully generated metadata files for RPM
You can check the macros being used by a particular component with the "checkmacros" command. For example with the "boot" component:
$ lcfg-reltool checkmacros --dir ~/dice/lcfg-boot/ Use of compile-time-only macro, EGREP, at: boot.cin:131 boot.cin:146 boot.cin:152 boot.cin:186 boot.cin:192 boot.cin:224 boot.cin:330 boot.cin:349 Use of compile-time-only macro, LCFGOS, at: boot.cin:33 boot.cin:34 boot.cin:264 boot.cin:265 Use of compile-time-only macro, MSG, at: waitonboot.cin:6 boot.cin:11 boot.def.cin:7 Use of compile-time-only macro, SED, at: boot.cin:159 boot.cin:202 boot.cin:285 Use of compile-time-only macro, SHELL, at: waitonboot.cin:1 boot.cin:1 Use of compile-time-only macro, SORT, at: boot.cin:157 boot.cin:197
Note that none of the warnings can be truly considered an error.
Even a message about an unknown macro is fine if you
add the specification for that variable to a local
CMakeLists.txt
file for that component. In general it has
to be left up to the software author to interpret the true importance
of a particular warning.
The warnings are listed in order of importance:
In each instance you will get a list of filenames and the line numbers of where the macros are used. The special case in which all of these warnings (except that for "deprecated macro") should be considered a fatal error is with the RPM specfile. By design, locally defined macros and those which are platform specific or compile-time only cannot be used in the specfile.
You might also need to replace the "Copyright" field name with "License", the field name was changed some time ago but the old build tools silently rewrote the specfile.
When you use lcfg-reltool
to execute commands such as
pack, devpack, srpm, rpm and
devrpm just prior to packing the source code into a gzipped
tarfile a couple of CMake files are generated and added to the source
directory. If you unpack the generated tar file you will find that
there are extra files named CMakeLists.txt
and
lcfg.cmake
. The first file is what drives CMake and, yes,
it really does have to be named like that... The second file contains
all the LCFG variables and macros you might need to build your
package. Some of it is standard and some of it is generated
differently for each package. You can view examples of the two files
for the file component: CMakeLists.txt
and lcfg.cmake.
Often a component comes with other scripts and Perl libraries which
need installing. Or maybe they have some extra templates and
configuration files which need to be put into special locations. At
this point you need to venture into the world of CMake. To make it
easier a set of CMake macros have been provided to make this as easy
as possible. The LCFG release tool is designed to only generate a
CMakeLists.txt
file if one does not already exist, it
will, however, always generate the lcfg.cmake
file. Examples below show how to take advantage of this behaviour.
Taking lcfg-sysinfo
as an example of a component which ships a Perl module. We need to
create a CMakeLists.txt
file which looks like:
cmake_minimum_required(VERSION 2.6) project (lcfg-sysinfo) include(lcfg.cmake) lcfg_add_component(${LCFG_NAME}) lcfg_add_perl_tree(lib)
Everything except the last line is standard and what would be
generated in the simple case. Here the lcfg_add_perl_tree
macro has been used, this will search for any files matching
"*.pm" inside the specified directory and install them into
the correct location. It will strip any perl docs (pod), install them
into /usr/lib/lcfg/doc/pod/
and also generate manual
pages which get put into section 3.
In many cases a component with Perl modules has them stored in the top-level directory rather than in lib (or something similar). There are two ways to work with this situation. The best option is to create a lib directory (or perllibs, or whatever you want it named) and move the Perl module tree into there. The second option is to manually add each Perl module using the lcfg_add_perl_module macro. An example would be to do something like:
lcfg_add_perl_module(LCFG/Foo.pm LCFG::Foo) lcfg_add_perl_module(LCFG/Foo/Bar.pm LCFG::Foo::Bar)
Note that in this case you need to specify the relative path to the module and the Perl name of the module.
The other common scenario is that a component needs to ship scripts
which are to be installed into /usr/bin
or
/usr/sbin
. Again there are some CMake macros to help. The
lcfg-authorize
component is a simple example.
cmake_minimum_required(VERSION 2.6) project (lcfg-authorize) include(lcfg.cmake) lcfg_add_component(${LCFG_NAME}) lcfg_add_perl_tree(lib) lcfg_add_bin(bin/lcfgcap podstrip)
The work is done here with the lcfg_add_bin macro. There
is a similar macro named lcfg_add_sbin for installing into
/usr/sbin
. If you give a second argument of
"podstrip" any perl documentation will be extracted from the
script and installed into /usr/lib/lcfg/doc/pod/
. Manual
pages will also be generated and put into section 1 for
lcfg_add_bin and section 8 for lcfg_add_sbin.
Previously there was a checkcommitted
target which
could be added to the uptodate
target in a Makefile to
ensure all files are committed into the revision-control system before
making a new release. To achieve the same thing you will need to set
an extra option in the new LCFG build tools metadata file. In the
vcs
section you need to add the
checkcommitted
key and set it to true. It should look
something like this:
vcs: checkcommitted: 1 genchangelog: 1 logname: Changes type: CVS
Previously there was a cvschangelog
target which could
be added to the changelog
target in a Makefile to
generate the project change log file from the version-control system
log. To achieve the same thing you will need to set an extra option in
the new LCFG build tools metadata file. In the vcs
section you need to add the genchangelog
key and set it
to true. It should look something like the example above.