Messing around with linkers & CMake

Tijl Coosemans tijl at
Wed Apr 19 18:39:12 UTC 2017

On Wed, 19 Apr 2017 20:06:06 +0200 Adriaan de Groot <groot at> wrote:
> On Saturday 15 April 2017 13:36:40 Koop Mast wrote:
>> So I was looking into using binutils from ports to build webkitgtk when
>> debug is enabled. With the CMAKE_AR and CMAKE_RANLIB variables I can
>> set the binutils ar and ranlib. However the problem is that for some
>> reason cmake doesn't have a LINKER variable, which results in it using
>> ld from base which doesn't understand thin archives. I tried
>> CMAKE_LINKER a while back and that didn't seem to work.  
> The problem is in several stages:
> 0) I'm going to assume CMake 3.7.1 is being used, and that you have a C-based 
> library that you are building.
> 1) First, the standard definitions can be found in 
> /usr/local/share/cmake/Modules/CMakeCInformation.cmake , and they define so-
> called rule-variables, which are rules that are later expanded by the (Makefile 
> | Ninja | whatever) generator for specific targets. There is a definition in 
> there for the rule that creates a shared library:
> That means that it is really going to use the C compiler (e.g. /usr/bin/cc, if 
> that is what it found), followed by a bunch of flags and thingies.
> There *is* a CMAKE_LINKER variable, but it is not used when creating a C-
> language shared library, because the rule variable doesn't use it. So what you 
> could do, is change the rule for creating a C-language shared library:
> -o
> See how I have changed the command at the start? Do this somewhere really 
> early in the top-level CMakeLists.txt; I'm not sure when the variable is 
> expanded or its value checked. But this does change the rule for *every* C-
> language shared library that is built by the project.
> 2) It's going to take some futzing to massage the command to work with a/the 
> linker directly. For example, SONAME_FLAG expands to -Wl,-soname, -- but I 
> don't think you want to change that variable, you want to DTRT in your command 
> to create C-language shared libraries:
> Since you're messing around with commands directly, and don't care for 
> portability to other systems or compilers *anyway*, you may want to plumb in 
> values more directly (this example probably does not do what you want):
>         "/usr/lbin/verify_krb5_conf --dumpconfig <TARGET_SONAME>")
> 3) You can verify what CMake has decided by subsequently building with 
> VERBOSE=1, but also remember that CMake writes Makefiles (or Ninja, or 
> whatever) that re-invoke CMake to run some commands; those commands are 
> usually read from a text file, and you can look at the text file, too.
> For instance, if I have this CMakeLists.txt:
> project(kwm)  # Kannie Wachten op Meson
> add_executable(kwm main.c)
> add_library(gt SHARED shared.c)
> Then the command that ends up in the Makefile (er .. I may mention Ninja a few 
> times here, but I've only ever tried Make):
>     /usr/local/bin/cmake -E cmake_link_script CMakeFiles/gt.dir/link.txt --
> verbose=1
> So to link my C-language shared library called gt, it calls cmake which reads 
> a file named link.txt (in a subdir obviously named after the shared library 
> being built). The content of that file is:
>     /usr/bin/ld -fPIC   -shared -soname -o 
> CMakeFiles/gt.dir/shared.c.o 
> (for this example I used the CMAKE_C_CREATE_SHARED_LIBRARY definition from the 
> middle of section (2), not the useless one at the end). Now you can map-
> backwards that line to the variables expanded from the rule variable for 
> creating C-language shared libraries.
> Use that to your advantage while tweaking the rules. What you *could* even do, 
> is post-configure edit the generated link.txt files if you can't get the effect 
> you want from within CMake. That would be "here be dragons" territory, though.
> 4) So coming back to your original question:
>> My question is now does cmake have a variable, or another way, that I
>> can set so it uses ld from binutils instead of ld from base?  
> There's three possible ways:
>  - find a flag to tell the C compiler to use a different linker (e.g. -fuse-ld, 
> if you can use that to set the linker to the one from binutils),

Adding -B${LOCALBASE}/bin to LDFLAGS should do the trick.  It's used in
a few places in the ports tree.

>  - tweak the rule command CMake uses to generate the Makefile rule that builds 
> the shared library, to use the other linker, for instance by replacing the 
> part of the rule <CMAKE_C_COMPILER> with something else,
>  - tweak the generated text file for the command, instead.
> I'm going to take a look at variable scope for rule-generation later tonight, 
> so that you might be able to tweak this for single libraries only, so's to 
> give you more nuanced control.
> So the *actual* answer to your question is "yes".

More information about the kde-freebsd mailing list