Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression: meson 0.53.0 cross compilation "Unable to determine dynamic linker" #6431

Closed
asavah opened this issue Jan 8, 2020 · 11 comments · May be fixed by #6436
Closed

Regression: meson 0.53.0 cross compilation "Unable to determine dynamic linker" #6431

asavah opened this issue Jan 8, 2020 · 11 comments · May be fixed by #6436

Comments

@asavah
Copy link

asavah commented Jan 8, 2020

Describe the bug
I get "Unable to determine dynamic linker" when trying to cross compile for example dav1d.

To Reproduce
Try cross compiling dav1d https://code.videolan.org/videolan/dav1d/blob/master/meson.build

Expected behavior
The build succeeds as it it did with 0.52.x
Adding ld = 'ld-binary" did not help
Disregard that this is x86_64 to x86_64 cross compilation, toolchain is different and cross is needed to keep host and target environments apart.

Build started at 2020-01-08T17:11:17.925584
Main binary: /home/asavah/kross/host/bin/python3
Build Options: -Db_ndebug=true -Db_lto=true -Dbitdepths=8,16 -Denable_asm=true -Denable_tools=true -Denable_examples=false -Denable_tests=false -Dlogging=false -Dprefix=/usr -Dbindir=/usr/bin -Ddatadir=/usr/share -Dincludedir=/usr/include -Dinfodir=/usr/share/info -Dlibdir=/usr/lib -Dlibexecdir=/usr/lib -Dlocalstatedir=/var -Dmandir=/usr/share/man -Dsbindir=/usr/sbin -Dsharedstatedir=/var -Dsysconfdir=/etc -Dbackend=ninja -Dbuildtype=plain '--cross-file /home/asavah/kross/tmp/asusb450eg/toolchain.meson'
Python system: Linux
The Meson build system
Version: 0.53.0
Source dir: /home/asavah/kross/src/dav1d
Build dir: /home/asavah/kross/tmp/asusb450eg/dav1d
Build type: cross build
Project name: dav1d
Project version: 0.5.2
No CFLAGS in the environment, not changing global flags.
No LDFLAGS in the environment, not changing global flags.
Appending CPPFLAGS from environment: '-DPIC'

meson.build:25:0: ERROR: Unable to determine dynamic linker
[binaries]
c = ['ccache','x86_64-asusb450eg-linux-gnu-gcc']
cpp = ['ccache','x86_64-asusb450eg-linux-gnu-g++']
ar = 'x86_64-asusb450eg-linux-gnu-ar'
strip = 'x86_64-asusb450eg-linux-gnu-strip'
nm = 'x86_64-asusb450eg-linux-gnu-nm'
ld = 'x86_64-asusb450eg-linux-gnu-ld'
objdump = 'x86_64-asusb450eg-linux-gnu-objdump'
pkgconfig = 'x86_64-asusb450eg-linux-gnu-pkg-config'
exe_wrapper = 'kqemu-wrapper'
llvm-config = '/home/asavah/kross/host/asusb450eg/bin-config/llvm-config'
cmake = '/home/asavah/kross/host/bin/cmake'

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

[properties]
needs_exe_wrapper = true
has_function_printf = true

system parameters

  • cross build
  • ubuntu 19.10
  • python 3.8.1
  • 0.53.0
  • 1.9.0.git

Edit:
Same happens when building systemd or any other project using meson.
Reverted to 0.52.1.
Suggest reverting ld nonsense and test cross compilation more thoroughly.

@asavah
Copy link
Author

asavah commented Jan 8, 2020

This check is bogus https://github.com/mesonbuild/meson/blob/master/mesonbuild/environment.py#L820
This is what actually runs with popen with or withoud ld= removed from the toolchain hint file.

cc -Wl,--version -DPIC -fuse-ld=x86_64-asusb450eg-linux-gnu-ld
cc: error: unrecognized command line option ‘-fuse-ld=x86_64-asusb450eg-linux-gnu-ld’

Which is not valid for gcc,
-fuse-ld can be either bfd or gold or lld without host prefix
I suggest whoever coded this mess reads gcc manual first https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html

setting
ld='bfd'
does not help either, "machine-prefixed-ld" is still passed to fuse-ld=.

This is what should run for such a test

machine-prefixed-cc -Wl,--version -DPIC -fuse-ld=bfd #or gold

@ryanwoodsmall
Copy link

Seconded. This broke a musl cross-compile on a glibc-based OS and I couldn't find a suitable workaround. Things I tried:

  • manually setting "ld = '...'" in a cross file
  • manually setting "ld = '...'" in a native file
  • setting LD environment variable
  • symlinking toolchain bins to a temp dir at the front of PATH

I would assume LD in the environment would override the linker guessing logic, but it doesn't appear to do so. This is somewhat ironic as I was actually attempting to compile C code to a static binary. Another assumption would be that --default-library static (or -Wl,-static in CFLAGS or -static in LDFLAGS) would also short-circuit checks here, or at least make the failure non-fatal, but that's not the case.

Meson figured that I was using a cross-compiler as "native" and warned such, but still couldn't resolve a dynamic linker. None of this was workable on x86_64 -> x86_64 cross with musl compilers on CentOS 7. For giggles, I tried on ARM 32- and 64-bit glibc dists with musl compilers as well with the same results. Native (glibc or musl) compiles seem to work fine, or at least better, for a quick set of tests.

Reverted to 0.52.1 as well until this is baked.

@asavah
Copy link
Author

asavah commented Jan 8, 2020

@ryanwoodsmall thanks for the pointer,

I thought I did not export LD in environment when cross compiling with meson,
I do unexport CC/CXX vars for meson because it freaks meson out.
I rechecked and yes, LD still was exported.
Unexporting it lets meson go one step further and it correctly guesses build machine linker

The Meson build system
Version: 0.53.0
Source dir: /home/asavah/kross/src/dav1d
Build dir: /home/asavah/kross/tmp/asusb450eg/dav1d
Build type: cross build
Project name: dav1d
Project version: 0.5.2
Appending CPPFLAGS from environment: '-DPIC'
C compiler for the build machine: ccache cc (gcc 9.2.1 "cc (Ubuntu 9.2.1-9ubuntu2) 9.2.1 20191008")
C linker for the build machine: cc GNU ld.bfd 2.33

meson.build:25:0: ERROR: Unable to determine dynamic linker

A full log can be found at /home/asavah/kross/tmp/asusb450eg/dav1d/meson-logs/meson-log.txt

Ok, lets see what meson does by adding a simple print(compiler + check_args) just above https://github.com/mesonbuild/meson/blob/master/mesonbuild/environment.py#L820

This is with `ld = 'x86_64-asusb450eg-linux-gnu-ld' in toolchain file, LD unexported:

The Meson build system
Version: 0.53.0
Source dir: /home/asavah/kross/src/dav1d
Build dir: /home/asavah/kross/tmp/asusb450eg/dav1d
Build type: cross build
Project name: dav1d
Project version: 0.5.2
Appending CPPFLAGS from environment: '-DPIC'
['cc', '-Wl,--version', '-DPIC']
C compiler for the build machine: ccache cc (gcc 9.2.1 "cc (Ubuntu 9.2.1-9ubuntu2) 9.2.1 20191008")
C linker for the build machine: cc GNU ld.bfd 2.33
['x86_64-asusb450eg-linux-gnu-gcc', '-Wl,--version', '-fuse-ld=x86_64-asusb450eg-linux-gnu-ld']

meson.build:25:0: ERROR: Unable to determine dynamic linker

A full log can be found at /home/asavah/kross/tmp/asusb450eg/dav1d/meson-logs/meson-log.txt

This is with without ld = and LD unexported:

The Meson build system
Version: 0.53.0
Source dir: /home/asavah/kross/src/dav1d
Build dir: /home/asavah/kross/tmp/asusb450eg/dav1d
Build type: cross build
Project name: dav1d
Project version: 0.5.2
Appending CPPFLAGS from environment: '-DPIC'
['cc', '-Wl,--version', '-DPIC']
C compiler for the build machine: ccache cc (gcc 9.2.1 "cc (Ubuntu 9.2.1-9ubuntu2) 9.2.1 20191008")
C linker for the build machine: cc GNU ld.bfd 2.33
['x86_64-asusb450eg-linux-gnu-gcc', '-Wl,--version']
C compiler for the host machine: ccache x86_64-asusb450eg-linux-gnu-gcc (gcc 9.2.1 "x86_64-asusb450eg-linux-gnu-gcc (GCC) 9.2.1 20200102")
C linker for the host machine: x86_64-asusb450eg-linux-gnu-gcc GNU ld.bfd 2.33.1.20191206
Build machine cpu family: x86_64
Build machine cpu: x86_64
Host machine cpu family: x86_64
Host machine cpu: znver1
Target machine cpu family: x86_64
Target machine cpu: znver1
Run-time dependency threads found: YES
Checking for function "clock_gettime" : YES
Library dl found: YES
Checking for function "dlsym" with dependency -ldl: YES
Check usable header "stdatomic.h" : YES
Check usable header "unistd.h" : YES
Check usable header "io.h" : NO
Checking for function "getopt_long" : YES
Checking for function "posix_memalign" : YES
Compiler for C supports arguments -fvisibility=hidden: YES
Compiler for C supports arguments -Wundef: YES
Compiler for C supports arguments -Werror=vla: YES
Compiler for C supports arguments -Wno-maybe-uninitialized -Wmaybe-uninitialized: YES
Compiler for C supports arguments -Wno-missing-field-initializers -Wmissing-field-initializers: YES
Compiler for C supports arguments -Wno-unused-parameter -Wunused-parameter: YES
Compiler for C supports arguments -Werror=missing-prototypes: YES
Compiler for C supports arguments -Wshorten-64-to-32: NO
Compiler for C supports arguments -mpreferred-stack-boundary=5: YES
Configuring config.h using configuration
Configuring config.asm using configuration
Program nasm found: YES (/home/asavah/kross/host/bin/nasm)
Configuring version.h using configuration
Program doxygen found: NO
Configuring cli_config.h using configuration
Build targets in project: 10

Option buildtype is: plain [default: release]
Option b_ndebug is: true [default: if-release]
Found ninja-1.9.0.git at /home/asavah/kross/host/bin/ninja
dav1d: configure DONE.

And it builds!

So the key for cross compilation is to make sure LD is NOT exported and ld = is NOT specified as target-triplet-ld (as we do for c||cpp||etc) but as linker type (bfd||gold||lld) in toolchain file or NOT specified at all.
This should be properly documented and as far as I understand it contradicts the purpose of [binaries] where one should specify the real executable substite. Eg doing ld = 'bfd' does not specify the binary for cross environment, but specifies linker type.

And AFAIK the fact that you can't have CC/CXX/LD variables exported while cross compiling with meson is not documented (if someone points me to the sentence where this is documented I'll happily stfu :) )
This is more important for OS builders/maintainers than for software developers.

@ryanwoodsmall
Copy link

Seconded to this as well. Have something working now, but feel this is still somewhat underdocumented. Furthermore, precedence seems underspecified, i.e., environment vs. cross/native file vs command line vs... Tables at https://mesonbuild.com/Reference-tables.html#linker-ids mention ld.bfd but that didn't work for either ld = ... or LD environment variable. Also attempted with a custom CC and LD=bfd env with no luck. Had to unset my entire cross environment, i.e. all of:

  • AR
  • AS
  • CC
  • CFLAGS
  • CPPFLAGS
  • CPP
  • CXXFLAGS
  • CXX
  • LDFLAGS
  • LD
  • STRIP

Working cross file looks like this:

[binaries]
ld = 'bfd'
c = 'x86_64-linux-musl-gcc'
ar = 'x86_64-linux-musl-ar'
as = 'x86_64-linux-musl-as'
cpp = 'x86_64-linux-musl-cpp'
strip = 'x86_64-linux-musl-strip'
[properties]
c_args = '-I/usr/local/crosware/software/muslfts/current/include'
c_link_args = '-L/usr/local/crosware/software/muslfts/current/lib -lfts -static'

Thanks for working through this and for pointers. Looks like I can now build ksh93 (from https://github.com/att/ast) with compilers built from musl-cross-make (https://github.com/richfelker/musl-cross-make) w/Meson 0.53.0.

@asavah
Copy link
Author

asavah commented Jan 8, 2020

Yep I had to unexport everything too:

ifeq ($(MESON_HACKS),1)
export HINT_CC := $(CC)
export HINT_CXX := $(CXX)
export HINT_LD := $(LD)
export HINT_CFLAGS := $(CFLAGS)
export HINT_CXXFLAGS := $(CXXFLAGS)
export HINT_LDFLAGS := $(LDFLAGS)
ifeq ($(BUILD_FOR),target)
export CC =
unexport CC
export CXX =
unexport CXX
export LD =
unexport LD
export CFLAGS =
unexport CFLAGS
export HOST_CFLAGS =
unexport HOST_CFLAGS
export CXXFLAGS =
unexport CXXFLAGS
export HOST_CXXFLAGS =
unexport HOST_CXXFLAGS
export LDFLAGS =
unexport LDFLAGS
export HOST_LDFLAGS =
unexport HOST_LDFLAGS
export STRIP =
unexport STRIP
export CMAKE =
unexport CMAKE
endif
endif

Quote from https://mesonbuild.com/Overview.html

The main design goals of this language has been simplicity, clarity and conciseness.

Yep, totally

@jameshilliard
Copy link
Contributor

See if #6436 fixes this.

@FlyingBBQ
Copy link

I experienced the same problem when updating to Meson 0.53.0 and I agree that documentation for this can be better.

In my project I cross compile for ARM where I have the following linker binaries on my Linux machine:

arm-none-eabi-ld
arm-none-eabi-ld.bfd
arm-none-eabi-ld.gold

Setting any of these binaries in my cross file resulted in the "Unable to determine dynamic linker" error. Eventually it was by trial and error that I found the correct setting should be ld = 'bfd', but as @asavah mentioned, this sort of contradicts the [binaries] section in the cross file.

To me it would make sense that I can explicitly set the linker binary e.g.

[binaries]
ld = 'arm-none-eabi-ld.bfd'
c = 'arm-none-eabi-gcc'
cpp = 'arm-none-eabi-g++'

@codyps
Copy link
Contributor

codyps commented Jan 9, 2020

@jameshilliard that will work around the issue, but it does seem like we might also want a way to set the -fuse-ld parameter separately from the ld program being passed in the cross file spec. It also could try to guess at the ld type (for example, someone might be using ld = 'arm-none-eabi-ld.gold', etc)

To clarify, right now I use ld = find_program('ld') in my meson.build file, and invoke ld directly in a custom_target to generate certain binary files.

@jameshilliard
Copy link
Contributor

@jmesmon Yeah, might be a good idea to do that as well(I'll let someone else figure that out if it's important for them), the -fuse-ld whitelist in my PR probably still makes sense to have as a last resort sanity check to prevent passing invalid args to gcc.

kleisauke referenced this issue in lovell/sharp-libvips Jan 9, 2020
0.53.0 crashes with 'Unable to determine dynamic linker'
@dcbaker
Copy link
Member

dcbaker commented Jan 13, 2020

Closing in favor of #6442, which is mean to find a solution to all of the linker stuff.

@dcbaker dcbaker closed this as completed Jan 13, 2020
@marc-h38
Copy link
Contributor

Furthermore, precedence seems underspecified, i.e., environment vs. cross/native file vs command line vs...

ld_args and c_args precedence leaves me confused too, see #6362

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants