Hi, I have been looking for a nice build system, for personal, for quite some time now. I saw waf at one point and thought it might be a good system, but I never paid much attention to it. Recently I again started looking into it and I decided to use pacman to test out how good it is. In comparison to autotools, the language (python) is a lot simpler and easier to understand, although it still took a while to understand waf. The size of the configuration script is significantly smaller (see statistics below). The waf website also claims that it is faster than autotools, I believe it is, but I did not actually benchmark anything. So far I've managed to get libalpm to compile (shared library only), and pacman shouldn't be too hard since most of the stuff is already there. The script is far from being finished, I simply wanted to see how difficult it was to get something compiled, while linking against external libraries. I just wanted to see if anyone was interested in actually using waf as the build system for pacman. If not, I'm not sure that I'll be bothering with compiling pacman, since I only really need libalpm. Not sure if all these files are created by people, but even configure.ac alone is larger;
$ wc -l configure.ac Makefile.am config.* acinclude.m4 404 configure.ac 29 Makefile.am 1526 config.guess 614 config.rpath 1658 config.sub 4952 acinclude.m4 9183 total
$ wc -l wscript 143 wscript
Note: The build script has only been tested on Mac OS X, and thus I don't know if it links properly against libdownload. From wscript:
VERSION = '3.1.4' APPNAME = 'pacman' LIB_VERSION = '2.3.1' LIB_NAME = 'libalpm'
srcdir = '.' blddir = 'build'
def set_options(opt): opt.tool_options('compiler_cc') # TODO: Optparse on Mac OSX Leopard seems outdated, this doesn't work there # opt.set_defaults( # root_dir='/', # pkg_ext='.pkg.tar.gz', # src_ext='.src.tar.gz', # db_ext='.db.tar.gz', # use_internal_download=True, # want_doc=False, # want_doxygen=False, # want_asciidoc=False, # want_debug=False, # want_gitver=False, # pacman_static=True # )
opt.add_option('--with-root-dir', dest='root_dir', help='set the location of pacman\'s root operating directory [/]', default='/') opt.add_option('--with-pkg-ext', dest='pkg_ext', help='set the file extension used by packages [pkg.tar.gz]', default='pkg.tar.gz') opt.add_option('--with-src-ext', dest='src_ext', help='set the file extension used by source packages [src.tar.gz]', default='src.tar.gz') opt.add_option('--with-db-ext', dest='db_ext', help='set the file extension used by the database [db.tar.gz]', default='db.tar.gz') # opt.add_option('--disable-internal-download', type='store_false', # dest='use_internal_download', # help='do not build with libdownload/libfetch support') # opt.add_option('--disable-doc', type='store_false', # dest='want_doc', # help='do not generate documentation') # opt.add_option('--enable-doxygen', dest='want_doxygen', type='store_true', # help='build your own API docs via Doxygen') # opt.add_option('--enable-asciidoc', dest='want_asciidoc', type='store_true', # help='build your own manpages with Asciidoc') # opt.add_option('--enable-debug', dest='want_debug', type='store_true', # help='enable debugging support') pass
def configure(conf): import Params
def conf_check_function(name, mandatory=1, headers=[], header_code='', define=''): functest = conf.create_function_enumerator() functest.mandatory = mandatory functest.function = name if headers: functest.headers = headers if not define: define='HAVE_' + name.upper() if header_code: functest.header_code = header_code functest.define = define functest.run()
conf.check_tool('compiler_cc checks')
headers = [ 'fcntl.h', 'libintl.h', 'limits.h', 'locale.h', 'string.h', 'strings.h', 'sys/ioctl.h', 'sys/param.h', 'sys/statvfs.h', 'sys/syslimits.h', 'sys/time.h', 'syslog.h', 'wchar.h', ]
for header in headers: headerconf = conf.create_header_configurator() headerconf.name = header headerconf.mandatory = 1 headerconf.message = header + ' is required.' headerconf.run()
conf_check_function('geteuid', 1, ['unistd.h']) conf_check_function('realpath', 1, ['stdlib.h']) conf_check_function('regcomp', 1, ['regex.h']) conf_check_function('strcasecmp', 1, ['string.h']) #conf_check_function('strndup', 1, ['string.h'], header_code='#define _GNU_SOURCE') #TODO: FIX conf_check_function('strrchr', 1, ['string.h']) conf_check_function('strsep', 1, ['string.h']) #conf_check_function('strverscmp', 1, ['string.h'], header_code='#define _GNU_SOURCE') conf_check_function('swprintf', 1, ['stdio.h', 'wchar.h']) conf_check_function('wcwidth', 1, ['wchar.h']) conf_check_function('uname', 1, ['sys/utsname.h']) conf_check_function('archive_read_data', 1, ['archive.h'], define='HAVE_LIBARCHIVE') conf_check_function('downloadParseURL', 0, ['download.h'], define='HAVE_LIBDOWNLOAD') conf_check_function('fetchParseURL', 0, ['sys/param.h', 'stdio.h', 'fetch.h'], define='HAVE_LIBFETCH') if conf.env['HAVE_LIBDOWNLOAD'] != 1 and conf.env['HAVE_LIBFETCH'] ! = 1: #TODO: Print error #fatal('libdownload or libfetch are needed to compile with internal download support') return
conf.env['LIB_ARCHIVE'] = 'archive' conf.env['LIB_DOWNLOAD'] = 'download' conf.env['LIB_FETCH'] = 'fetch'
conf.define('PACKAGE', APPNAME) conf.define('PACKAGE_VERSION', VERSION) conf.define('LIB_VERSION', LIB_VERSION) conf.define('ROOTDIR', Params.g_options.root_dir) conf.define('DBEXT', Params.g_options.db_ext) conf.define('PKGEXT', Params.g_options.pkg_ext) conf.define('DBPATH', '/usr/lib/pacman/') conf.define('LOGFILE', '/usr/log/pacman.log') conf.define('CACHEDIR', '/var/cache/pacman/pkg/') conf.define('CONFFILE', '/etc/pacman.conf') #TODO: make path configurable conf.define('RETSIGTYPE', 'int') #TODO: Fix? (AC_TYPE_SIGNAL replacement) #conf.define('HAVE_CONFIG_H', 1) # autotools compatibility
conf.write_config_header('config.h')
def build(build): import Constants env = build.env() libalpm = build.create_obj('cc', 'shlib') libalpm.name = LIB_NAME libalpm.target = 'alpm' # waf prepends 'lib' (why?) libalpm.uselib = 'ARCHIVE' if env['HAVE_LIBDOWNLOAD'] != Constants.UNDEFINED: libalpm.uselib += ' DOWNLOAD' elif env['HAVE_LIBFETCH'] != Constants.UNDEFINED: libalpm.uselib += ' FETCH' libalpm.find_sources_in_dirs('lib/libalpm', exts=['.c'])
# pacman = build.create_obj('cc', 'program') # pacman.name = 'pacman' # pacman.target = 'pacman' # pacman.uselib = 'libalpm' # pacman.find_sources_in_dirs('src/pacman', exts=['.c'])