Meson: Cross compiler ignored when build and host architectures are identical

Created on 17 Mar 2019  路  31Comments  路  Source: mesonbuild/meson

I'm trying to compile for Android x86_64 on Linux x86_64. Unfortunately, Meson selects the native compiler instead of the one provided by the cross-file. The setup is the same as described in #5097.

regression

All 31 comments

This sounds like a regression, it used to work fine in the past, can you confirm by trying with 0.49.2?

This seems to be affecting me as well. I'm cross compiling for iOS, and specifying c_args as -arch arm64. That argument was not used in find_library('sqlite3') which broke my build.

@nirbheek Yep, works as expected in 0.49.2.

https://github.com/mesonbuild/meson/pull/5128 is an alternative fix for more than just C. edit that's for a different issue.

This is likely something I caused, but I'll need more information (or better yet a test case) to fix it.

My guess is that you are right on the build == host, and since meson thinks both are the same our pervasive use of

if environment.is_cross_build() and not self.is_cross:
    for_machine = MachineChoice.BUILD
else:
    for_machine = MachineChoice.HOST

doesn't yield the desired results since:

def is_cross_build(self):
    return not self.machines.matches_build_machine(MachineChoice.HOST)

The best solution to this problem is https://github.com/mesonbuild/meson/pull/4010, which removes most of the environment.is_cross_build() checks in lieu of tracking the build and host platforms (or equivalently native: true/false kwargs) directly. In a sense that means meson is always cross compiling, and the cross file just overrides various thing[host] = thing[build] defaults.

CC @dcbaker

In case it's helpful, I did a git bisect on this issue and found the following 3 commits to be the cause (note that the 3 commits do not build independently, so git bisect can't point out exactly which commit is the cause):

2b22576f Remove cross_info; cross file is parsed up front and discarded
dbf080af Get rid of need_cross_compiler
edb3585b Simplify config file checking code, inlining _ok_type

Note that in my case, I'm seeing the issue even with host == x86_64 and target == aarch64, so it's possible this is unrelated, but from my own debugging it appears to be similar (based on debug prints, it has to do with the is_cross_file() function returning False sometimes.

I also tried with the branch in https://github.com/mesonbuild/meson/pull/4010, and it fixes the issue for me.

In case it helps, I can repro this via an Android cross-build:

git clone https://github.com/XevoInc/xlib
cd xlib
git reset --hard 7a9ce72 # this commit is needed as xlib switched to CMake as a workaround to the issue
cat << EOF >> android.cross
[binaries]
c = ['aarch64-linux-android-clang']
cpp = ['aarch64-linux-android-clang++']
ar = ['aarch64-linux-android-ar']
nm = ['aarch64-linux-android-nm']
ld = ['aarch64-linux-android-ld']
strip = ['aarch64-linux-android-strip']
pkgconfig = 'pkg-config'

[properties]
needs_exe_wrapper = true
c_args = ['-fPIE', '-fPIC']
c_link_args = ['-Wl,-pie']
cpp_args = []
cpp_link_args = []

[host_machine]
system = 'linux'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'

[target_machine]
system = 'linux'
cpu_family = 'aarch64'
cpu = 'aarch64'
endian = 'little'
EOF

# Setup an aarch64 android toolchain following these instructions:
# https://developer.android.com/ndk/guides/standalone_toolchain
# Then add the toolchain's bin directory to your PATH.

meson --cross-file android.cross -Dxargparse=false build .
ninja -C build
file build/libxlib.so.0.1

You will get something like this output from the file command, indicating an x86 binary:

build/libxlib.so.0.1: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld64.so.1, BuildID[sha1]=7d3b16ff3f41562d982aebada399b72eea78af9c, with debug_info, not stripped

Oh wait this is way simpler. You don't need a target machine to be specified and your host should be aarch64. Your cross file would be for building a cross compiler, not using one to build something else.

You are right! just setting host_machine works fine. Thanks, user error.

Glad to here this! Maybe you should close this then?

For the record, my PR "fixed" your issue because it makes cross vs native irrelevant. You can have separate build vs host compilers either way.

Glad to here this! Maybe you should close this then?

No, cross compilation is still utterly broken. And this bug deserves a 0.50.x fix.

See the linked dxvk issue above. And I got the same issue on another project: https://github.com/iXit/wine-nine-standalone

If the build machine equals the host machine, the cross compiler is just ignored.
https://github.com/doitsujin/dxvk/blob/master/build-wine64.txt

But it's totally valid to cross compile in such an environment. In this case its winegcc.
Then I could just use a specific gcc version from a chroot using --sysroot to target libraries found in there. Of course I want that compiler to be used and not just ignored by meson...

OK well the easiest fix for 0.50.* is probably to make the presence of a cross file force is_cross_build again. This is morally equivalent to reverting dbf080afe99a8bbb04a3bfb19a81363d3b78e7b4 given how much everything else has changed (for the better). The #4010 fix is still superior, but definitely too much for 0.50.*.

Yes, I think this bug is still valid, but I was mistaken in thinking my issue was a bug. Sorry for the confusion!

No worries! Sorry for prematurely suggesting it be closed.

Could somebody assign this to me?

Apparently you need to be a group member first so invited.

oh, thanks!

What's the status of this one, we really should get the point release out soon.

I don't think there has been any changes since the last comment.

I'll prepare something tonight, and double check the link flag issues in my other unmerged regression fix (https://github.com/mesonbuild/meson/pull/5173).

Sorry will have to be tomorrow morning.

Any news? This bug blocks all winegcc based packages on Fedora 31, which ships only 0.50.0

We're working on it, and it will be fixed soon for the 0.50.1 release.

Sorry for the double delay. Just opened https://github.com/mesonbuild/meson/pull/5234

Fixed with https://github.com/mesonbuild/meson/pull/5234 (not sure why the commit didn't automatically close the issue)

@nirbheek It didn't automatically close for a good reason, actually: there is no fix on master. I added the test case to https://github.com/mesonbuild/meson/pull/4010, confirming that PR can fix the issue for master.

I wish github could track issues per branch, but baring that maybe this should be removed from the 0.51.0 (edit: 0.50.1 I meant instead) milestone too?

Which PR fixed this for 0.51 (master)?

Oh sorry @nirbheek ! I meant remove in 0.50.1 and keep in 0.51. #4010 would fix it, but isn't ready to merge.

I can't believe I keep on getting confused cause they both end in 1...

I guess this sort of android cross config works if you have no external library dependencies. The Android NDK doesn't provide it's own pkg-config and the meson cross build requires it to be defined. So you have to organize your meson.build such that it only uses cpp.find_library(), otherwise the bogus call to dependency() will use the native pkg-config to search for the lib and return garbage.

There should be a way to disable pkgconfig resolution for platforms that don't provide it.

I you make false or something your Android PKG& config that would probably help.

It's a good idea, but it doesn't work. After much experimenting. I finally got something that links but it's pretty sophisticated.

https://github.com/ppetraki/meson-android-helloworld

...
meson.build:20:0: ERROR: Pkg-config binary for machine MachineChoice.HOST not found. Giving up.

Android cross-build support just doesn't work in the current form. The cmake provided by AndroidStudio must be used at a minimum for dependency() resolution. pkgconfig simply must be removed as a prerequisite for Android platforms.

Also, when we specify the cmake path, we also need to configure the cross compilation environment and persist that configuration for future calls to dependency and subprojects usage.

I actually got a proof of concept working after building a driver script to harness the cross config. It links! Though cmake itself is probably still broken.

ppetraki@vanguard:~/Sandbox/Games/meson-android-helloworld$ ./cross/build-armv7a.sh 
building...
Toolchain: /home/ppetraki/Android/Sdk/ndk-bundle/build/cmake/android.toolchain.cmake
The Meson build system
Version: 0.51.999
Source dir: /home/ppetraki/Sandbox/Games/meson-android-helloworld
Build dir: /home/ppetraki/Sandbox/Games/meson-android-helloworld/armv7a-build
Build type: cross build
WARNING: Unknown options: "ANDROID_ABI, ANDROID_PLATFORM, ANDROID_STL, ANDROID_TOOLCHAIN, CMAKE_TOOLCHAIN_FILE"
Project name: android_helloworld
Project version: 1.0.0
C compiler for the build machine: ccache cc (gcc 7.4.0 "cc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0")
C linker for the build machine: GNU ld.bfd 2.30
C++ compiler for the build machine: ccache c++ (gcc 7.4.0 "c++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0")
C++ linker for the build machine: GNU ld.bfd 2.30
C compiler for the host machine: armv7a-linux-androideabi21-clang (clang 8.0.7 "Android (5220042 based on r346389c) clang version 8.0.7 (https://android.googlesource.com/toolchain/clang b55f2d4ebfd35bf643d27dbca1bb228957008617) (https://android.googlesource.com/toolchain/llvm 3c393fe7a7e13b0fba4ac75a01aa683d7a5b11cd) (based on LLVM 8.0.7svn)")
C linker for the host machine: GNU ld.bfd 2.27.0.20170315
C++ compiler for the host machine: armv7a-linux-androideabi21-clang++ (clang 8.0.7 "Android (5220042 based on r346389c) clang version 8.0.7 (https://android.googlesource.com/toolchain/clang b55f2d4ebfd35bf643d27dbca1bb228957008617) (https://android.googlesource.com/toolchain/llvm 3c393fe7a7e13b0fba4ac75a01aa683d7a5b11cd) (based on LLVM 8.0.7svn)")
C++ linker for the host machine: GNU ld.bfd 2.27.0.20170315
Build machine cpu family: x86_64
Build machine cpu: x86_64
Host machine cpu family: arm
Host machine cpu: armv7
Target machine cpu family: arm
Target machine cpu: armv7
Library android found: YES
Library log found: YES
Build targets in project: 2
Found ninja-1.8.2 at /usr/bin/ninja
ninja: Entering directory `armv7a-build'                                                            
[4/4] Linking target libandroid_helloworld_lib.so.
ppetraki@vanguard:~/Sandbox/Games/meson-android-helloworld$ file armv7a-build/libandroid_helloworld_lib.so
armv7a-build/libandroid_helloworld_lib.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, with debug_info, not stripped
Was this page helpful?
0 / 5 - 0 ratings