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

Embedded GCC has_link_argument does not work because test program fails to link #10957

Open
LunarLambda opened this issue Oct 25, 2022 · 8 comments

Comments

@LunarLambda
Copy link

LunarLambda commented Oct 25, 2022

Describe the bug
meson.get_compiler('c').has_link_argument('-Wl,--no-warn-rwx-segments') doesn't work,

C compiler is arm-none-eabi-gcc (Arch Repository) 12.2.0.

Depending on how meson's detection works, it might be failing because the cross compiler can't simply produce a 'do nothing' executable without extra linker arguments, the way the native (x86_64) compiler can:

$ echo 'int main() {}' | arm-none-eabi-gcc -x c -o /dev/null -Wl,--no-warn-rwx-segments -
/usr/lib/gcc/arm-none-eabi/12.2.0/../../../../arm-none-eabi/bin/ld: /usr/lib/gcc/arm-none-eabi/12.2.0/../../../../arm-none-eabi/lib/libc.a(lib_a-exit.o): in function `exit':
/build/arm-none-eabi-newlib/src/build-newlib/arm-none-eabi/newlib/libc/stdlib/../../../../../newlib-4.2.0.20211231/newlib/libc/stdlib/exit.c:64: undefined reference to `_exit'
collect2: error: ld returned 1 exit status

vs

$ echo 'int main() {}' | gcc -x c -o /dev/null -Wl,--no-warn-rwx-segments -

which works.

In the case of arm-none-eabi-gcc, the above do-nothing test can be fixed by specfiying -specs=nosys.specs (assuming it's using newlib / c_stdlib is not overriden), or changing the supplied source code to include void _exit(int x) {}, however I am not sure if meson allows overriding compiler test behaviour like that.

To Reproduce

[binaries]
c = 'arm-none-eabi-gcc'
cpp = 'arm-none-eabi-g++'
ar = 'arm-none-eabi-gcc-ar'
strip = 'arm-none-eabi-strip'
objcopy = 'arm-none-eabi-objcopy'
nm = 'arm-none-eabi-nm'

[host_machine]
system = 'none'
cpu_family = 'arm'
cpu = 'arm7tdmi'
endian = 'little'
project('gba-meson', 'c',
  meson_version: '>=0.56.0',
  default_options: [
    'cpp_eh=none',
    'cpp_rtti=false'])

if meson.get_compiler('c').has_link_argument('-Wl,--no-warn-rwx-segments')
  add_global_link_arguments(
    '-Wl,--no-warn-rwx-segments',
    language: 'c')
endif

Expected behavior
meson properly detects the availability of --no-warn-rwx-segments.

system parameters

  • Is this a cross build or just a plain native build (for the same computer)? cross
  • what operating system (e.g. MacOS Catalina, Windows 10, CentOS 8.0, Ubuntu 18.04, etc.) Arch Linux
  • what Python version are you using e.g. 3.8.0 3.10.8
  • what meson --version 0.63.3
  • what ninja --version if it's a Ninja build 1.11.1
@LunarLambda
Copy link
Author

LunarLambda commented Dec 2, 2022

Ended up specifying ld in the cross file and doing a version check:

# Assume GNU binutils (ld.bfd)
if find_program('ld', version: '>=2.39', required: false).found()
  add_project_link_arguments('-Wl,--no-warn-rwx-segments', language: 'c')
endif

If one overrides c_ld this will break though. find_program('c_ld') doesn't work either unless explicitly specified in a cross/machine file, and I don't think meson currently exposes a way to get the selected linker for a given language as an external_program.

@LunarLambda LunarLambda changed the title Embedded GCC has_link_argument does not work, has_argument throws warning Embedded GCC has_link_argument does not work because test program fails to link Dec 2, 2022
@eli-schwartz
Copy link
Member

however I am not sure if meson allows overriding compiler test behaviour like that.

It sounds like that's probably a good idea to do in general, at least have some way to set up a cross environment that defines missing bits needed to correctly link under embedded environments.

But indeed I don't think meson currently allows that.

I think this may solely affect has_link_argument, e.g. cc.links would just use your own presumably embedded-compatible code.

You could roll your own check with cc.links to check your own minimal source code and see if that flag works? But also, patches welcome to extend meson to handle this natively or with a small bit of cross file prompting.

@LunarLambda
Copy link
Author

compiler.links would indeed work, albeit be a little verbose, and the "minimum linkable product" code obviously can/will differ from toolchain to toolchain.

What would be a good way to improve meson's support there? Should find_program or compiler be extended to expose the selected linker (and what about the static-linker i.e. ar/lib)? Or should machine/cross files be extended to control the code/flags used for 'feature tests' like has_xyz?

I can see arguments for and against either approach, I'm not sure which would be considered more sound and compatible.

@eli-schwartz
Copy link
Member

I think extending the code used would be the best option. That allows people to write the obvious code in meson.build to check options etc. without having to manually construct tests via looking up the linker. Plus, it's related to the toolchain used, not the project, so keeping it as toolchain info seems more elegant.

@LunarLambda
Copy link
Author

Right. Should it go in [properties], where the documentation shows things like overriding sizeofs and has_functions? (iirc)

I think I can try my hand at a patch that allows setting flags and code for compile and link tests.

On that note, if such properties are added, should they also be considered for compiler.compiles and compiler.links? Those already allow specifying the arguments to use, but also allow omitting the default set of arguments (except for cross file *_args, iirc). Not sure what the feature intersection there is, but I suppose it might be weird if has_link_argument uses different default flags from links, when they both (at least currently) check that a binary links cleanly.

@LunarLambda
Copy link
Author

I didn't end up finding the time to work on a PR for this sadly, too much on my plate with life currently. Would still like to see it land in meson at some point.

cc.links() does make an acceptable workaround, since my project only has one target and toolchain.

@Volker-Weissmann
Copy link
Contributor

If I put this into the cross file:

[binaries]
c = ['arm-none-eabi-gcc', '-specs=nosys.specs']

the check for meson.get_compiler('c').has_link_argument('-Wl,--no-warn-rwx-segments') is run like this:

arm-none-eabi-gcc -specs=nosys.specs /home/volker/Documents/mesontest/10957/build/meson-private/tmpb9y5msa8/testfile.c -o /home/volker/Documents/mesontest/10957/build/meson-private/tmpb9y5msa8/output.exe -D_FILE_OFFSET_BITS=64 -O0 -Wl,--fatal-warnings -Wl,--no-warn-rwx-segments 

This would return success, if it would not be for -Wl,--fatal-warnings. Proposal: Adding something like this to the cross file

[host_machine]
test_binary = '''
    void _exit() {}
    void _close() {}
    void _lseek() {}
    int main() {
       $MAINCODE
    }
'''

What do you think?

@jpakkane
Copy link
Member

We usually prefer to fix things in core rather than adding more toggles for people to twiddle. The latter tends to lead to bad usability via a gajillion choices. Is there a way to make the check program detect this case and automatically do the necessary steps to make it work out of the box?

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

No branches or pull requests

4 participants