README.adoc: Improve the tarballs link text
[jackdbus.git] / wscript
blob3a67cb459445e66594940348195dfa9a0e9552df
1 #! /usr/bin/python3
2 # encoding: utf-8
4 # Copyright (C) 2015-2018 Karl Linden <karl.j.linden@gmail.com>
5 # Copyleft (C) 2008-2022 Nedko Arnaudov
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 from __future__ import print_function
23 import os
24 import shutil
25 import sys
26 import re
28 from waflib import Logs, Options, TaskGen
29 from waflib import Context
30 from waflib import Scripting
31 from waflib.Build import BuildContext, CleanContext, InstallContext, UninstallContext
32 from waftoolchainflags import WafToolchainFlags
34 VERSION = "2.23.0"
35 APPNAME = 'jackdbus'
37 # these variables are mandatory ('/' are converted automatically)
38 top = '.'
39 out = 'build'
41 def display_feature(conf, msg, build):
42     if build:
43         conf.msg(msg, 'yes', color='GREEN')
44     else:
45         conf.msg(msg, 'no', color='YELLOW')
48 def options(opt):
49     # options provided by the modules
50     opt.load('compiler_c')
51     opt.load('autooptions')
53     # install directories
54     opt.add_option(
55         '--htmldir',
56         type='string',
57         default=None,
58         help='HTML documentation directory [Default: <prefix>/share/jack-audio-connection-kit/reference/html/',
59     )
60     opt.add_option('--libdir', type='string', help='Library directory [Default: <prefix>/lib]')
61     opt.add_option('--pkgconfigdir', type='string', help='pkg-config file directory [Default: <libdir>/pkgconfig]')
62     opt.add_option('--mandir', type='string', help='Manpage directory [Default: <prefix>/share/man/man1]')
64     # options affecting binaries
65     opt.add_option(
66         '--platform',
67         type='string',
68         default=sys.platform,
69         help='Target platform for cross-compiling, e.g. cygwin or win32',
70     )
71     opt.add_auto_option(
72         'devmode',
73         help='Enable devmode', # enable warnings and treat them as errors
74         conf_dest='BUILD_DEVMODE',
75         default=False,
76     )
77     opt.add_option('--debug', action='store_true', default=False, dest='debug', help='Build debuggable binaries')
78     opt.add_option('--siginfo', action='store_true', default=False, dest='siginfo', help="Log backtrace on fatal signal")
80     #opt.set_auto_options_define('HAVE_%s')
81     #opt.set_auto_options_style('yesno_and_hack')
83     # options with third party dependencies
84     #doxygen = opt.add_auto_option(
85     #        'doxygen',
86     #        help='Build doxygen documentation',
87     #        conf_dest='BUILD_DOXYGEN_DOCS',
88     #        default=False)
89     #doxygen.find_program('doxygen')
91     # dbus options
92     opt.recurse('dbus')
94     # this must be called before the configure phase
95     #opt.apply_auto_options_hack()
98 def detect_platform(conf):
99     # GNU/kFreeBSD and GNU/Hurd are treated as Linux
100     platforms = [
101         # ('KEY, 'Human readable name', ['strings', 'to', 'check', 'for'])
102         ('IS_LINUX',   'Linux',   ['gnu0', 'gnukfreebsd', 'linux', 'posix']),
103         ('IS_FREEBSD', 'FreeBSD', ['freebsd']),
104         ('IS_SUN',     'SunOS',   ['sunos']),
105     ]
107     for key, name, strings in platforms:
108         conf.env[key] = False
110     conf.start_msg('Checking platform')
111     platform = Options.options.platform
112     for key, name, strings in platforms:
113         for s in strings:
114             if platform.startswith(s):
115                 conf.env[key] = True
116                 conf.end_msg(name, color='CYAN')
117                 break
119 def configure(conf):
120     conf.load('compiler_c')
122     detect_platform(conf)
123     flags = WafToolchainFlags(conf)
125     conf.check_cfg(package='jackserver', uselib_store='JACKSERVER', args=["--cflags", "--libs"])
127     conf.check_cfg(package='expat', args='--cflags --libs')
129     flags.add_c('-Wall')
131     if conf.env['IS_FREEBSD']:
132         conf.check(lib='execinfo', uselib='EXECINFO', define_name='EXECINFO')
133         conf.check_cfg(package='libsysinfo', args='--cflags --libs')
135     conf.load('autooptions')
137     conf.env['LIB_PTHREAD'] = ['pthread']
138     conf.env['LIB_DL'] = ['dl']
139     conf.env['LIB_RT'] = ['rt']
140     conf.env['LIB_M'] = ['m']
141     conf.env['JACK_VERSION'] = VERSION
143     conf.env['BINDIR'] = conf.env['PREFIX'] + '/bin'
145     if Options.options.htmldir:
146         conf.env['HTMLDIR'] = Options.options.htmldir
147     else:
148         # set to None here so that the doxygen code can find out the highest
149         # directory to remove upon install
150         conf.env['HTMLDIR'] = None
152     if Options.options.libdir:
153         conf.env['LIBDIR'] = Options.options.libdir
154     else:
155         conf.env['LIBDIR'] = conf.env['PREFIX'] + '/lib'
157     if Options.options.pkgconfigdir:
158         conf.env['PKGCONFDIR'] = Options.options.pkgconfigdir
159     else:
160         conf.env['PKGCONFDIR'] = conf.env['LIBDIR'] + '/pkgconfig'
162     if Options.options.mandir:
163         conf.env['MANDIR'] = Options.options.mandir
164     else:
165         conf.env['MANDIR'] = conf.env['PREFIX'] + '/share/man/man1'
167     flags.add_c('-std=gnu99')
168     if conf.env['BUILD_DEVMODE']:
169         flags.add_c(['-Wall', '-Wextra'])
170         #flags.add_c('-Wpedantic')
171         flags.add_c('-Werror')
172         flags.add_c(['-Wno-variadic-macros', '-Wno-gnu-zero-variadic-macro-arguments'])
174         # https://wiki.gentoo.org/wiki/Modern_C_porting
175         if conf.env['CC'] == 'clang':
176             flags.add_c('-Wno-unknown-argumemt')
177             flags.add_c('-Werror=implicit-function-declaration')
178             flags.add_c('-Werror=incompatible-function-pointer-types')
179             flags.add_c('-Werror=deprecated-non-prototype')
180             flags.add_c('-Werror=strict-prototypes')
181             if int(conf.env['CC_VERSION'][0]) < 16:
182                 flags.add_c('-Werror=implicit-int')
183         else:
184             flags.add_c('-Wno-unknown-warning-option')
185             flags.add_c('-Werror=implicit-function-declaration')
186             flags.add_c('-Werror=implicit-int')
187             flags.add_c('-Werror=incompatible-pointer-types')
188             flags.add_c('-Werror=strict-prototypes')
189     if conf.env['BUILD_DEBUG']:
190         flags.add_c(['-O0', '-g', '-fno-omit-frame-pointer'])
191         flags.add_link('-g')
193     conf.env['BUILD_SIGINFO'] =  Options.options.siginfo
195     conf.define('JACK_VERSION', conf.env['JACK_VERSION'])
196     conf.define('SIGINFO_ENABLED', conf.env['BUILD_SIGINFO'])
197     conf.write_config_header('config.h', remove=False)
199     conf.recurse('dbus')
201     flags.flush()
203     print()
204     version_msg = APPNAME + "-" + VERSION
205     if os.access('version.h', os.R_OK):
206         data = open('version.h').read()
207         m = re.match(r'^#define GIT_VERSION "([^"]*)"$', data)
208         if m != None:
209             version_msg += " exported from " + m.group(1)
210     elif os.access('.git', os.R_OK):
211         version_msg += " git revision will be checked and eventually updated during build"
212     print(version_msg)
214     conf.msg('Install prefix', conf.env['PREFIX'], color='CYAN')
215     conf.msg('Library directory', conf.all_envs['']['LIBDIR'], color='CYAN')
216     display_feature(conf, 'Build debuggable binaries', conf.env['BUILD_DEBUG'])
217     display_feature(conf, 'Build with siginfo', conf.env['BUILD_SIGINFO'])
219     tool_flags = [
220         ('C compiler flags',   ['CFLAGS', 'CPPFLAGS']),
221         ('Linker flags',       ['LINKFLAGS', 'LDFLAGS'])
222     ]
223     for name, vars in tool_flags:
224         flags = []
225         for var in vars:
226             flags += conf.all_envs[''][var]
227         conf.msg(name, repr(flags), color='NORMAL')
229     #conf.summarize_auto_options()
231     conf.msg('D-Bus service install directory', conf.env['DBUS_SERVICES_DIR'], color='CYAN')
233     if conf.env['DBUS_SERVICES_DIR'] != conf.env['DBUS_SERVICES_DIR_REAL']:
234         print()
235         print(Logs.colors.RED + 'WARNING: D-Bus session services directory as reported by pkg-config is')
236         print(Logs.colors.RED + 'WARNING:', end=' ')
237         print(Logs.colors.CYAN + conf.env['DBUS_SERVICES_DIR_REAL'])
238         print(Logs.colors.RED + 'WARNING: but service file will be installed in')
239         print(Logs.colors.RED + 'WARNING:', end=' ')
240         print(Logs.colors.CYAN + conf.env['DBUS_SERVICES_DIR'])
241         print(
242             Logs.colors.RED + 'WARNING: You may need to adjust your D-Bus configuration after installing jackdbus'
243             )
244         print('WARNING: You can override dbus service install directory')
245         print('WARNING: with --enable-pkg-config-dbus-service-dir option to this script')
246         print(Logs.colors.NORMAL, end=' ')
247     print()
249 def git_ver(self):
250     if type(self) == Scripting.Dist:
251         header = "./version.h"
252         bld = self
253     else:
254         bld = self.generator.bld
255         header = self.outputs[0].abspath()
256         if os.access('./version.h', os.R_OK):
257             #header = os.path.join(os.getcwd(), out, "version.h")
258             shutil.copy('./version.h', header)
259             data = open(header).read()
260             m = re.match(r'^#define GIT_VERSION "([^"]*)"$', data)
261             if m != None:
262                 self.ver = m.group(1)
263                 Logs.pprint('BLUE', "tarball from git revision " + self.ver)
264             else:
265                 self.ver = "tarball"
266             return
268     if os.access('./.git', os.R_OK):
269         self.ver = bld.cmd_and_log("LANG= git rev-parse HEAD", quiet=Context.BOTH).splitlines()[0]
270         if bld.cmd_and_log("LANG= git diff-index --name-only HEAD", quiet=Context.BOTH).splitlines():
271             self.ver += "-dirty"
273         Logs.pprint('BLUE', "git revision " + self.ver)
274     else:
275         self.ver = "unknown"
277     fi = open(header, 'w')
278     fi.write('#define GIT_VERSION "%s"\n' % self.ver)
279     fi.close()
281 def build(bld):
282     bld(rule=git_ver, target='version.h', update_outputs=True, always=True, ext_out=['.h'])
284     # process subfolders from here
286     if bld.env['IS_LINUX'] or bld.env['IS_FREEBSD']:
287         bld.recurse('man')
288     bld.recurse('dbus')
290     if bld.env['BUILD_DOXYGEN_DOCS']:
291         html_build_dir = bld.path.find_or_declare('html').abspath()
293         bld(
294             features='subst',
295             source='doxyfile.in',
296             target='doxyfile',
297             HTML_BUILD_DIR=html_build_dir,
298             SRCDIR=bld.srcnode.abspath(),
299             VERSION=VERSION
300         )
302         # There are two reasons for logging to doxygen.log and using it as
303         # target in the build rule (rather than html_build_dir):
304         # (1) reduce the noise when running the build
305         # (2) waf has a regular file to check for a timestamp. If the directory
306         #     is used instead waf will rebuild the doxygen target (even upon
307         #     install).
308         def doxygen(task):
309             doxyfile = task.inputs[0].abspath()
310             logfile = task.outputs[0].abspath()
311             cmd = '%s %s &> %s' % (task.env['DOXYGEN'][0], doxyfile, logfile)
312             return task.exec_command(cmd)
314         bld(
315             rule=doxygen,
316             source='doxyfile',
317             target='doxygen.log'
318         )
320         # Determine where to install HTML documentation. Since share_dir is the
321         # highest directory the uninstall routine should remove, there is no
322         # better candidate for share_dir, but the requested HTML directory if
323         # --htmldir is given.
324         if bld.env['HTMLDIR']:
325             html_install_dir = bld.options.destdir + bld.env['HTMLDIR']
326             share_dir = html_install_dir
327         else:
328             share_dir = bld.options.destdir + bld.env['PREFIX'] + '/share/jack-audio-connection-kit'
329             html_install_dir = share_dir + '/reference/html/'
331         if bld.cmd == 'install':
332             if os.path.isdir(html_install_dir):
333                 Logs.pprint('CYAN', 'Removing old doxygen documentation installation...')
334                 shutil.rmtree(html_install_dir)
335                 Logs.pprint('CYAN', 'Removing old doxygen documentation installation done.')
336             Logs.pprint('CYAN', 'Installing doxygen documentation...')
337             shutil.copytree(html_build_dir, html_install_dir)
338             Logs.pprint('CYAN', 'Installing doxygen documentation done.')
339         elif bld.cmd == 'uninstall':
340             Logs.pprint('CYAN', 'Uninstalling doxygen documentation...')
341             if os.path.isdir(share_dir):
342                 shutil.rmtree(share_dir)
343             Logs.pprint('CYAN', 'Uninstalling doxygen documentation done.')
344         elif bld.cmd == 'clean':
345             if os.access(html_build_dir, os.R_OK):
346                 Logs.pprint('CYAN', 'Removing doxygen generated documentation...')
347                 shutil.rmtree(html_build_dir)
348                 Logs.pprint('CYAN', 'Removing doxygen generated documentation done.')
350 def dist(ctx):
351     git_ver(ctx)