Closed barracuda156 closed 2 months ago
I don't understand which problem you are trying to solve. The code you modify is executed only if the $ARCHFLAGS
environment variable is set. This environment variable is used for cross compilation. Why are you setting the $ARCHFLAGS
variable when apparently you are compiling on on PPC for PPC? What does Rosetta have to do with this? Do you mean that you are running a Python compiled for x86_64 on PPC via Rosetta?
The code you modify is executed only if the $ARCHFLAGS environment variable is set.
For every architecture, AFAIU, nativearch value from platform.mac_ver()
will be identical to build arch value (when they are actually the same), but not for PowerPC (where the arch value is ppc
/ppc64
, but platform.mac_ver()
gives out PowerPC
or Power Macintosh
).
ARCHFLAGS may be there in environment for different reasons, not necessarily cross-compilation. Why should they break something?
What does Rosetta have to do with this
This was primarily a clarification (for those who may wonder how come I have ppc
on 10.6.8). Also the value for machine on native PowerPC is usually Power Macintosh
(but cython
accounts for that).
ARCHFLAGS may be there in environment for different reasons, not necessarily cross-compilation. Why should they break something?
$ARCHFALGS
is supported in meson-python only for the purpose of cross compilation. What else do you want to do with it? To which value do you set this environment variable?
ARCHFALGS is supported in meson-python only for the purpose of cross compilation
Not an exhaustive list, but:
To which value do you set this environment variable?
In my case it will be -arch ppc
(or -arch ppc64
if built for ppc64
).
Which tools do look at the $ARCHFLAGS
environment variable? AFAIK it is a setuptools invention. Therefore, if you are not building with setuptools, there is no reason to ever set it. Your patch makes $ARCHFLAGS
have no effect at all, thus I don't understand why you say that it is required to set it.
I readily admit that my proposed fix may not be optimal, so if there is a better way to do this, let’s change it.
My concern is the following:
The existing code conditions on something which evaluates as false in 100% of cases (for PowerPC) (I meant those values are never equal; condition is ≠, so true in 100% of cases, but anyway). If it has been already established that we are cross-compiling, then at best this condition is redundant. If it is not redundant, then it does not work correctly for a case of macOS PowerPC.
While admittedly this problem may ever affect very few people, it breaks the build in a rather non-obvious way, with wrong compiler being picked, in violation of environment settings, and nothing in the error output says what to do. Yes, we could fix it locally in Macports, but then someone else eventually wastes a day trying to figure out what goes wrong.
@dnicolodi Provided that condition is not redundant (which, I assume, is the case), what we want – hopefully – is for it to actually work, for every arch. For PowerPC there are two archs (ppc and ppc64), and compilers on Darwin use respective flags: -arch ppc
and -arch ppc64
. AFAIU, the code strips the flags to convert into build arch values (which is correct). What is not correct is to use machine
to infer the arch:
– it never differentiates between the two (there is no possible way for it to guess which arch one wants, the return value is always Power Macintosh
(or PowerPC
);
– return value from machine will never be equal to build arch: they are different strings.
Due to the former issue it will not work to mechanically define something like PowerPC == ppc
. Instead, maybe a code from cython
can be borrowed, if relying on a ready-made function does not work for needed purposes.
(Perhaps I should have explained a bit in detail from the beginning, sorry.)
I don't understand what you are trying to do, what the behavior you observe is, and what the behavior you want should be. Piecing together the information you provided, I understand that you compile with $ARCHFLAGS
set to -arch ppc
or -arch ppc64
and you expect this to be reflected in the flags passed to the compiler during package build. If this is the case, the code is working just fine as it is: it detects that the value for the -arch
options passed in $ARCHFLAGS
is not the system architecture, and it synthesizes a cross file to pass to meson specifying the desired -arch
flag. If you don't want the -arch
flags passed to the compiler, just don't set the $ARCHFLAGS
environment variable.
In particular, this statement does not reflect how the code you are modifying behaves:
This makes the build system believe it is cross-compiling, and if the cross-file is not provided (and in
Numpy
it is not, for example), disaster ensues:
If meson-python detects that $ARCHFLAGS
is used to specify an architecture that is not the system one, it synthesizes a cross file and passes it to Meson. Therefore the user is not expected to provide one. I don't see what this has to do with the linked bug report where the build fails because the cython
compiler is not found.
it detects that the value for the -arch options passed in $ARCHFLAGS is not the system architecture
But it is. I do not know what to add to already explained above. There is no archflag “PowerPC”. There is no machine value ppc
or ppc64
. Comparing these two is a meaningless endeavor: the condition of non-equality is always true, since these values are never identical. Is it supposed to be always true? Then it can be just removed with no consequences.
That is, logically it is just wrong. In practice, independently of logic, it breaks the build.
it synthesizes a cross file and passes it to Meson. Therefore the user is not expected to provide one.
Well, it does not work this way. To begin with, it misdetects that the arch is different from a native one, as I tried to explain above. Secondly, it fails to generate correct cross-file, and the build fails.
P. S. How would one specify an architecture to build for on a PowerPC machine with G5 cpu and macOS 10.5.x without an archflag (or other way to set the arch, like a triple)? Both ppc and ppc64 are native, there is no cross-compilation whatsoever happening. Both OS and hardware support building and running ppc and ppc64 binaries natively. I am not an expert with Intel, but I think it is a similar case with i386 and x86_64 binaries on x86_64 hardware with macOS 10.6+.
There is no archflag “PowerPC”. There is no machine value
ppc
orppc64
. Comparing these two is a meaningless endeavor: the condition of non-equality is always true, since these values are never identical. Is it supposed to be always true? Then it can be just removed with no consequences.
The check is there for a reason, for other architectures. The only consequence of it being true is that meson-python synthesizes a cross file with the -arch ppc
or -arch ppc64
if that is what $ARCHFLAGS
contains. Again, if you don't wish to have this flags passed to the compiler, don't specify them in $ARCHFLAGS
.
That is, logically it is just wrong. In practice, independently of logic, it breaks the build.
Can you please provide a build log demonstrating the failure? The one in the bug report you link reports that cython
or cython3
are not found, which has nothing to do with compilation flags.
How would one specify an architecture to build for on a PowerPC machine with G5 cpu and macOS 10.5.x without an archflag
The G5 is a ppc64, thus I'm almost sure that the compiler emits ppc64 code if you don't add any compiler flag.
The check is there for a reason, for other architectures.
So why should it be left broken for PowerPC then? It does not work now simply because nobody was aware of this and no one tested or paid attention to a failure. It is totally fixable (whether via my fix or elsewise). We just need to make the build system aware of correct definitions.
The only consequence of it being true is that meson-python synthesizes a cross file with the
-arch ppc
or-arch ppc64
if that is what$ARCHFLAGS
contains. Again, if you don't wish to have this flags passed to the compiler, don't specify them in$ARCHFLAGS
.
At least in three cases archflags are needed: building for ppc64, building FAT and building on Rosetta.
Can you please provide a build log demonstrating the failure? The one in the bug report you link reports that
cython
orcython3
are not found, which has nothing to do with compilation flags.
Yes, I will once on the machine. However the issue, I think, is the following:
Why it did not fail before was that pep517 was not used, and it looks like Macports used a wrapper to fix Meson behavior with cross-file. (I need to verify how exactly it was fixed, but as a matter of fact pep517 is broken, including on x86_64 up to 10.7, while non-pep517 build works fine.)
The G5 is a ppc64, thus I'm almost sure that the compiler emits ppc64 code if you don't add any compiler flag.
AFAIK otherwise, I will check on 10.5, but the point is that archflags or target is needed there, since two archs are native, and machine value makes no difference between them.
The G5 is a ppc64
G5, while being a 64-bit cpu, supports both ppc and ppc64 natively. OS running on it may or may not.
I will explain it once more, maybe I was not sufficiently clear before. There are two possibilities: you need to pass -arch ppc
or -arch ppc64
to the compiler, or you do not.
If you do, you can set the $ARCHFLAGS
environment variable to -arch ppc
or -arch ppc64
. When you do, meson-python synthesizes a cross compilation environment definition and passes it to meson via the --cross-file
option. Because people likes to do stupid things, meson-python checks whether the architecture passed to the -arch
option in $ARCHFLAGS
is different from the system native architecture. If it is the same, it skips the generation of the cross compilation environment definition and does not pass the --cross-file
option to meson. Therefore, as not other piece of software looks at the $ARCHFLAGS
environment variable, the case in which the value passed to -arch
in $ARCHFLAGS
and the system native architecture are the same, has no effect on the compilation.
What your patch does, is to make meson-python detect that the native architecture for OSX on PowerPC is ppc
or ppc64
. This in turn makes meson-python skip the generation of the cross compilation environment definition and passing of the --cross-file
option to meson when you set $ARCHFLAGS
to -arch ppc64
on your G5. This is absolutely identical to do not set $ARCHFLAGS
.
However, you insist that you need the proposed patch and you need to pass -arch ppc64
to the compiler. This cannot be correct, as the effect of your patch is to do not pass the flag to the compiler. If you don't need the flag, don't set $ARCHFLAGS
. If you do need it, your patch is wrong.
A quick update from powerpc machine and numpy
1.26.2:
ppc64
and Rosetta, likely for universal too.)meson
picks the wrong compiler and linker. So cross-build without user-provided cross-file is broken on macOS PowerPC.The log is for the second case: main.log
However, you insist that you need the proposed patch and you need to pass
-arch ppc64
to the compiler. This cannot be correct, as the effect of your patch is to do not pass the flag to the compiler. If you don't need the flag, don't set$ARCHFLAGS
. If you do need it, your patch is wrong.
As per your comment above re return values of sysconfig.get_platform()
, I agree, my patch will not work in a general case and should not be merged in this form.
Then, the question can be put another way: can we fix cross-file generation, so that compiler and linker are picked from environment and not randomly from system prefix? If it is not possible, well, I guess we will need to add our cross-file and patch meson.build
to use specifically that one.
(It is not essential whether a native ppc/ppc64 build is misdetected as cross, after all, if in result the build gonna work nevertheless.)
I am tired of repeating myself. You seem to attribute some magic property to the $ARCHFLAGS
environment variable, which are obviously not there. $ARCHFLAGS
is the wrong solution for your problems. Patching meson-python is the wrong solution for your problems. You don't need to patch anything to pass a cross compilation environment definition describing your setup to meson through meson-python.
@dnicolodi I agree with you that setting ARCHFLAGS is not needed in a trivial case. I have verified that works, at least on ppc
, as I mention above. There is nothing to fix for this case.
What I do not get is how do you suggest to handle a case when there are more than 1 native archs supported by the OS. Maybe I am phrasing it in a confusing way, I apologize if so.
Suppose a version of gcc
supporting 2011 standard is built as universal (ppc+ppc64) on 10.5.8 on a G5. That is, hardware, OS and gcc
support two archs natively.
If I do not pass archflags (or use another way to set the needed target), presumably some one arch will be built with no ARCHFLAGS being set (I think it will be ppc
, but in any case it can be only one choice of the three, whether deterministic, hopefully, or random). I may need to build for a different arch, or build universal (which requires to build each of the archs separately and then use lipo
). How do I do that? If I set ARCHFLAGS, the build will be detected as cross, and we have already seen that it does not work, because meson
picks a wrong compiler when generating a cross-file (the build is started with gcc13, cross-file randomly picks gcc-4.2 from system prefix, which will not build numpy
).
If you say that I will need a custom cross-file in any such a case, okay, I can accept that; otherwise I do not see how it is supposed to work.
Because people likes to do stupid things, meson-python checks whether the architecture passed to the -arch option in $ARCHFLAGS is different from the system native architecture. If it is the same, it skips the generation of the cross compilation environment definition and does not pass the --cross-file option to meson.
Just to reiterate, this does not work in a described way on PowerPC: meson
fails to realize it is a native build when ARCHFLAGS is passed. Fair enough, you can say it is a fault of a user to pass ARCHFLAGS, but nevertheless the code does not work as it is supposed to work.
Whether it should be fixed or not, is up to you and other meson
developers to decide, of course.
Would it be possible to use -m32
and -m64
instead of specifying -arch ppc
and -arch ppc64
?
@erikbs If you mean whether than gonna work for macOS with a native build, then yes, AFAIK is does.
It will not work for FAT builds if one arch is of a different family (i.e. something like i386 + ppc).
Ah, I think I understand.
So just like system libraries are fat binaries containing both x86_64 and aarch64 code on recent macOS versions, older Mac OS X versions had fat system libraries for ppc, i386 and x86_64. On an older system I can pass -arch i386
to compile my program for Intel and -arch ppc
to compile for PowerPC, and both will be linked to /usr/lib/libSystem.B.dylib etc. There is no cross-compilation and no need to set -isysroot
etc. (as when cross-compiling for iOS). I can use lipo
to create a fat binary that can be transferred between Intel and PowerPC Macs and run on both.
If I understand correctly, meson-python will not cross-compile if passing -arch i386
on an Intel Mac (with a 32-bit OS), but it will initiate cross-compilation if passing -arch ppc
, then fail because it tries to cross-compile and fails to find the libraries, compiler etc.? If passing -arch i386
on x86_64, meson-python will cross-compile, but if passing -m32
it will just build in 32-bit mode without cross-compiling, whilst Clang treats these options as exactly the same?
I agree that when Apple’s developer tools allow (require?) you to do this without cross-compilation, it is strange that meson-python instead enforces cross-compilation for one of the architectures. Does it even make sense to let architecture alone determine cross-compilation on Mac? After all, compiling an aarch64 iOS app on aarch64 macOS requires cross-compilation, even though the architecture is the same.
I also wonder what happens if you pass multiple -arch
flags to meson-python. If I call clang -arch x86_64 -arch aarch64 …
on my macOS 11 system, a fat binary (x86_64+aarch64) is produced. What will meson-python do? Will the order matter?
Anyway, given that the Mac operating system itself is (or at least was) identical regardless of architecture and that the hardware will/would simply boot the code matching its architecture, could one argue that the OS has more than one “native” architecture? For clarity we could of course call them “supported architectures” or something instead.
Could it then be an option to let platform.mac_ver()
also return a list of supported architectures (would be ppc+ppc64+i386 on 10.5, i386+x86_64 on 10.9, x86_64+aarch64 on 11 etc.) and replace the cross-compilation condition if arch != nativearch
with if not arch in supportedarchs
?
It is a more general solution that does not check explicitly for ppc
/ppc64
. The list of supported architectures per Mac OS version could be hardcoded or determined from e.g. /usr/lib/libSystem.B.dylib
.
It will not work for FAT builds if one arch is of a different family
meson-python does not support FAT or unified builds.
@dnicolodi @erikbs Perhaps my last comment has brought about a bit of a confusion.
There is no expectation that meson-python
is, will or should support FAT builds. It is also unnecessary for our purposes (because Macports can handle separate builds for every arch and then lipo those – ports do not have to have any kind of support for FAT builds from their side) and largely useless to begin with, since modern gcc does not support FAT builds as well.
The only issue we have, IMO, is that meson-python
behaves differently when building on a PowerPC in described scenarios, since it detects the platform to be Power Macintosh
, but build arch to be ppc
, which leads to an incorrect assumption of this being a cross-build.
Assumption of cross-build combined with a lack of needed cross-file leads to a wrong compiler and linker being picked, which in turn breaks the build, when specific compiler is required (typical case is a need for C++11 or higher), different from a system one (gcc-4.2).
I do believe this can and should be fixed on meson-python
side, but obviously I am not making decisions here, it is up to the upstream.
It is still possible to hack around this bug and make it work correctly from Macports side.
@erikbs cross compilation via the $ARCHFLAGS
environment variable on macOS works just fine with meson-python for compiling aarch64 binaries on x86_64 systems and the other way around. Universal binaries in wheels (wheels build for multiple architectures) are a bad idea for a number of reasons and are not supported. meson-python raises an error if multiple -arch
options are specified in $ARCHFLAGS
.
I have yet to understood what exactly @barracuda156 is trying to do, despite multiple requests to him to clarify what his goals are. What we have so far are just statements saying that setting $ARCHFLAGS
does not work for him. The only thing that could be actionable is the observation that settign $ARCHFLAGS="-arch ppc64"
on a system where ppc64 is the native architecture results in meson-python generatign a cross file for meson specifying this compiler option, despite it not being strictly necessary. However, this should not have any adverse effect on the build. This nuisance is also not particularly difficult to fix. However, the meson-python developers have no access to a system where any patch fixing the problem could be tested: PowerPC is not an architecture supported by any current macOS release. Running such a system connected to a network is an inherent security risk, thus having access to one is extremely difficult. Although, if someone wants to send some PowerPC hardware my way, I can provide a delivery address. On the other hand, this nuisance can be completely avoided not setting the $ARCHFLAGS
environment variable to bogus values.
Reading between the lines, it seems that what @barracuda156 is trying to do, is to cross compile a ppc binary on a ppc64 build host with a compiler that is not the one found as the cc
binary in $PATH
. The way to do that is to craft a cross, something like:
[binaries]
c = ['path/to/gcc', '-arch', 'ppc']
cpp = ['path/to/g++', '-arch', 'ppc']
[host_machine]
system = 'darwin'
cpu = 'ppc'
cpu_family = 'ppc'
endian = 'big'
and pass it to Meson using meson-python command line build settings:
python -m build -Csetup-args=--cross-file=cross.txt
meson-python supports $ARCHFLAGS
for compatibility with setuptools. It can work only for the very simple case where the only thing that is needed is to pass the -arch
option to the default compiler. For anything more, Meson native files or cross files definitions must be used.
I do believe this can and should be fixed on
meson-python
side, but obviously I am not making decisions here, it is up to the upstream.
We don't have any way to test a fix for this. The fix you proposed does not work and you didn't come up with an alternative. If you produce something that has at least a chance of being correct we may consider merging it.
It is still possible to hack around this bug and make it work correctly from Macports side.
There is no bug to work around. You are using meson-python wrong. I'm kind of tired to repeat that if setting $ARCHFLAGS
does not work for you, you should simply not do it, but you insist that you must set it, without providing any explanation for why you think this is the case.
I do believe this can and should be fixed on
meson-python
side, but obviously I am not making decisions here, it is up to the upstream.We don't have any way to test a fix for this. The fix you proposed does not work and you didn't come up with an alternative. If you produce something that has at least a chance of being correct we may consider merging it.
@dnicolodi Thank you. Let me see if it can be addressed in a correct way. I agree with you that proposed fix is not correct in a general case and should not be merged.
This hasn't seen any activity since January, I don't know how the problem could be solved, and it is not really possible to get access to a system where this cab be tested as any macOS version that supports ppc is long out of support. I'm closing this. If someone is annoyed enough about this and has a reliable way to detect the macOS native architecture on ppc they are welcome to open a new PR.
(If this can be done in a simpler way, please advise me. Python is not my sphere of expertise.)
Problem
platform.mac_ver()
on PowerPC is not giving a value which the code expects (this is in Rosetta):This makes the build system believe it is cross-compiling, and if the cross-file is not provided (and in
Numpy
it is not, for example), disaster ensues: https://trac.macports.org/ticket/68908What is giving the correct values is
sysconfig.get_platform()
used in the same file just above:It is defined for PowerPC here: https://github.com/python/cpython/blob/48c907a15ceae7202fcfeb435943addff896c42c/Lib/_osx_support.py#L566-L572