Waf: Difference between revisions

From SambaWiki
No edit summary
No edit summary
Line 1: Line 1:
= Experiments with using waf to build Samba =
= Using waf to build Samba =


As of March 2010, the waf build of Samba4 is now nearly complete. We
As I mentioned previously, I've been experimenting with using waf for
have waf build rules for libreplace, talloc, tdb, tevent, ldb and
Samba builds. So far it looks very promising. The waf maintainer is
Samba4. Kai is working on the waf build for Samba3.
being extremely helpful.


The waf builds are set up so builds appear in bin/ (so if building in
I've added 'wscript' waf rules for libreplace, tevent, tdb, talloc and
ldb. Configure, build, install all work. The build in source4 partly works.

I've set it up so builds appear in bin/ (so if building in
source4/lib/ldb then you get source4/lib/ldb/bin/ldbadd for
source4/lib/ldb then you get source4/lib/ldb/bin/ldbadd for
example). This keeps the current workflow we use in Samba development.
example). This is consistent with the current workflow we use in Samba
development.


rpath is used so the binaries can be run directly (so no stuffing
Where supported, rpath is used so the binaries can be run directly
without the need for LD_LIBRARY_PATH. If rpath is not supported then
about with LD_LIBRARY_PATH etc for gdb, valgrind and other testing)
LD_LIBRARY_PATH is automatically set for running the testsuites.


all built files (object, libs, binaries) are in bin. The source tree
All built files (object, libs, binaries) are in bin. The source tree
is never modified. If you do "rm -rf bin" then you're back to a
is never modified (with one minor exception for gen_ndr, as described
pristine tree.
below). If you do "rm -rf bin" then you're back to a pristine tree.

I've also written a script to auto-convert our existing config.mk
files for Samba4 to wscript_build scripts. This would allow us to run
the two build systems in parallel with very little pain, as you run
one script to re-generate all the waf build scripts.

The full Samba4 build is not working yet. I still have quite a bit to
do on the rules for pidl, asn1, errtable etc, plus rules for how we
will handle library dependencies.


waf is certainly fast. It uses full content hashing for dependencies,
waf is certainly fast. It uses full content hashing for dependencies,
but so far that hasn't been a problem. It also has a 'wafcache' which
but still manages to run quickly. It also has a 'wafcache' which is a
is a ccache like system, but that applies to all builds, so it will
ccache like system, but that applies to all builds, so it will safely
safely cache pidl, asn1, libraries, configure checks etc.
cache pidl, asn1, libraries, configure checks etc.

The main thing I've learned from trying this is that the build rules
for Samba4 are very complex, and do not lend themselves to a simple
representation. We have 485 build targets in the Samba4 tree
(ie. subsystems, modules, binaries, libraries etc).


== Getting the code ==
== Getting the code ==
Line 53: Line 38:
== Trying it out ==
== Trying it out ==


There are two ways to use the waf build. You can use ./autogen-waf.sh
This is highly experimental at the moment, but if you do want to give
followed by ./configure and make as usual, or you can directly call
it a go then try this:
waf.

If you directly call waf then you get some nice additional features,
such as a progress bar with 'waf -p' and the ability to specify which
tests to run in the testsuite. To run waf directly do this:


* setup your PATH to point at the buildtools/ directory in the root of the Samba sources
* setup your PATH to point at the buildtools/ directory in the root of the Samba sources
Line 60: Line 50:
export PATH=$HOME/samba-waf/buildtools:$PATH
export PATH=$HOME/samba-waf/buildtools:$PATH


* don't install waf on your system, instead use the one in buildtools/. This ensures we are all always using the same version.
* don't install waf on your system, instead use the one in
buildtools/. This ensures we are all always using the same version.


* now try one of the trees that have been converted to waf. For example, to try the tdb tree do this:
* now try one of the trees that have been converted to waf. For
example, to try the tdb tree do this:


cd lib/tdb
cd lib/tdb
waf configure --enable-developer --prefix=$HOME/testprefix
waf configure --enable-developer --prefix=$HOME/testprefix
waf
waf -p

* If you are installing to a place that is not in your system library path, then you might like to use --enable-rpath

waf configure --enable-developer --prefix=$HOME/testprefix --enable-rpath


* that will configure tdb and build the binaries in lib/tdb/bin/. To install them use:
* that will configure tdb and build the binaries in lib/tdb/bin/. To install them use:
Line 76: Line 64:
waf install
waf install


* The other trees that have been converted are lib/replace, lib/talloc, lib/tevent and source4/lib/ldb
* The other trees that have been converted are lib/replace,
lib/talloc, lib/tevent and source4/lib/ldb and source4


== Building Samba4 ==
== Building Samba4 ==
Line 124: Line 113:
file. That file can depend on other project wscript files. I've kept
file. That file can depend on other project wscript files. I've kept
the wscript files for each project simple by using a 'waf tool' called
the wscript files for each project simple by using a 'waf tool' called
'wafsamba.py', which is an add-on for waf that sets up the waf
'wafsamba', which is in buildtools/wafsamba. Wafsamba is an add-on for
configuration and build commands to follow the same sorts of
waf that sets up the waf configuration and build commands to follow
conventions that we have in the existing Samba4 build system.
the same sorts of conventions that we have in the existing Samba4
build system.


If you want to have a look at how this was done, then look in
If you want to have a look at how this was done, then look in
Line 142: Line 132:
== Adding new commands ==
== Adding new commands ==


In Samba we are used to a number of non-standard make targets, such as
In Samba we are used to a number of non-standard make targets, such as 'make quicktest'. We can add the same targets using waf. Even better, when you add a new target in waf it shows up in 'waf --help'. To give an example, I've added a selftest/wscript here [http://git.samba.org/?p=tridge/samba.git;a=blob;f=source4/selftest/wscript;hb=waf-wip source4/selftest/wscript]. As you can see, it adds a 'test' and 'quicktest' target. Now if we run 'waf --help' we get this:
'make quicktest'. We can add the same targets using waf. Even better,
when you add a new target in waf it shows up in 'waf --help'.


Main commands (example: ./waf build -j4)
Main commands (example: ./waf build -j4)
Line 155: Line 147:
uninstall: removes the installed files
uninstall: removes the installed files


The commands themselves are arbitrary python. The simplest first approach will be to call our existing
The commands themselves are arbitrary python. See the source4/selftest
directory for some examples on how this works.
perl based testsuite. Then if we wish to convert it to python later we can.



== Documentation ==
== Documentation ==
Line 164: Line 157:


The build rules I've added for Samba would also need to be documented
The build rules I've added for Samba would also need to be documented
if we adopt waf, probably by annotating wafsamba.py.
if we adopt waf, probably by using the python documentation tools on
the wafsamba tool.

== Converting Samba4 ==

Converting libreplace, talloc, ldb etc was easy. The hard bit comes
when trying to do a full Samba4 build. If you want to see what I've
doing for that, have a look in buildtools/mktowscript/. That contains
an extremely hackish perl script that converts our existing .mk files
to wscript_build files.

You can see an example auto-generated waf build file for the dsdb/
subsystem of Samba4 here [http://git.samba.org/?p=tridge/samba.git;a=blob;f=source4/dsdb/wscript_build;hb=waf-wip source4/dsdb/wscript_build]

I think the resulting auto-generated file compares quite favourably to the original config.mk that it was generated from [http://git.samba.org/?p=tridge/samba.git;a=blob;f=source4/dsdb/config.mk;hb=waf-wip source4/dsdb/config.mk]


There is a lot more work to do before we can build Samba3 and Samba4 fully with waf, but this should give you some idea of the approach I am taking.


= Parallel builds =
= Parallel builds =

Revision as of 07:20, 28 March 2010

Using waf to build Samba

As of March 2010, the waf build of Samba4 is now nearly complete. We have waf build rules for libreplace, talloc, tdb, tevent, ldb and Samba4. Kai is working on the waf build for Samba3.

The waf builds are set up so builds appear in bin/ (so if building in source4/lib/ldb then you get source4/lib/ldb/bin/ldbadd for example). This is consistent with the current workflow we use in Samba development.

Where supported, rpath is used so the binaries can be run directly without the need for LD_LIBRARY_PATH. If rpath is not supported then LD_LIBRARY_PATH is automatically set for running the testsuites.

All built files (object, libs, binaries) are in bin. The source tree is never modified (with one minor exception for gen_ndr, as described below). If you do "rm -rf bin" then you're back to a pristine tree.

waf is certainly fast. It uses full content hashing for dependencies, but still manages to run quickly. It also has a 'wafcache' which is a ccache like system, but that applies to all builds, so it will safely cache pidl, asn1, libraries, configure checks etc.

Getting the code

You need to do a git checkout of the waf-wip branch like this:

git clone git://git.samba.org/tridge/samba.git samba-waf
cd samba-waf
git checkout -b waf-wip origin/waf-wip

To update your checkout when something has changed, run this:

cd samba-waf
git pull --rebase

Trying it out

There are two ways to use the waf build. You can use ./autogen-waf.sh followed by ./configure and make as usual, or you can directly call waf.

If you directly call waf then you get some nice additional features, such as a progress bar with 'waf -p' and the ability to specify which tests to run in the testsuite. To run waf directly do this:

  • setup your PATH to point at the buildtools/ directory in the root of the Samba sources
export PATH=$HOME/samba-waf/buildtools:$PATH
  • don't install waf on your system, instead use the one in
 buildtools/. This ensures we are all always using the same version.
  • now try one of the trees that have been converted to waf. For
 example, to try the tdb tree do this:
cd lib/tdb
waf configure --enable-developer --prefix=$HOME/testprefix
waf -p
  • that will configure tdb and build the binaries in lib/tdb/bin/. To install them use:
waf install
  • The other trees that have been converted are lib/replace,
 lib/talloc, lib/tevent and source4/lib/ldb and source4

Building Samba4

The current waf-wip branch can build Samba4. This is still a work in progress, but if you want to try it, then try this:

cd samba-waf/source4
./autogen-waf.sh
./configure.developer
make
make quicktest

This avoids waf commands directly. To get the most out of waf you should use waf itself instead. Have a look at the configure script and Makefile that autogen-waf.sh produces to see examples of how to use it.

Other commands

Try "waf --help" for help on using waf. Try "waf configure --help" for the equivalent of "./configure --help". I haven't added all of our Samba configuration options yet, but I've put in a few (such as --enable-developer). See lib/replace/wscript for how these are added.

You may also find "waf -v" useful for seeing the build commands. Or use "waf -v clean build" to clean and build a tree, with the commands shown. Use "waf -p" to show a progress bar on the build.

This command illustrates the use of multiple build directories:

waf configure --enable-developer -b devbuild

It ends up creating the binaries in devbuild instead of the default of bin/.

If you want to debug why something isn't working, then you can either increase the verbosity of waf with something like "waf -vvv", or you can enable tracing of a particular phase of the build. For example, you could trace the build dependencies like this:

 waf -v --zone=deps

It is sometimes useful to disable the wafcache when debugging. use the --nocache option for that:

 waf -v --nocache clean build

How it works

Each project within Samba (tdb, ldb, talloc etc) gets a wscript file. That file can depend on other project wscript files. I've kept the wscript files for each project simple by using a 'waf tool' called 'wafsamba', which is in buildtools/wafsamba. Wafsamba is an add-on for waf that sets up the waf configuration and build commands to follow the same sorts of conventions that we have in the existing Samba4 build system.

If you want to have a look at how this was done, then look in buildtools/wafsamba/. You will notice that I've put a lot of paranoia checking in there, as I've found that the exiting config.mk files for the bulk of Samba4 contain some 'interesting' features, such as dependency loops and missing dependencies.

The waf build rules are very simple, and easy to modify. For example:

Adding new commands

In Samba we are used to a number of non-standard make targets, such as 'make quicktest'. We can add the same targets using waf. Even better, when you add a new target in waf it shows up in 'waf --help'.

Main commands (example: ./waf build -j4)
 clean    : removes the build files
 configure: configures the project
 dist     : makes a tarball for redistributing the sources
 distcheck: checks if the sources compile (tarball from 'dist')
 distclean: removes the build directory
 install  : installs the build files
 quicktest: Run the quick test suite
 test     : Run the full test suite
 uninstall: removes the installed files

The commands themselves are arbitrary python. See the source4/selftest directory for some examples on how this works.


Documentation

waf itself is documented in a online book here: http://freehackers.org/~tnagy/wafbook/single.html

The build rules I've added for Samba would also need to be documented if we adopt waf, probably by using the python documentation tools on the wafsamba tool.


Parallel builds

One nice thing about the use of waf is we gain parallel builds. On a 16 CPU machine a complete clean Samba4 build takes just 35s, including rebuilding all of the IDL files. It takes over 5 minutes on the same machine with the old build system.

Here is a graph of the build time versus -j flag

16-cpus.png


TODO

A short list of work items, not complete!

make waf builds works from subdirectories

You could be able to "cd source4/client" and run waf

reliable builds

we need to detect changing system headers/libraries and give an error.

we should include system headers in the dependecy calculation.

Note that this TODO is well beyond what the current build system can do. We're aiming for a very high standard of dependency checking.

implement LIBRARY->LIBRARY dependency reduction

We want object files used in common between libraries that depend on each other to be removed from the parent library, unless the parent library exports the symbols publicly and the child library is a private library

COMPLETED TODO ITEMS

speedup null build

the null build now takes about 1.6s which is good enough

fix 'waf test'

all s4 tests now pass with the waf build

check each compiler option

for options like --enable-developer we need to check the compiler supports the various options.

The flags should only be used in the build and not within configure checks.

get the waf build working in the build farm

This will test the portability quite well

its passing on some hosts in the build farm. The others are being worked on

get git revision in logs and -V output

bin/samba -V should show the git revsion

waf configure --help

waf configure --help should display 'build' as possible command

implement waf install

We need to call the same install scripts we used from the old build, at least initially.

all done now

add --no-bundled-libraries

done, as --bundled-libraries=LIST