Search code examples
makefileld

Test the support of a linker flag


I need to test the support of a specific linker flag (--no-undefined) before eventually making it part of a Makefile recipe.

This linker flag is not guaranteed to be supported on all platforms (as a matter of fact, it breaks macosx link stage), so it's important to only enable it when it's actually supported.

I lean towards a runtime test, which seems preferable to a static list of compilers / systems which would be more difficult to maintain.

Preferably, the test would be run from the Makefile, which would then conditionally set the flag.


Solution

  • The most reliable test would be a linking test, i.e. try to actually link something. This kind of test would depend on whether you are linking through the compiler or directly with the linker. My approach would be to create a generic template for testing arbitrary flag so it could be reused for different flags in different places, e.g.:

    $ cat Makefile
    CHECK_CC_FLAGS := -Wl,--no-undefined -Wl,--whatever
    CHECK_LD_FLAGS := --no-undefined --whatever
    
    define check_cc_flag
      $(shell echo 'int main() { return 0; }' | $(CC) $(1) -xc - 2>/dev/null && echo $(1))
    endef
    
    define check_ld_flag
      $(shell $(LD) $(1) -e 0 /dev/null 2>/dev/null && echo $(1))
    endef
    
    # If linking with $(CC)
    test: LDFLAGS += $(foreach flag,$(CHECK_CC_FLAGS),$(call check_cc_flag,$(flag)))
    
    # If linking with $(LD)
    test_ld: LDFLAGS += $(foreach flag,$(CHECK_LD_FLAGS),$(call check_ld_flag,$(flag)))
    test_ld: test.o
            $(LD) $(LDFLAGS) -o $@ $<
    

    The template tries to run the compiler or linker and if it succeeds (i.e. exits with 0) it will print out the flag, otherwise the output will be empty. May be more cumbersome if the compiler and/or linker do not behave good (return 0 on failed attempts).

    Actual output on Ubuntu 20.04 LTS:

    $ make test
    cc    -c -o test.o test.c
    cc   -Wl,--no-undefined     test.o   -o test
    
    $ make test_ld
    ld   --no-undefined    -o test_ld test.o
    ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000