mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Build universal binaries on macOS
This commit is contained in:
parent
e5cab43321
commit
e195b3a1e2
@ -25,7 +25,9 @@ from bypy.constants import (
|
||||
from bypy.freeze import (
|
||||
extract_extension_modules, fix_pycryptodome, freeze_python, path_to_freeze_dir
|
||||
)
|
||||
from bypy.utils import current_dir, mkdtemp, py_compile, timeit, walk
|
||||
from bypy.utils import (
|
||||
current_dir, get_arches_in_binary, mkdtemp, py_compile, timeit, walk
|
||||
)
|
||||
|
||||
abspath, join, basename, dirname = os.path.abspath, os.path.join, os.path.basename, os.path.dirname
|
||||
iv = globals()['init_env']
|
||||
@ -35,7 +37,7 @@ py_ver = '.'.join(map(str, python_major_minor_version()))
|
||||
sign_app = runpy.run_path(join(dirname(abspath(__file__)), 'sign.py'))['sign_app']
|
||||
|
||||
QT_PREFIX = join(PREFIX, 'qt')
|
||||
QT_FRAMEWORKS = [x.replace('5', '') for x in QT_DLLS]
|
||||
QT_FRAMEWORKS = [x.replace('6', '') for x in QT_DLLS]
|
||||
|
||||
ENV = dict(
|
||||
FONTCONFIG_PATH='@executable_path/../Resources/fonts',
|
||||
@ -56,7 +58,7 @@ def compile_launcher_lib(contents_dir, gcc, base, pyver, inc_dir):
|
||||
|
||||
dest = join(contents_dir, 'Frameworks', 'calibre-launcher.dylib')
|
||||
src = join(base, 'util.c')
|
||||
cmd = [gcc] + '-Wall -dynamiclib -std=gnu99'.split() + [src] + \
|
||||
cmd = [gcc] + '-arch x86_64 -arch arm64 -Wall -dynamiclib -std=gnu99'.split() + [src] + \
|
||||
['-I' + base] + '-DPY_VERSION_MAJOR={} -DPY_VERSION_MINOR={}'.format(*pyver.split('.')).split() + \
|
||||
[f'-I{path_to_freeze_dir()}', f'-I{inc_dir}'] + \
|
||||
[f'-DENV_VARS={env}', f'-DENV_VAR_VALS={env_vals}'] + \
|
||||
@ -87,7 +89,8 @@ def compile_launchers(contents_dir, inc_dir, xprograms, pyver):
|
||||
programs.append(out)
|
||||
is_gui = 'true' if ptype == 'gui' else 'false'
|
||||
cmd = [
|
||||
gcc, '-Wall', f'-DPROGRAM=L"{program}"', f'-DMODULE=L"{module}"', f'-DFUNCTION=L"{func}"', f'-DIS_GUI={is_gui}',
|
||||
gcc, '-Wall', '-arch', 'x86_64', '-arch', 'arm64',
|
||||
f'-DPROGRAM=L"{program}"', f'-DMODULE=L"{module}"', f'-DFUNCTION=L"{func}"', f'-DIS_GUI={is_gui}',
|
||||
'-I' + base, src, lib, '-o', out, '-headerpad_max_install_names'
|
||||
]
|
||||
# print('\t'+' '.join(cmd))
|
||||
@ -108,7 +111,14 @@ def flipwritable(fn, mode=None):
|
||||
return old_mode
|
||||
|
||||
|
||||
def check_universal(path):
|
||||
arches = get_arches_in_binary(path)
|
||||
if arches != EXPECTED_ARCHES:
|
||||
raise SystemExit(f'The file {path} is not a universal binary, it only has arches: {", ".join(arches)}')
|
||||
|
||||
|
||||
STRIPCMD = ['/usr/bin/strip', '-x', '-S', '-']
|
||||
EXPECTED_ARCHES = {'x86_64', 'arm64'}
|
||||
|
||||
|
||||
def strip_files(files, argv_max=(256 * 1024)):
|
||||
@ -272,6 +282,7 @@ class Freeze:
|
||||
|
||||
@flush
|
||||
def fix_dependencies_in_lib(self, path_to_lib):
|
||||
check_universal(path_to_lib)
|
||||
self.to_strip.append(path_to_lib)
|
||||
old_mode = flipwritable(path_to_lib)
|
||||
for dep, bname, is_id in self.get_local_dependencies(path_to_lib):
|
||||
|
@ -178,6 +178,9 @@ def get_python_include_paths():
|
||||
return sorted(frozenset(filter(None, map(gp, sorted(ans)))))
|
||||
|
||||
|
||||
is_macos_universal_build = ismacos and 'universal2' in sysconfig.get_platform()
|
||||
|
||||
|
||||
def init_env(debug=False, sanitize=False):
|
||||
from setup.build_environment import win_ld, is64bit, win_inc, win_lib, NMAKE, win_cc
|
||||
linker = None
|
||||
@ -222,6 +225,9 @@ def init_env(debug=False, sanitize=False):
|
||||
ldflags += (sysconfig.get_config_var('LINKFORSHARED') or '').split()
|
||||
|
||||
if ismacos:
|
||||
if is_macos_universal_build:
|
||||
cflags.extend(['-arch', 'x86_64', '-arch', 'arm64'])
|
||||
ldflags.extend(['-arch', 'x86_64', '-arch', 'arm64'])
|
||||
cflags.append('-D_OSX')
|
||||
ldflags.extend('-bundle -undefined dynamic_lookup'.split())
|
||||
cflags.extend(['-fno-common', '-dynamic'])
|
||||
@ -443,7 +449,7 @@ class Build(Command):
|
||||
def check_call(self, *args, **kwargs):
|
||||
"""print cmdline if an error occurred
|
||||
|
||||
If something is missing (qmake e.g.) you get a non-informative error
|
||||
If something is missing (cmake e.g.) you get a non-informative error
|
||||
self.check_call(qmc + [ext.name+'.pro'])
|
||||
so you would have to look at the source to see the actual command.
|
||||
"""
|
||||
@ -481,6 +487,8 @@ class Build(Command):
|
||||
if os.path.exists(bdir):
|
||||
shutil.rmtree(bdir)
|
||||
cmd = [CMAKE]
|
||||
if is_macos_universal_build:
|
||||
cmd += ['-DCMAKE_OSX_ARCHITECTURES=x86_64;arm64']
|
||||
if sw and os.path.exists(os.path.join(sw, 'qt')):
|
||||
cmd += ['-DCMAKE_SYSTEM_PREFIX_PATH=' + os.path.join(sw, 'qt').replace(os.sep, '/')]
|
||||
os.makedirs(bdir)
|
||||
@ -491,7 +499,7 @@ class Build(Command):
|
||||
self.check_call([self.env.make] + ['-j%d'%(cpu_count or 1)])
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
os.rename(self.j(bdir, 'libheadless.' + ('dylib' if ismacos else 'so')), target)
|
||||
os.rename(self.j(bdir, 'libheadless.so'), target)
|
||||
|
||||
def create_sip_build_skeleton(self, src_dir, ext):
|
||||
from setup.build_environment import pyqt_sip_abi_version
|
||||
|
@ -159,6 +159,7 @@ elif ismacos:
|
||||
sw = os.environ.get('SW', os.path.expanduser('~/sw'))
|
||||
sw_inc_dir = os.path.join(sw, 'include')
|
||||
sw_lib_dir = os.path.join(sw, 'lib')
|
||||
sw_bin_dir = os.path.join(sw, 'bin')
|
||||
podofo_inc = os.path.join(sw_inc_dir, 'podofo')
|
||||
hunspell_inc_dirs = [os.path.join(sw_inc_dir, 'hunspell')]
|
||||
podofo_lib = sw_lib_dir
|
||||
@ -167,6 +168,8 @@ elif ismacos:
|
||||
SSL = os.environ.get('OPENSSL_DIR', os.path.join(sw, 'private', 'ssl'))
|
||||
openssl_inc_dirs = [os.path.join(SSL, 'include')]
|
||||
openssl_lib_dirs = [os.path.join(SSL, 'lib')]
|
||||
if os.path.exists(os.path.join(sw_bin_dir, 'cmake')):
|
||||
CMAKE = os.path.join(sw_bin_dir, 'cmake')
|
||||
else:
|
||||
ft_inc_dirs = pkgconfig_include_dirs('freetype2', 'FT_INC_DIR',
|
||||
'/usr/include/freetype2')
|
||||
|
Loading…
x
Reference in New Issue
Block a user