4 # Copyright (C) 2015-2018 Karl Linden <karl.j.linden@gmail.com>
5 # Copyleft (C) 2008-2024 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')
57 help='HTML documentation directory [Default: <prefix>/share/jack-audio-connection-kit/reference/html/',
59 opt.add_option('--libdir', help='Library directory [Default: <prefix>/lib]')
60 opt.add_option('--pkgconfigdir', help='pkg-config file directory [Default: <libdir>/pkgconfig]')
61 opt.add_option('--mandir', help='Manpage directory [Default: <prefix>/share/man/man1]')
63 # options affecting binaries
67 help='Target platform for cross-compiling, e.g. cygwin or win32',
71 help='Enable devmode', # enable warnings and treat them as errors
72 conf_dest='BUILD_DEVMODE',
75 opt.add_option('--debug', action='store_true', default=False, dest='debug', help='Build debuggable binaries')
76 opt.add_option('--siginfo', action='store_true', default=False, dest='siginfo', help="Log backtrace on fatal signal")
77 opt.add_option('--distname', default=None, help="Name for the distribution tarball")
78 opt.add_option('--distsuffix', default="", help="String to append to the distribution tarball name")
79 # opt.add_option('--tagdist', action='store_true', default=False, help='Create of git tag for distname')
81 #opt.set_auto_options_define('HAVE_%s')
82 #opt.set_auto_options_style('yesno_and_hack')
84 # options with third party dependencies
85 #doxygen = opt.add_auto_option(
87 # help='Build doxygen documentation',
88 # conf_dest='BUILD_DOXYGEN_DOCS',
90 #doxygen.find_program('doxygen')
95 # this must be called before the configure phase
96 #opt.apply_auto_options_hack()
99 def detect_platform(conf):
100 # GNU/kFreeBSD and GNU/Hurd are treated as Linux
102 # ('KEY, 'Human readable name', ['strings', 'to', 'check', 'for'])
103 ('IS_LINUX', 'Linux', ['gnu0', 'gnukfreebsd', 'linux', 'posix']),
104 ('IS_FREEBSD', 'FreeBSD', ['freebsd']),
105 ('IS_SUN', 'SunOS', ['sunos']),
108 for key, name, strings in platforms:
109 conf.env[key] = False
111 conf.start_msg('Checking platform')
112 platform = Options.options.platform
113 for key, name, strings in platforms:
115 if platform.startswith(s):
117 conf.end_msg(name, color='CYAN')
121 conf.load('compiler_c')
123 detect_platform(conf)
124 flags = WafToolchainFlags(conf)
126 conf.check_cfg(package='jackserver', uselib_store='JACKSERVER', args=["--cflags", "--libs"])
128 conf.check_cfg(package='expat', args='--cflags --libs')
132 if conf.env['IS_FREEBSD']:
133 conf.check(lib='execinfo', uselib='EXECINFO', define_name='EXECINFO')
134 conf.check_cfg(package='libsysinfo', args='--cflags --libs')
136 conf.load('autooptions')
138 conf.env['LIB_PTHREAD'] = ['pthread']
139 conf.env['LIB_DL'] = ['dl']
140 conf.env['LIB_RT'] = ['rt']
141 conf.env['LIB_M'] = ['m']
142 conf.env['JACK_VERSION'] = VERSION
144 conf.env['BINDIR'] = conf.env['PREFIX'] + '/bin'
146 if Options.options.htmldir:
147 conf.env['HTMLDIR'] = Options.options.htmldir
149 # set to None here so that the doxygen code can find out the highest
150 # directory to remove upon install
151 conf.env['HTMLDIR'] = None
153 if Options.options.libdir:
154 conf.env['LIBDIR'] = Options.options.libdir
156 conf.env['LIBDIR'] = conf.env['PREFIX'] + '/lib'
158 if Options.options.pkgconfigdir:
159 conf.env['PKGCONFDIR'] = Options.options.pkgconfigdir
161 conf.env['PKGCONFDIR'] = conf.env['LIBDIR'] + '/pkgconfig'
163 if Options.options.mandir:
164 conf.env['MANDIR'] = Options.options.mandir
166 conf.env['MANDIR'] = conf.env['PREFIX'] + '/share/man/man1'
168 flags.add_c('-std=gnu99')
169 if conf.env['BUILD_DEVMODE']:
170 flags.add_c(['-Wall', '-Wextra'])
171 #flags.add_c('-Wpedantic')
172 flags.add_c('-Werror')
173 flags.add_c(['-Wno-variadic-macros', '-Wno-gnu-zero-variadic-macro-arguments'])
175 # https://wiki.gentoo.org/wiki/Modern_C_porting
176 if conf.env['CC'] == 'clang':
177 flags.add_c('-Wno-unknown-argumemt')
178 flags.add_c('-Werror=implicit-function-declaration')
179 flags.add_c('-Werror=incompatible-function-pointer-types')
180 flags.add_c('-Werror=deprecated-non-prototype')
181 flags.add_c('-Werror=strict-prototypes')
182 if int(conf.env['CC_VERSION'][0]) < 16:
183 flags.add_c('-Werror=implicit-int')
185 flags.add_c('-Wno-unknown-warning-option')
186 flags.add_c('-Werror=implicit-function-declaration')
187 flags.add_c('-Werror=implicit-int')
188 flags.add_c('-Werror=incompatible-pointer-types')
189 flags.add_c('-Werror=strict-prototypes')
190 if conf.env['BUILD_DEBUG']:
191 flags.add_c(['-O0', '-g', '-fno-omit-frame-pointer'])
194 conf.env['BUILD_SIGINFO'] = Options.options.siginfo
196 conf.define('JACK_VERSION', conf.env['JACK_VERSION'])
197 conf.define('SIGINFO_ENABLED', conf.env['BUILD_SIGINFO'])
198 conf.write_config_header('config.h', remove=False)
205 version_msg = APPNAME + "-" + VERSION
206 if os.access('version.h', os.R_OK):
207 data = open('version.h').read()
208 m = re.match(r'^#define GIT_VERSION "([^"]*)"$', data)
210 version_msg += " exported from " + m.group(1)
211 elif os.access('.git', os.R_OK):
212 version_msg += " git revision will be checked and eventually updated during build"
215 conf.msg('Install prefix', conf.env['PREFIX'], color='CYAN')
216 conf.msg('Library directory', conf.all_envs['']['LIBDIR'], color='CYAN')
217 display_feature(conf, 'Build debuggable binaries', conf.env['BUILD_DEBUG'])
218 display_feature(conf, 'Build with siginfo', conf.env['BUILD_SIGINFO'])
221 ('C compiler flags', ['CFLAGS', 'CPPFLAGS']),
222 ('Linker flags', ['LINKFLAGS', 'LDFLAGS'])
224 for name, vars in tool_flags:
227 flags += conf.all_envs[''][var]
228 conf.msg(name, repr(flags), color='NORMAL')
230 #conf.summarize_auto_options()
232 conf.msg('D-Bus service install directory', conf.env['DBUS_SERVICES_DIR'], color='CYAN')
234 if conf.env['DBUS_SERVICES_DIR'] != conf.env['DBUS_SERVICES_DIR_REAL']:
236 print(Logs.colors.RED + 'WARNING: D-Bus session services directory as reported by pkg-config is')
237 print(Logs.colors.RED + 'WARNING:', end=' ')
238 print(Logs.colors.CYAN + conf.env['DBUS_SERVICES_DIR_REAL'])
239 print(Logs.colors.RED + 'WARNING: but service file will be installed in')
240 print(Logs.colors.RED + 'WARNING:', end=' ')
241 print(Logs.colors.CYAN + conf.env['DBUS_SERVICES_DIR'])
243 Logs.colors.RED + 'WARNING: You may need to adjust your D-Bus configuration after installing jackdbus'
245 print('WARNING: You can override dbus service install directory')
246 print('WARNING: with --enable-pkg-config-dbus-service-dir option to this script')
247 print(Logs.colors.NORMAL, end=' ')
251 bld = self.generator.bld
252 header = self.outputs[0].abspath()
253 if os.access('./version.h', os.R_OK):
254 header = os.path.join(os.getcwd(), out, "version.h")
255 shutil.copy('./version.h', header)
256 data = open(header).read()
257 m = re.match(r'^#define GIT_VERSION "([^"]*)"$', data)
259 self.ver = m.group(1)
260 Logs.pprint('BLUE', "tarball from git revision " + self.ver)
265 if bld.srcnode.find_node('.git'):
266 self.ver = bld.cmd_and_log("LANG= git rev-parse HEAD", quiet=Context.BOTH).splitlines()[0]
267 if bld.cmd_and_log("LANG= git diff-index --name-only HEAD", quiet=Context.BOTH).splitlines():
270 Logs.pprint('BLUE', "git revision " + self.ver)
274 fi = open(header, 'w')
275 fi.write('#define GIT_VERSION "%s"\n' % self.ver)
279 bld(rule=git_ver, target='version.h', update_outputs=True, always=True, ext_out=['.h'])
281 # process subfolders from here
283 if bld.env['IS_LINUX'] or bld.env['IS_FREEBSD']:
287 if bld.env['BUILD_DOXYGEN_DOCS']:
288 html_build_dir = bld.path.find_or_declare('html').abspath()
292 source='doxyfile.in',
294 HTML_BUILD_DIR=html_build_dir,
295 SRCDIR=bld.srcnode.abspath(),
299 # There are two reasons for logging to doxygen.log and using it as
300 # target in the build rule (rather than html_build_dir):
301 # (1) reduce the noise when running the build
302 # (2) waf has a regular file to check for a timestamp. If the directory
303 # is used instead waf will rebuild the doxygen target (even upon
306 doxyfile = task.inputs[0].abspath()
307 logfile = task.outputs[0].abspath()
308 cmd = '%s %s &> %s' % (task.env['DOXYGEN'][0], doxyfile, logfile)
309 return task.exec_command(cmd)
317 # Determine where to install HTML documentation. Since share_dir is the
318 # highest directory the uninstall routine should remove, there is no
319 # better candidate for share_dir, but the requested HTML directory if
320 # --htmldir is given.
321 if bld.env['HTMLDIR']:
322 html_install_dir = bld.options.destdir + bld.env['HTMLDIR']
323 share_dir = html_install_dir
325 share_dir = bld.options.destdir + bld.env['PREFIX'] + '/share/jack-audio-connection-kit'
326 html_install_dir = share_dir + '/reference/html/'
328 if bld.cmd == 'install':
329 if os.path.isdir(html_install_dir):
330 Logs.pprint('CYAN', 'Removing old doxygen documentation installation...')
331 shutil.rmtree(html_install_dir)
332 Logs.pprint('CYAN', 'Removing old doxygen documentation installation done.')
333 Logs.pprint('CYAN', 'Installing doxygen documentation...')
334 shutil.copytree(html_build_dir, html_install_dir)
335 Logs.pprint('CYAN', 'Installing doxygen documentation done.')
336 elif bld.cmd == 'uninstall':
337 Logs.pprint('CYAN', 'Uninstalling doxygen documentation...')
338 if os.path.isdir(share_dir):
339 shutil.rmtree(share_dir)
340 Logs.pprint('CYAN', 'Uninstalling doxygen documentation done.')
341 elif bld.cmd == 'clean':
342 if os.access(html_build_dir, os.R_OK):
343 Logs.pprint('CYAN', 'Removing doxygen generated documentation...')
344 shutil.rmtree(html_build_dir)
345 Logs.pprint('CYAN', 'Removing doxygen generated documentation done.')
347 class jackdbus_dist(Scripting.Dist):
352 Scripting.Dist.__init__(self)
353 if Options.options.distname:
354 self.base_name = Options.options.distname
355 self.tag_name = Options.options.distname
357 self.tag_name = VERSION
359 sha = self.cmd_and_log("LANG= git rev-parse --short HEAD", quiet=Context.BOTH).splitlines()[0]
360 self.base_name = APPNAME + '-' + VERSION + "-g" + sha
362 self.base_name = APPNAME + '-' + VERSION
363 self.base_name += Options.options.distsuffix
365 #print self.base_name
367 # if Options.options.tagdist:
368 ret = self.exec_command("LANG= git tag " + self.tag_name)
370 raise waflib.Errors.WafError('git tag creation failed')
372 def get_base_name(self):
373 return self.base_name
376 excl = Scripting.Dist.get_excl(self)
378 excl += ' .gitmodules'
382 excl += ' .cirrus.yml'
383 excl += ' .wafupdaterc'
385 excl += ' README-docinfo-header.html'
386 excl += ' README-docinfo.html'
399 shutil.copy('./build/version.h', "./")
401 super(jackdbus_dist, self).execute()
403 os.remove("version.h")