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
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
37 # these variables are mandatory ('/' are converted automatically)
41 def display_feature(conf, msg, build):
43 conf.msg(msg, 'yes', color='GREEN')
45 conf.msg(msg, 'no', color='YELLOW')
49 # options provided by the modules
50 opt.load('compiler_c')
51 opt.load('autooptions')
58 help='HTML documentation directory [Default: <prefix>/share/jack-audio-connection-kit/reference/html/',
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
69 help='Target platform for cross-compiling, e.g. cygwin or win32',
73 help='Enable devmode', # enable warnings and treat them as errors
74 conf_dest='BUILD_DEVMODE',
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(
86 # help='Build doxygen documentation',
87 # conf_dest='BUILD_DOXYGEN_DOCS',
89 #doxygen.find_program('doxygen')
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
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']),
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:
114 if platform.startswith(s):
116 conf.end_msg(name, color='CYAN')
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')
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
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
155 conf.env['LIBDIR'] = conf.env['PREFIX'] + '/lib'
157 if Options.options.pkgconfigdir:
158 conf.env['PKGCONFDIR'] = Options.options.pkgconfigdir
160 conf.env['PKGCONFDIR'] = conf.env['LIBDIR'] + '/pkgconfig'
162 if Options.options.mandir:
163 conf.env['MANDIR'] = Options.options.mandir
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')
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'])
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)
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)
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"
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'])
220 ('C compiler flags', ['CFLAGS', 'CPPFLAGS']),
221 ('Linker flags', ['LINKFLAGS', 'LDFLAGS'])
223 for name, vars in tool_flags:
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']:
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'])
242 Logs.colors.RED + 'WARNING: You may need to adjust your D-Bus configuration after installing jackdbus'
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=' ')
250 if type(self) == Scripting.Dist:
251 header = "./version.h"
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)
262 self.ver = m.group(1)
263 Logs.pprint('BLUE', "tarball from git revision " + self.ver)
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():
273 Logs.pprint('BLUE', "git revision " + self.ver)
277 fi = open(header, 'w')
278 fi.write('#define GIT_VERSION "%s"\n' % self.ver)
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']:
290 if bld.env['BUILD_DOXYGEN_DOCS']:
291 html_build_dir = bld.path.find_or_declare('html').abspath()
295 source='doxyfile.in',
297 HTML_BUILD_DIR=html_build_dir,
298 SRCDIR=bld.srcnode.abspath(),
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
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)
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
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.')