Support for arm64 macOS builds.
authorCarl Hetherington <cth@carlh.net>
Fri, 1 Jan 2021 21:16:21 +0000 (22:16 +0100)
committerCarl Hetherington <cth@carlh.net>
Mon, 4 Jan 2021 09:48:59 +0000 (10:48 +0100)
cscript
platform/osx/make_dmg.sh
src/wx/wscript
wscript

diff --git a/cscript b/cscript
index 7b03b0e87bca8b4d01af9c1f7626c6245f223391..da68b8a6c626e8e52605bc47d423ff14e1fdc483 100644 (file)
--- 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)
index a6755e918a6613273b88d81a83009471b258cb45..9603c95641a047de9f339b74f8ff08f766ca783c 100644 (file)
@@ -1,9 +1,9 @@
 #!/bin/bash
 #
 SYNTAX="make_dmg.sh <environment> <builddir> <type> <apple-id> <apple-password>"
-# where <type> is universal or thin
+# where <type> 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 <type> is universal or thin"
+    echo "where <type> 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
index 989135587ab4ce646aa3aa57d5f4156be70e844f..bd428c81bb54bd52ec761598c8cddffbcad094c2 100644 (file)
@@ -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 ad1e137f22d24f23bc59f621b8615089dfa33ba6..171bfc935c9b0532c03f480d209d2e6aab1112b1 100644 (file)
--- 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: