#!/usr/bin/env python # Licensed under the GNU GPL v3 or later, see COPYING file for details. # Copyright 2008-2013 David Robillard # Copyright 2008 Nedko Arnaudov import os from waflib import Build, Logs, Options, Utils from waflib.extras import autowaf # Version of this package (even if built as a child) PATCHAGE_VERSION = '1.0.5' # Variables for 'waf dist' APPNAME = 'patchage' VERSION = PATCHAGE_VERSION # Mandatory variables top = '.' out = 'build' # Release variables uri = 'http://drobilla.net/sw/patchage' dist_pattern = 'http://download.drobilla.net/patchage-%d.%d.%d.tar.bz2' post_tags = ['Hacking', 'LAD', 'Patchage'] def options(ctx): ctx.load('compiler_cxx') opt = ctx.configuration_options() opt.add_option('--patchage-install-name', type='string', default=APPNAME, help='patchage install name') opt.add_option('--patchage-human-name', type='string', default='Patchage', help='patchage human name') ctx.add_flags( opt, {'jack-dbus': 'use Jack via D-Bus', 'no-alsa': 'do not build Alsa Sequencer support', 'no-binloc': 'do not find files from executable location', 'light-theme': 'use light coloured theme'}) def configure(conf): conf.load('compiler_cxx', cache=True) conf.load('autowaf', cache=True) autowaf.set_cxx_lang(conf, 'c++14') if Options.options.strict: # Check for programs used by lint target conf.find_program("flake8", var="FLAKE8", mandatory=False) conf.find_program("clang-tidy", var="CLANG_TIDY", mandatory=False) conf.find_program("iwyu_tool", var="IWYU_TOOL", mandatory=False) if Options.options.ultra_strict: autowaf.add_compiler_flags(conf.env, '*', { 'clang': [ '-Wno-alloca', '-Wno-cast-qual', '-Wno-double-promotion', '-Wno-float-conversion', '-Wno-float-equal', '-Wno-implicit-float-conversion', '-Wno-padded', '-Wno-pedantic', '-Wno-shorten-64-to-32', '-Wno-sign-conversion', ], 'gcc': [ '-Wno-alloca', '-Wno-conversion', '-Wno-float-equal', '-Wno-inline', '-Wno-padded', '-Wno-pedantic', '-Wno-stack-protector', '-Wno-suggest-attribute=const', '-Wno-suggest-attribute=noreturn', '-Wno-suggest-attribute=pure', '-Wno-suggest-final-methods', '-Wno-suggest-final-types', ], }) autowaf.add_compiler_flags(conf.env, 'c', { 'clang': [ '-Wno-bad-function-cast', '-Wno-missing-noreturn', ], 'gcc': [ '-Wno-bad-function-cast', ], }) autowaf.add_compiler_flags(conf.env, 'cxx', { 'clang': [ '-Wno-weak-vtables', ], 'gcc': [ '-Wno-conditionally-supported', '-Wno-effc++', ], }) conf.check_pkg('dbus-1', uselib_store='DBUS', system=True, mandatory=False) conf.check_pkg('dbus-glib-1', uselib_store='DBUS_GLIB', system=True, mandatory=False) conf.check_pkg('gthread-2.0 >= 2.14.0', system=True, uselib_store='GTHREAD') conf.check_pkg('glibmm-2.4 >= 2.14.0', system=True, uselib_store='GLIBMM') conf.check_pkg('gtkmm-2.4 >= 2.12.0', system=True, uselib_store='GTKMM') conf.check_pkg('ganv-1 >= 1.5.2', uselib_store='GANV') if conf.env.DEST_OS == 'darwin': conf.check_pkg('gtk-mac-integration', uselib_store='GTK_OSX', system=True, mandatory=False) if conf.env.HAVE_GTK_OSX: conf.define('PATCHAGE_GTK_OSX', 1) # Check for dladdr conf.check_function('cxx', 'dladdr', header_name = 'dlfcn.h', defines = ['_GNU_SOURCE'], lib = ['dl'], define_name = 'HAVE_DLADDR', return_type = 'int', arg_types = 'const void*,Dl_info*', mandatory = False) # Use Jack D-Bus if requested (only one jack driver is allowed) use_jack_dbus = (Options.options.jack_dbus and conf.env.HAVE_DBUS and conf.env.HAVE_DBUS_GLIB) if use_jack_dbus: conf.define('HAVE_JACK_DBUS', 1) else: conf.check_pkg('jack >= 0.120.0', uselib_store='JACK', system=True, mandatory=False) if conf.env.HAVE_JACK: conf.define('PATCHAGE_LIBJACK', 1) conf.check_function('cxx', 'jack_get_property', header_name = 'jack/metadata.h', define_name = 'HAVE_JACK_METADATA', uselib = 'JACK', return_type = 'int', arg_types = '''jack_uuid_t, const char*, char**, char**''', mandatory = False) # Use Alsa if present unless --no-alsa if not Options.options.no_alsa: conf.check_pkg('alsa', uselib_store='ALSA', system=True, mandatory=False) # Find files at binary location if we have dladdr unless --no-binloc if not Options.options.no_binloc and conf.is_defined('HAVE_DLADDR'): conf.define('PATCHAGE_BINLOC', 1) if Options.options.light_theme: conf.define('PATCHAGE_USE_LIGHT_THEME', 1) # Boost headers conf.check_cxx(header_name='boost/optional/optional.hpp') conf.check_cxx(header_name='boost/variant.hpp') # Check for system provided fmt conf.check_pkg('fmt', uselib_store='FMT', system=True, mandatory=False) if not conf.env.HAVE_FMT: # Fall back to minimal bundled version if not found Logs.warn("System fmt library not found, using bundled copy") include_dir = conf.path.find_node('subprojects/fmt/include') conf.define('FMT_HEADER_ONLY', 1) conf.env.LIB_FMT = [] conf.env.INCLUDES_FMT = [include_dir.abspath()] conf.env.PATCHAGE_VERSION = PATCHAGE_VERSION conf.env.APP_INSTALL_NAME = Options.options.patchage_install_name conf.env.APP_HUMAN_NAME = Options.options.patchage_human_name conf.define('PATCHAGE_DATA_DIR', os.path.join( conf.env.DATADIR, conf.env.APP_INSTALL_NAME)) conf.define('PATCHAGE_VERSION', PATCHAGE_VERSION) conf.write_config_header('patchage_config.h', remove=False) autowaf.display_summary( conf, {'Install name': conf.env.APP_INSTALL_NAME, 'App human name': conf.env.APP_HUMAN_NAME, 'Jack (D-Bus)': conf.is_defined('HAVE_JACK_DBUS'), 'Jack (libjack)': conf.is_defined('PATCHAGE_LIBJACK'), 'Jack Metadata': conf.is_defined('HAVE_JACK_METADATA'), 'Alsa Sequencer': bool(conf.env.HAVE_ALSA)}) if conf.env.DEST_OS == 'darwin': autowaf.display_msg(conf, "Mac Integration", bool(conf.env.HAVE_GTK_OSX)) def build(bld): out_base = '' if bld.env.DEST_OS == 'darwin': out_base = 'Patchage.app/Contents/' # Program prog = bld(features = 'cxx cxxprogram', includes = ['.', 'src'], target = out_base + bld.env.APP_INSTALL_NAME, uselib = 'DBUS GANV DBUS_GLIB FMT GTKMM GTHREAD GTK_OSX', install_path = '${BINDIR}') prog.source = ''' src/Canvas.cpp src/CanvasModule.cpp src/Configuration.cpp src/Drivers.cpp src/Legend.cpp src/Metadata.cpp src/Patchage.cpp src/Reactor.cpp src/TextViewLog.cpp src/event_to_string.cpp src/handle_event.cpp src/main.cpp ''' if bld.is_defined('HAVE_JACK_DBUS'): prog.source += ' src/JackDbusDriver.cpp ' if bld.is_defined('PATCHAGE_LIBJACK'): prog.source += ' src/JackLibDriver.cpp ' prog.uselib += ' JACK NEWJACK ' if bld.env.HAVE_ALSA: prog.source += ' src/AlsaDriver.cpp ' prog.uselib += ' ALSA ' if bld.is_defined('PATCHAGE_BINLOC') and bld.is_defined('HAVE_DLADDR'): prog.lib = ['dl'] # XML UI definition bld(features = 'subst', source = 'src/patchage.ui', target = out_base + 'patchage.ui', install_path = '${DATADIR}/' + bld.env.APP_INSTALL_NAME, chmod = Utils.O644, PATCHAGE_VERSION = PATCHAGE_VERSION) # 'Desktop' file (menu entry, icon, etc) bld(features = 'subst', source = 'patchage.desktop.in', target = 'patchage.desktop', install_path = '${DATADIR}/applications', chmod = Utils.O644, BINDIR = os.path.normpath(bld.env.BINDIR), APP_INSTALL_NAME = bld.env.APP_INSTALL_NAME, APP_HUMAN_NAME = bld.env.APP_HUMAN_NAME) if bld.env.DEST_OS == 'darwin': # Property list bld(features = 'subst', source = 'osx/Info.plist.in', target = out_base + 'Info.plist', install_path = '', chmod = Utils.O644) # Icons bld(rule = 'cp ${SRC} ${TGT}', source = 'osx/Patchage.icns', target = out_base + 'Resources/Patchage.icns') # Gtk/Pango/etc configuration files for i in ['pangorc', 'pango.modules', 'loaders.cache', 'gtkrc']: bld(rule = 'cp ${SRC} ${TGT}', source = 'osx/' + i, target = out_base + 'Resources/' + i) # Icons # After installation, icon cache should be updated using: # gtk-update-icon-cache -f -t $(datadir)/icons/hicolor icon_sizes = [16, 22, 24, 32, 48, 128, 256] for s in icon_sizes: d = '%dx%d' % (s, s) bld.install_as( os.path.join(bld.env.DATADIR, 'icons', 'hicolor', d, 'apps', bld.env.APP_INSTALL_NAME + '.png'), os.path.join('icons', d, 'patchage.png')) bld.install_as( os.path.join(bld.env.DATADIR, 'icons', 'hicolor', 'scalable', 'apps', bld.env.APP_INSTALL_NAME + '.svg'), os.path.join('icons', 'scalable', 'patchage.svg')) bld.install_files('${MANDIR}/man1', bld.path.ant_glob('doc/*.1')) class LintContext(Build.BuildContext): fun = cmd = 'lint' def lint(ctx): "checks code for style issues" import subprocess import sys st = 0 if "FLAKE8" in ctx.env: Logs.info("Running flake8") st = subprocess.call([ctx.env.FLAKE8[0], "wscript", "--ignore", "E221,W504,E251,E241,E741"]) else: Logs.warn("Not running flake8") if "IWYU_TOOL" in ctx.env: Logs.info("Running include-what-you-use") cmd = [ctx.env.IWYU_TOOL[0], "-o", "clang", "-p", "build"] output = subprocess.check_output(cmd).decode('utf-8') if 'error: ' in output: sys.stdout.write(output) st += 1 else: Logs.warn("Not running include-what-you-use") if "CLANG_TIDY" in ctx.env and "clang" in ctx.env.CXX[0]: Logs.info("Running clang-tidy") import json with open('build/compile_commands.json', 'r') as db: commands = json.load(db) files = [c['file'] for c in commands] procs = [] for f in files: cmd = [ctx.env.CLANG_TIDY[0], '--quiet', '-p=.', f] procs += [subprocess.Popen(cmd, cwd='build')] for proc in procs: proc.communicate() st += proc.returncode else: Logs.warn("Not running clang-tidy") if st != 0: sys.exit(st)