From c39b290f02f49b68a3eb928fe1109cc7f6bf59eb Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Fri, 1 Jan 2021 22:16:21 +0100 Subject: [PATCH] Support for arm64 macOS builds. --- cscript | 16 ++++--- platform/osx/make_dmg.sh | 97 +++++++++++++++++++++++++++++----------- src/wx/wscript | 35 +++++++++------ wscript | 8 +++- 4 files changed, 109 insertions(+), 47 deletions(-) diff --git a/cscript b/cscript index 7b03b0e87..da68b8a6c 100644 --- a/cscript +++ b/cscript @@ -431,7 +431,10 @@ def configure_options(target, options): opt += ' --static-dcpomatic' if can_build_disk(target): - opt += ' --enable-disk' + opt += ' --enable-disk' + + if target.platform == 'osx' and target.arch == 'arm64': + opt += ' --target-macos-arm64 --wx-config=%s/wx-config' % target.bin return opt @@ -685,11 +688,14 @@ def package(target, version, options): return package_debian(target, cpu, version, options) elif target.distro == 'centos' or target.distro == 'fedora' or target.distro == 'mageia': return package_rpm(target, cpu, version, options) - elif target.platform == 'osx' and target.bits is None: - target.command('bash platform/osx/make_dmg.sh %s %s universal no %s %s' % (target.environment_prefix, target.directory, target.apple_id, target.apple_password)) + elif target.platform == 'osx' and hasattr(target, 'archs') and sorted(target.archs) == sorted(('arm64', 'x86_64')): + target.command('bash platform/osx/make_dmg.sh %s %s arm-intel-64 %s %s' % (target.environment_prefix, target.directory, target.apple_id, target.apple_password)) + return [os.path.abspath(x) for x in glob.glob('build/platform/osx/DCP-o-matic*.dmg')] + elif target.platform == 'osx' and hasattr(target, 'archs') and sorted(target.archs) == sorted(('i386', 'x86_64')): + target.command('bash platform/osx/make_dmg.sh %s %s intel-32-64 %s %s' % (target.environment_prefix, target.directory, target.apple_id, target.apple_password)) return [os.path.abspath(x) for x in glob.glob('build/platform/osx/DCP-o-matic*.dmg')] - elif target.platform == 'osx' and target.bits == 64: - target.command('bash platform/osx/make_dmg.sh %s %s thin %s %s' % (target.environment_prefix, target.directory, target.apple_id, target.apple_password)) + elif target.platform == 'osx' and hasattr(target, 'arch') and target.arch == 'arm64': + target.command('bash platform/osx/make_dmg.sh %s %s arm64 %s %s' % (target.environment_prefix, target.directory, target.apple_id, target.apple_password)) packages = [] for x in glob.glob('build/platform/osx/DCP-o-matic*.dmg'): a = os.path.abspath(x) diff --git a/platform/osx/make_dmg.sh b/platform/osx/make_dmg.sh index a6755e918..9603c9564 100644 --- a/platform/osx/make_dmg.sh +++ b/platform/osx/make_dmg.sh @@ -1,9 +1,9 @@ #!/bin/bash # SYNTAX="make_dmg.sh " -# where is universal or thin +# where is arm-intel-64, intel-32-64 or arm64 # -# e.g. make_dmg.sh /Users/carl/osx-environment /Users/carl/cdist universal foo@bar.net opensesame +# e.g. make_dmg.sh /Users/carl/osx-environment /Users/carl/cdist arm-intel-64 foo@bar.net opensesame # Don't set -e here as egrep (used a few times) returns 1 if no matches # were found. @@ -18,9 +18,9 @@ TYPE=$3 APPLE_ID=$4 APPLE_PASSWORD=$5 -if [ "$TYPE" != "universal" -a "$TYPE" != "thin" ]; then +if [ "$TYPE" != "arm-intel-64" -a "$TYPE" != "intel-32-64" -a "$TYPE" != "arm64" ]; then echo $SYNTAX - echo "where is universal or thin" + echo "where is arm-intel-64, intel-32-64 or arm64" exit 1 fi @@ -41,18 +41,29 @@ EOF function copy { case $TYPE in - universal) - for f in $1/32/$2; do + arm-intel-64) + for f in $1/arm64/$2; do if [ -h $f ]; then ln -s $(readlink $f) "$3/`basename $f`" else - g=`echo $f | sed -e "s/\/32\//\/64\//g"` + g=`echo $f | sed -e "s/\/arm64\//\/x86_64\//g"` mkdir -p "$3" lipo -create $f $g -output "$3/`basename $f`" fi done ;; - thin) + intel-32-64) + for f in $1/i386/$2; do + if [ -h $f ]; then + ln -s $(readlink $f) "$3/`basename $f`" + else + g=`echo $f | sed -e "s/\/i386\//\/x86_64\//g"` + mkdir -p "$3" + lipo -create $f $g -output "$3/`basename $f`" + fi + done + ;; + arm64) if [ -h $1/$2 ]; then ln -s $(readlink $1/$2) "$3/`basename $f`" else @@ -64,18 +75,29 @@ function copy { function copy_lib_root { case $TYPE in - universal) - for f in $ROOT/32/lib/$1*.dylib; do + arm-intel-64) + for f in $ROOT/arm64/lib/$1*.dylib; do + if [ -h $f ]; then + ln -s $(readlink $f) "$2/`basename $f`" + else + g=`echo $f | sed -e "s/\/arm64\//\/x86_64\//g"` + mkdir -p "$2" + lipo -create $f $g -output "$2/`basename $f`" + fi + done + ;; + intel-32-64) + for f in $ROOT/intel-32-64/lib/$1*.dylib; do if [ -h $f ]; then ln -s $(readlink $f) "$2/`basename $f`" else - g=`echo $f | sed -e "s/\/32\//\/64\//g"` + g=`echo $f | sed -e "s/\/i386\//\/x86_64\//g"` mkdir -p "$2" lipo -create $f $g -output "$2/`basename $f`" fi done ;; - thin) + arm64) for f in $ROOT/lib/$1*.dylib; do if [ -h $f ]; then ln -s $(readlink $f) "$2/`basename $f`" @@ -91,19 +113,30 @@ function copy_lib_root { function copy_lib_env { case $TYPE in - universal) - for f in $ENV/32/lib/$1*.dylib; do + arm-intel-64) + for f in $ENV/arm64/lib/$1*.dylib; do if [ -h $f ]; then ln -s $(readlink $f) "$2/`basename $f`" else - g=`echo $f | sed -e "s/\/32\//\/64\//g"` + g=`echo $f | sed -e "s/\/arm64\//\/x86_64\//g"` mkdir -p "$2" lipo -create $f $g -output "$2/`basename $f`" fi done ;; - thin) - for f in $ENV/64/lib/$1*.dylib; do + intel-32-64) + for f in $ENV/i386/lib/$1*.dylib; do + if [ -h $f ]; then + ln -s $(readlink $f) "$2/`basename $f`" + else + g=`echo $f | sed -e "s/\/i386\//\/x86_64\//g"` + mkdir -p "$2" + lipo -create $f $g -output "$2/`basename $f`" + fi + done + ;; + arm64) + for f in $ENV/arm64/lib/$1*.dylib; do if [ -h $f ]; then ln -s $(readlink $f) "$2/`basename $f`" else @@ -187,10 +220,13 @@ function copy_libs { function copy_resources { local dest="$1" case $TYPE in - universal) - local prefix=$ROOT/32 + arm-intel-64) + local prefix=$ROOT/x86_64 + ;; + intel-32-64) + local prefix=$ROOT/x86_64 ;; - thin) + arm64) local prefix=$ROOT ;; esac @@ -257,7 +293,7 @@ function copy_resources { # i18n: wxWidgets .mo files for lang in de es fr it sv nl ru pl da cs; do mkdir "$dest/$lang" - cp $ENV/64/share/locale/$lang/LC_MESSAGES/wxstd.mo "$dest/$lang" + cp $ENV/x86_64/share/locale/$lang/LC_MESSAGES/wxstd.mo "$dest/$lang" done } @@ -272,9 +308,11 @@ function relink_relative { for dep in $deps; do base=`basename $dep` if [ "$TYPE" == "universal" ]; then - # $dep will be a path within 64/; make a 32/ path too - dep32=`echo $dep | sed -e "s/\/64\//\/32\//g"` - changes="$changes -change $dep @executable_path/../Frameworks/$base -change $dep32 @executable_path/../Frameworks/$base" + # $dep will be a path within x86_64/; make i386 and arm64 paths too + dep_i386=`echo $dep | sed -e "s/\/x86_64\//\/i386\//g"` + changes="$changes -change $dep @executable_path/../Frameworks/$base -change $dep_i386 @executable_path/../Frameworks/$base" + dep_arm64=`echo $dep | sed -e "s/\/x86_64\//\/arm64\//g"` + changes="$changes -change $dep @executable_path/../Frameworks/$base -change $dep_arm64 @executable_path/../Frameworks/$base" else changes="$changes -change $dep @executable_path/../Frameworks/$base" fi @@ -436,10 +474,15 @@ function setup { } case $TYPE in - universal) - prefix=$ROOT/32 + arm-intel-64) + # copy() writes the universal binary to arm64 + prefix=$ROOT/arm64 + ;; + intel-32-64) + # copy() writes the universal binary to i386 + prefix=$ROOT/i386 ;; - thin) + arm64) prefix=$ROOT ;; esac diff --git a/src/wx/wscript b/src/wx/wscript index 989135587..bd428c81b 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -172,31 +172,40 @@ def configure(conf): wx_libs = 'core,richtext,adv,html,xml,propgrid' - try: - wx_config = '/usr/lib64/wx/config/gtk2-unicode-3.0' - conf.check_cfg(msg='Checking for wxWidgets using gtk2-unicode-3.0', + if conf.options.wx_config is not None: + wx_config = conf.options.wx_config + conf.check_cfg(msg='Checking for wxWidgets using %s' % wx_config, package='', path=wx_config, args='--cppflags --cxxflags --libs %s --gl-libs' % wx_libs, uselib_store='WXWIDGETS', mandatory=True) - except: + else: try: - wx_config = 'wx-config-3.0-gtk2' - conf.check_cfg(msg='Checking for wxWidgets using wx-config-3.0-gtk2', + wx_config = '/usr/lib64/wx/config/gtk2-unicode-3.0' + conf.check_cfg(msg='Checking for wxWidgets using gtk2-unicode-3.0', package='', path=wx_config, args='--cppflags --cxxflags --libs %s --gl-libs' % wx_libs, uselib_store='WXWIDGETS', mandatory=True) except: - wx_config = 'wx-config' - conf.check_cfg(msg='Checking for wxWidgets using wx-config', - package='', - path=wx_config, - args='--cppflags --cxxflags --libs %s --gl-libs' % wx_libs, - uselib_store='WXWIDGETS', - mandatory=True) + try: + wx_config = 'wx-config-3.0-gtk2' + conf.check_cfg(msg='Checking for wxWidgets using wx-config-3.0-gtk2', + package='', + path=wx_config, + args='--cppflags --cxxflags --libs %s --gl-libs' % wx_libs, + uselib_store='WXWIDGETS', + mandatory=True) + except: + wx_config = 'wx-config' + conf.check_cfg(msg='Checking for wxWidgets using wx-config', + package='', + path=wx_config, + args='--cppflags --cxxflags --libs %s --gl-libs' % wx_libs, + uselib_store='WXWIDGETS', + mandatory=True) if conf.env.TARGET_LINUX: conf.env.append_value('CXXFLAGS', ['-DGLX_GLXEXT_PROTOTYPES']) diff --git a/wscript b/wscript index ad1e137f2..171bfc935 100644 --- a/wscript +++ b/wscript @@ -58,7 +58,8 @@ def options(opt): 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('--install-prefix', default=None, help='prefix of where DCP-o-matic will be installed') - opt.add_option('--target-windows', action='store_true', default=False, help='set up to do a cross-compile to make a Windows package') + opt.add_option('--target-windows', action='store_true', default=False, help='set up to do a cross-compile for Windows') + 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') opt.add_option('--static-wxwidgets', action='store_true', default=False, help='link statically to wxWidgets') @@ -75,6 +76,7 @@ def options(opt): 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('--warnings-are-errors', action='store_true', default=False, help='build with -Werror') + opt.add_option('--wx-config', help='path to wx-config') def configure(conf): conf.load('compiler_cxx') @@ -101,7 +103,6 @@ def configure(conf): conf.env.append_value('CXXFLAGS', ['-D__STDC_CONSTANT_MACROS', '-D__STDC_LIMIT_MACROS', '-D__STDC_FORMAT_MACROS', - '-msse', '-fno-strict-aliasing', '-Wall', '-Wextra', @@ -116,6 +117,9 @@ def configure(conf): 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.env['CXX_NAME'] == 'gcc': gcc = conf.env['CC_VERSION'] if int(gcc[0]) >= 8: -- 2.30.2