@@ -543,7 +543,7 @@ def build(self, directory: Path) -> pathlib.Path:
543
543
544
544
545
545
MesonArgsKeys = Literal ['dist' , 'setup' , 'compile' , 'install' ]
546
- MesonArgs = Mapping [MesonArgsKeys , Collection [str ]]
546
+ MesonArgs = Mapping [MesonArgsKeys , List [str ]]
547
547
548
548
549
549
class Project ():
@@ -554,7 +554,7 @@ class Project():
554
554
]
555
555
_metadata : Optional [pyproject_metadata .StandardMetadata ]
556
556
557
- def __init__ (
557
+ def __init__ ( # noqa: C901
558
558
self ,
559
559
source_dir : Path ,
560
560
working_dir : Path ,
@@ -566,13 +566,41 @@ def __init__(
566
566
self ._build_dir = pathlib .Path (build_dir ).absolute () if build_dir else (self ._working_dir / 'build' )
567
567
self ._install_dir = self ._working_dir / 'install'
568
568
self ._meson_native_file = self ._source_dir / '.mesonpy-native-file.ini'
569
+ self ._meson_cross_file = self ._source_dir / '.mesonpy-cross-file.ini'
570
+ self ._meson_args : MesonArgs = collections .defaultdict (list )
569
571
self ._env = os .environ .copy ()
570
572
571
573
# prepare environment
572
574
ninja_path = _env_ninja_command ()
573
575
if ninja_path is not None :
574
576
self ._env .setdefault ('NINJA' , str (ninja_path ))
575
577
578
+ # setuptools-like ARCHFLAGS environment variable support
579
+ if sysconfig .get_platform ().startswith ('macosx-' ):
580
+ archflags = self ._env .get ('ARCHFLAGS' )
581
+ if archflags is not None :
582
+ arch , * other = filter (None , (x .strip () for x in archflags .split ('-arch' )))
583
+ if other :
584
+ raise ConfigError (f'multi-architecture builds are not supported but $ARCHFLAGS={ archflags !r} ' )
585
+ macver , _ , nativearch = platform .mac_ver ()
586
+ if arch != nativearch :
587
+ x = self ._env .setdefault ('_PYTHON_HOST_PLATFORM' , f'macosx-{ macver } -{ arch } ' )
588
+ if not x .endswith (arch ):
589
+ raise ConfigError (f'$ARCHFLAGS={ archflags !r} and $_PYTHON_HOST_PLATFORM={ x !r} do not agree' )
590
+ family = 'aarch64' if arch == 'arm64' else arch
591
+ cross_file_data = textwrap .dedent (f'''
592
+ [binaries]
593
+ c = ['cc', '-arch', { arch !r} ]
594
+ cpp = ['cpp', '-arch', { arch !r} ]
595
+ [host_machine]
596
+ system = 'Darwin'
597
+ cpu = { arch !r}
598
+ cpu_family = { family !r}
599
+ endian = 'little'
600
+ ''' )
601
+ self ._meson_cross_file .write_text (cross_file_data )
602
+ self ._meson_args ['setup' ].extend (('--cross-file' , os .fspath (self ._meson_cross_file )))
603
+
576
604
# load config -- PEP 621 support is optional
577
605
self ._config = tomllib .loads (self ._source_dir .joinpath ('pyproject.toml' ).read_text ())
578
606
self ._pep621 = 'project' in self ._config
@@ -594,16 +622,20 @@ def __init__(
594
622
self ._validate_metadata ()
595
623
596
624
# load meson args
597
- self ._meson_args = collections .defaultdict (tuple , meson_args or {})
598
625
for key in self ._get_config_key ('args' ):
599
- args_from_config = tuple (self ._get_config_key (f'args.{ key } ' ))
600
- self ._meson_args [key ] = args_from_config + tuple (self ._meson_args [key ])
626
+ self ._meson_args [key ].extend (self ._get_config_key (f'args.{ key } ' ))
601
627
# XXX: We should validate the user args to make sure they don't conflict with ours.
602
628
603
629
self ._check_for_unknown_config_keys ({
604
630
'args' : typing_get_args (MesonArgsKeys ),
605
631
})
606
632
633
+ # meson arguments from the command line take precedence over
634
+ # arguments from the configuration file thus are added later
635
+ if meson_args :
636
+ for key , value in meson_args .items ():
637
+ self ._meson_args [key ].extend (value )
638
+
607
639
# make sure the build dir exists
608
640
self ._build_dir .mkdir (exist_ok = True )
609
641
self ._install_dir .mkdir (exist_ok = True )
0 commit comments