X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=wscript;h=6dd7417cda41fefa7cd0b76389a0f829820f7523;hb=ffc489c67f97366016e51de9390eb3f6841ad069;hp=4b3164f71e16d6101133c96c504a0318f630eb54;hpb=8aa97c043d73e0c6c8bc484a307b944702c7d3dd;p=dcpomatic.git diff --git a/wscript b/wscript index 4b3164f71..6dd7417cd 100644 --- a/wscript +++ b/wscript @@ -35,9 +35,11 @@ except ImportError: from waflib import Logs, Context APPNAME = 'dcpomatic' +libdcp_version = '1.8.73' +libsub_version = '1.6.42' this_version = subprocess.Popen(shlex.split('git tag -l --points-at HEAD'), stdout=subprocess.PIPE).communicate()[0] -last_version = subprocess.Popen(shlex.split('git describe --tags --abbrev=0'), stdout=subprocess.PIPE).communicate()[0] +last_version = subprocess.Popen(shlex.split('git describe --tags --match v* --abbrev=0'), stdout=subprocess.PIPE).communicate()[0] # Python 2/3 compatibility; I don't really understand what's going on here if not isinstance(this_version, str): @@ -45,7 +47,7 @@ if not isinstance(this_version, str): if not isinstance(last_version, str): last_version = last_version.decode('utf-8') -if this_version == '': +if this_version == '' or this_version == 'merged-to-main': VERSION = '%sdevel' % last_version[1:].strip() else: VERSION = this_version[1:].strip() @@ -57,7 +59,8 @@ def options(opt): opt.add_option('--enable-debug', action='store_true', default=False, help='build with debugging information and without optimisation') opt.add_option('--disable-gui', action='store_true', default=False, help='disable building of GUI tools') opt.add_option('--disable-tests', action='store_true', default=False, help='disable building of tests') - opt.add_option('--target-windows', action='store_true', default=False, help='set up to do a cross-compile for Windows') + opt.add_option('--target-windows-64', action='store_true', default=False, help='set up to do a cross-compile for Windows 64-bit') + opt.add_option('--target-windows-32', action='store_true', default=False, help='set up to do a cross-compile for Windows 32-bit') opt.add_option('--target-macos-arm64', action='store_true', default=False, help='set up to do a cross-compile for macOS arm64') opt.add_option('--static-dcpomatic', action='store_true', default=False, help='link to components of DCP-o-matic statically') opt.add_option('--static-boost', action='store_true', default=False, help='link statically to Boost') @@ -73,27 +76,32 @@ def options(opt): opt.add_option('--workaround-gssapi', action='store_true', default=False, help='link to gssapi_krb5') opt.add_option('--use-lld', action='store_true', default=False, help='use lld linker') opt.add_option('--enable-disk', action='store_true', default=False, help='build dcpomatic2_disk tool; requires Boost process, lwext4 and nanomsg libraries') + opt.add_option('--enable-grok', action='store_true', default=False, help='build with support for grok J2K encoder') opt.add_option('--warnings-are-errors', action='store_true', default=False, help='build with -Werror') opt.add_option('--wx-config', help='path to wx-config') + opt.add_option('--enable-asan', action='store_true', help='build with asan') + opt.add_option('--disable-more-warnings', action='store_true', default=False, help='disable some warnings raised by Xcode 15 with the 2.16 branch') def configure(conf): conf.load('compiler_cxx') conf.load('clang_compilation_database', tooldir=['waf-tools']) - if conf.options.target_windows: + if conf.options.target_windows_64 or conf.options.target_windows_32: conf.load('winres') # Save conf.options that we need elsewhere in conf.env conf.env.DISABLE_GUI = conf.options.disable_gui conf.env.DISABLE_TESTS = conf.options.disable_tests - conf.env.TARGET_WINDOWS = conf.options.target_windows + conf.env.TARGET_WINDOWS_64 = conf.options.target_windows_64 + conf.env.TARGET_WINDOWS_32 = conf.options.target_windows_32 conf.env.TARGET_OSX = sys.platform == 'darwin' - conf.env.TARGET_LINUX = not conf.env.TARGET_WINDOWS and not conf.env.TARGET_OSX + conf.env.TARGET_LINUX = not conf.env.TARGET_WINDOWS_64 and not conf.env.TARGET_WINDOWS_32 and not conf.env.TARGET_OSX conf.env.VERSION = VERSION conf.env.DEBUG = conf.options.enable_debug conf.env.STATIC_DCPOMATIC = conf.options.static_dcpomatic conf.env.ENABLE_DISK = conf.options.enable_disk - if conf.options.destdir is None: - conf.env.INSTALL_PREFIX = conf.env.PREFIX + conf.env.ENABLE_GROK = conf.options.enable_grok + if conf.options.destdir == '': + conf.env.INSTALL_PREFIX = conf.options.prefix else: conf.env.INSTALL_PREFIX = conf.options.destdir @@ -105,27 +113,45 @@ def configure(conf): '-Wall', '-Wextra', '-Wwrite-strings', + # getMessengerLogger() in the grok code triggers these warnings + '-Wno-nonnull', + '-Wno-error=deprecated', # I tried and failed to ignore these with _Pragma '-Wno-ignored-qualifiers', '-D_FILE_OFFSET_BITS=64', '-std=c++11']) + if conf.options.disable_more_warnings: + # These are for Xcode 15.0.1 with the v2.16.x-era + # dependencies; maybe they aren't necessary when building + # v2.1{7,8}.x + conf.env.append_value('CXXFLAGS', ['-Wno-deprecated-builtins', + '-Wno-deprecated-declarations', + '-Wno-enum-constexpr-conversion', + '-Wno-deprecated-copy']) + if conf.options.warnings_are_errors: conf.env.append_value('CXXFLAGS', '-Werror') if not conf.options.target_macos_arm64: conf.env.append_value('CXXFLAGS', '-msse') + if conf.options.enable_asan: + conf.env.append_value('CXXFLAGS', '-fsanitize=address') + conf.env.append_value('LINKFLAGS', '-fsanitize=address') + if conf.env['CXX_NAME'] == 'gcc': gcc = conf.env['CC_VERSION'] if int(gcc[0]) >= 8: # I tried and failed to ignore these with _Pragma conf.env.append_value('CXXFLAGS', ['-Wno-cast-function-type']) - have_c11 = int(gcc[0]) >= 4 and int(gcc[1]) >= 8 and int(gcc[2]) >= 1 # Most gccs still give these warnings from boost::optional conf.env.append_value('CXXFLAGS', ['-Wno-maybe-uninitialized']) - else: - have_c11 = False + if int(gcc[0]) > 8: + # gcc 4.8.5 on Centos 7 does not have this warning + # gcc 7.5.0 on Ubuntu 18.04 and gcc 8.3.0 on Debian 10 do, but + # I didn't manage to turn it back off again with a pragma + conf.env.append_value('CXXFLAGS', ['-Wsuggest-override']) if conf.options.enable_debug: conf.env.append_value('CXXFLAGS', ['-g', '-DDCPOMATIC_DEBUG', '-fno-omit-frame-pointer']) @@ -135,6 +161,9 @@ def configure(conf): if conf.options.enable_disk: conf.env.append_value('CXXFLAGS', '-DDCPOMATIC_DISK') + if conf.options.enable_grok: + conf.env.append_value('CXXFLAGS', '-DDCPOMATIC_GROK') + if conf.options.use_lld: try: conf.find_program('ld.lld') @@ -143,15 +172,14 @@ def configure(conf): pass # - # Windows/Linux/OS X specific + # Windows/Linux/macOS specific # # Windows - if conf.env.TARGET_WINDOWS: + if conf.env.TARGET_WINDOWS_64 or conf.env.TARGET_WINDOWS_32: conf.env.append_value('CXXFLAGS', '-DDCPOMATIC_WINDOWS') conf.env.append_value('CXXFLAGS', '-DWIN32_LEAN_AND_MEAN') conf.env.append_value('CXXFLAGS', '-DBOOST_USE_WINDOWS_H') - conf.env.append_value('CXXFLAGS', '-DUNICODE') conf.env.append_value('CXXFLAGS', '-DBOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN') conf.env.append_value('CXXFLAGS', '-mfpmath=sse') conf.env.append_value('CXXFLAGS', '-Wcast-align') @@ -169,8 +197,9 @@ def configure(conf): conf.check(lib='winmm', uselib_store='WINMM', msg="Checking for library winmm") conf.check(lib='ksuser', uselib_store='KSUSER', msg="Checking for library ksuser") conf.check(lib='setupapi', uselib_store='SETUPAPI', msg="Checking for library setupapi") - boost_lib_suffix = '-mt' - boost_thread = 'boost_thread-mt' + conf.check(lib='uuid', uselib_store='UUID', msg="Checking for library uuid") + boost_lib_suffix = '-mt-x32' if conf.options.target_windows_32 else '-mt-x64' + boost_thread = 'boost_thread' + boost_lib_suffix conf.check_cxx(fragment=""" #include \n int main() { std::locale::global (boost::locale::generator().generate ("")); }\n @@ -200,6 +229,7 @@ def configure(conf): if conf.env.TARGET_OSX: conf.env.append_value('CXXFLAGS', ['-DDCPOMATIC_OSX', '-DGL_SILENCE_DEPRECATION']) conf.env.append_value('LINKFLAGS', '-headerpad_max_install_names') + conf.env.append_value('LINKFLAGS', '-llzma') # # Dependencies. @@ -215,7 +245,7 @@ def configure(conf): conf.env.STLIB_CURL = ['curl'] conf.env.LIB_CURL = ['ssh2', 'idn'] else: - conf.check_cfg(package='libcurl', args='--cflags --libs', atleast_version='7.19.1', uselib_store='CURL', mandatory=True) + conf.check_cfg(package='libcurl', args='libcurl >= 7.19.1 --cflags --libs', uselib_store='CURL', mandatory=True) # libicu if conf.check_cfg(package='icu-i18n', args='--cflags --libs', uselib_store='ICU', mandatory=False) is None: @@ -244,13 +274,31 @@ def configure(conf): conf.check_cfg(package='libzip', args='--cflags --libs', uselib_store='ZIP', mandatory=True) conf.check_cxx(fragment=""" #include - int main() { zip_source_t* foo; } + int main() { zip_source_t* foo; (void)foo; } """, mandatory=False, msg="Checking for zip_source_t", uselib="ZIP", define_name='DCPOMATIC_HAVE_ZIP_SOURCE_T' ) + conf.check_cxx(fragment=""" + #include + int main() { struct zip* zip = nullptr; zip_source_t* source = nullptr; zip_file_add(zip, "foo", source, ZIP_FL_ENC_GUESS); } + """, + mandatory=False, + msg="Checking for zip_file_add", + uselib="ZIP", + define_name='DCPOMATIC_HAVE_ZIP_FILE_ADD' + ) + conf.check_cxx(fragment=""" + #include + int main() { int error; zip_open("foo", ZIP_RDONLY, &error); } + """, + mandatory=False, + msg="Checking for ZIP_RDONLY", + uselib="ZIP", + define_name='DCPOMATIC_HAVE_ZIP_RDONLY' + ) # libbz2; must be explicitly linked on macOS for some reason conf.check_cxx(fragment=""" @@ -264,6 +312,18 @@ def configure(conf): uselib_store="BZ2" ) + # libz; must be explicitly linked on macOS for some reason + conf.check_cxx(fragment=""" + #include + int main() { zlibVersion(); } + """, + mandatory=True, + msg="Checking for libz", + okmsg='yes', + lib='z', + uselib_store="LIBZ" + ) + # fontconfig conf.check_cfg(package='fontconfig', args='--cflags --libs', uselib_store='FONTCONFIG', mandatory=True) @@ -276,43 +336,12 @@ def configure(conf): # leqm_nrt conf.check_cfg(package='leqm_nrt', args='--cflags --libs', uselib_store='LEQM_NRT', mandatory=True) - # See if we have Cairo::ImageSurface::format_stride_for_width; Centos 5 does not - conf.check_cxx(fragment=""" - #include - int main(void) { - Cairo::ImageSurface::format_stride_for_width (Cairo::FORMAT_ARGB32, 1024);\n - return 0; }\n - """, - mandatory=False, - msg='Checking for format_stride_for_width', - okmsg='yes', - includes=conf.env['INCLUDES_CAIROMM'], - uselib='CAIROMM', - define_name='DCPOMATIC_HAVE_FORMAT_STRIDE_FOR_WIDTH') - - # See if we have Pango::Layout::show_in_cairo_context; Centos 5 does not - conf.check_cxx(fragment=""" - #include - int main(void) { - Cairo::RefPtr context; - Glib::RefPtr layout; - layout->show_in_cairo_context (context); - return 0; }\n - """, - mandatory=False, - msg='Checking for show_in_cairo_context', - okmsg='yes', - includes=conf.env['INCLUDES_PANGOMM'], - uselib='PANGOMM', - define_name='DCPOMATIC_HAVE_SHOW_IN_CAIRO_CONTEXT') - - # libcxml if conf.options.static_cxml: - conf.check_cfg(package='libcxml', atleast_version='0.17.0', args='--cflags', uselib_store='CXML', mandatory=True) + conf.check_cfg(package='libcxml', args='libcxml >= 0.17.0 --cflags', uselib_store='CXML', mandatory=True) conf.env.STLIB_CXML = ['cxml'] else: - conf.check_cfg(package='libcxml', atleast_version='0.16.0', args='--cflags --libs', uselib_store='CXML', mandatory=True) + conf.check_cfg(package='libcxml', args='libcxml >= 0.16.0 --cflags --libs', uselib_store='CXML', mandatory=True) # libssh if conf.options.static_ssh: @@ -334,21 +363,21 @@ def configure(conf): # libdcp if conf.options.static_dcp: - conf.check_cfg(package='libdcp-1.0', atleast_version='1.6.7', args='--cflags', uselib_store='DCP', mandatory=True) + conf.check_cfg(package='libdcp-1.0', args='libdcp-1.0 >= %s --cflags' % libdcp_version, uselib_store='DCP', mandatory=True) conf.env.DEFINES_DCP = [f.replace('\\', '') for f in conf.env.DEFINES_DCP] conf.env.STLIB_DCP = ['dcp-1.0', 'asdcp-carl', 'kumu-carl', 'openjp2'] conf.env.LIB_DCP = ['glibmm-2.4', 'ssl', 'crypto', 'bz2', 'xslt', 'xerces-c'] else: - conf.check_cfg(package='libdcp-1.0', atleast_version='1.6.7', args='--cflags --libs', uselib_store='DCP', mandatory=True) + conf.check_cfg(package='libdcp-1.0', args='libdcp-1.0 >= %s --cflags --libs' % libdcp_version, uselib_store='DCP', mandatory=True) conf.env.DEFINES_DCP = [f.replace('\\', '') for f in conf.env.DEFINES_DCP] # libsub if conf.options.static_sub: - conf.check_cfg(package='libsub-1.0', atleast_version='1.4.7', args='--cflags', uselib_store='SUB', mandatory=True) + conf.check_cfg(package='libsub-1.0', args='libsub-1.0 >= %s --cflags' % libsub_version, uselib_store='SUB', mandatory=True) conf.env.DEFINES_SUB = [f.replace('\\', '') for f in conf.env.DEFINES_SUB] conf.env.STLIB_SUB = ['sub-1.0'] else: - conf.check_cfg(package='libsub-1.0', atleast_version='1.4.7', args='--cflags --libs', uselib_store='SUB', mandatory=True) + conf.check_cfg(package='libsub-1.0', args='libsub-1.0 >= %s --cflags --libs' % libsub_version, uselib_store='SUB', mandatory=True) conf.env.DEFINES_SUB = [f.replace('\\', '') for f in conf.env.DEFINES_SUB] # libxml++ @@ -373,6 +402,18 @@ def configure(conf): # libpng conf.check_cfg(package='libpng', args='--cflags --libs', uselib_store='PNG', mandatory=True) + # libjpeg + conf.check_cxx(fragment=""" + #include + #include + #include + int main() { struct jpeg_compress_struct compress; jpeg_create_compress (&compress); return 0; } + """, + msg='Checking for libjpeg', + libpath='/usr/local/lib', + lib=['jpeg'], + uselib_store='JPEG') + # lwext4 if conf.options.enable_disk: conf.check_cxx(fragment=""" @@ -436,7 +477,7 @@ def configure(conf): int main () { av_ebur128_get_true_peaks (0); }\n """, msg='Checking for EBUR128-patched FFmpeg', - uselib='AVCODEC AVFILTER', + uselib='AVCODEC AVFILTER AVUTIL SWRESAMPLE', define_name='DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG', mandatory=False) @@ -468,6 +509,19 @@ def configure(conf): define_name='DCPOMATIC_HAVE_AVCOMPONENTDESCRIPTOR_DEPTH_MINUS1', mandatory=False) + # See if we have av_register_all and avfilter_register_all + conf.check_cxx(fragment=""" + extern "C" {\n + #include \n + #include \n + }\n + int main () { av_register_all(); avfilter_register_all(); }\n + """, + msg='Checking for av_register_all and avfilter_register_all', + uselib='AVFORMAT AVFILTER', + define_name='DCPOMATIC_HAVE_AVREGISTER', + mandatory=False) + # Hack: the previous two check_cxx calls end up copying their (necessary) cxxflags # to these variables. We don't want to use these for the actual build, so clean them out. conf.env['CXXFLAGS_AVCODEC'] = [] @@ -547,7 +601,7 @@ def configure(conf): # program has to link with boost_system so I'm doing it this way. if conf.options.enable_disk: deps = ['boost_system%s' % boost_lib_suffix] - if conf.env.TARGET_WINDOWS: + if conf.env.TARGET_WINDOWS_64 or conf.env.TARGET_WINDOWS_32: deps.append('ws2_32') deps.append('boost_filesystem%s' % boost_lib_suffix) conf.check_cxx(fragment=""" @@ -576,12 +630,12 @@ def configure(conf): conf.recurse('test') Logs.pprint('YELLOW', '') - if conf.env.TARGET_WINDOWS: + if conf.env.TARGET_WINDOWS_64 or conf.env.TARGET_WINDOWS_32: Logs.pprint('YELLOW', '\t' + 'Target'.ljust(25) + ': Windows') elif conf.env.TARGET_LINUX: Logs.pprint('YELLOW', '\t' + 'Target'.ljust(25) + ': Linux') elif conf.env.TARGET_OSX: - Logs.pprint('YELLOW', '\t' + 'Target'.ljust(25) + ': OS X') + Logs.pprint('YELLOW', '\t' + 'Target'.ljust(25) + ': macOS') def report(name, variable): linkage = '' @@ -604,38 +658,37 @@ def configure(conf): Logs.pprint('YELLOW', '') -def download_supporters(can_fail): - r = os.system('curl -m 2 -s -f https://dcpomatic.com/supporters.cc > src/wx/supporters.cc') - if (r >> 8) == 0: - r = os.system('curl -s -f https://dcpomatic.com/subscribers.cc > src/wx/subscribers.cc') - if (r >> 8) != 0: - if can_fail: - raise Exception("Could not download supporters lists (%d)" % (r >> 8)) - else: - f = open('src/wx/supporters.cc', 'w') - print('supported_by.Add(wxT("Debug build - no supporters lists available"));', file=f) - f.close() - f = open('src/wx/subscribers.cc', 'w') - print('subscribers.Add(wxT("Debug build - no subscribers lists available"));', file=f) - f.close() - def build(bld): create_version_cc(VERSION, bld.env.CXXFLAGS) - download_supporters(not bld.env.DEBUG) + + # waf can't find these dependencies by itself because they are only included if DCPOMATIC_GROK is defined, + # and I can't find a way to pass that to waf's dependency scanner + if bld.env.ENABLE_GROK: + for dep in ( + 'src/lib/j2k_encoder.cc', + 'src/tools/dcpomatic.cc', + 'src/tools/dcpomatic_server.cc', + 'src/tools/dcpomatic_server_cli.cc', + 'src/tools/dcpomatic_batch.cc' + ): + bld.add_manual_dependency(bld.path.find_node(dep), bld.path.find_node('src/lib/grok/context.h')) + bld.add_manual_dependency(bld.path.find_node(dep), bld.path.find_node('src/lib/grok/messenger.h')) + + bld.add_manual_dependency(bld.path.find_node('src/wx/full_config_dialog.cc'), bld.path.find_node('src/wx/grok/gpu_config_panel.h')) bld.recurse('src') bld.recurse('graphics') if not bld.env.DISABLE_TESTS: bld.recurse('test') - if bld.env.TARGET_WINDOWS: + if bld.env.TARGET_WINDOWS_64 or bld.env.TARGET_WINDOWS_32: bld.recurse('platform/windows') if bld.env.TARGET_LINUX: bld.recurse('platform/linux') if bld.env.TARGET_OSX: bld.recurse('platform/osx') - if not bld.env.TARGET_WINDOWS: + if not bld.env.TARGET_WINDOWS_64 and not bld.env.TARGET_WINDOWS_32: bld.install_files('${PREFIX}/share/dcpomatic2', 'fonts/LiberationSans-Regular.ttf') bld.install_files('${PREFIX}/share/dcpomatic2', 'fonts/LiberationSans-Italic.ttf') bld.install_files('${PREFIX}/share/dcpomatic2', 'fonts/LiberationSans-Bold.ttf') @@ -697,16 +750,9 @@ def create_version_cc(version, cxx_flags): def post(ctx): if ctx.cmd == 'install' and ctx.env.TARGET_LINUX: ctx.exec_command('/sbin/ldconfig') - # setuid root executables - for e in ['dcpomatic2_uuid', 'dcpomatic2_disk_writer']: - # I can't find anything which tells me where things have been installed to, - # so here's some nasty hacks to guess. - debian = os.path.join(ctx.out_dir, '../debian/dcpomatic/usr/bin/%s' % e) - prefix = os.path.join(ctx.env['INSTALL_PREFIX'], 'bin/%s' % e) - if os.path.exists(debian): - os.chmod(debian, 0o4755) - if os.path.exists(prefix): - os.chmod(prefix, 0o4755) + exe = os.path.join(ctx.env['INSTALL_PREFIX'], 'bin/dcpomatic2_disk_writer') + if os.path.exists(exe): + os.system('setcap "cap_dac_override+ep cap_sys_admin+ep" %s' % exe) def pot(bld): bld.recurse('src') @@ -714,6 +760,13 @@ def pot(bld): def pot_merge(bld): bld.recurse('src') +def supporters(bld): + r = os.system('curl -m 2 -s -f https://dcpomatic.com/supporters.cc > src/wx/supporters.cc') + if (r >> 8) == 0: + r = os.system('curl -s -f https://dcpomatic.com/subscribers.cc > src/wx/subscribers.cc') + if (r >> 8) != 0: + raise Exception("Could not download supporters lists (%d)" % (r >> 8)) + def tags(bld): os.system('etags src/lib/*.cc src/lib/*.h src/wx/*.cc src/wx/*.h src/tools/*.cc')