On Wed, 19 Apr 2017 20:06:06 +0200 Adriaan de Groot <gr...@kde.org> 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: > > set(CMAKE_C_CREATE_SHARED_LIBRARY > "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> > <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> > <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>") > > 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: > > set(CMAKE_C_CREATE_SHARED_LIBRARY > "<CMAKE_LINKER> <CMAKE_SHARED_LIBRARY_C_FLAGS> > <LANGUAGE_COMPILE_FLAGS> < > LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> > <SONAME_FLAG><TARGET_SONAME> > -o > <TARGET> <OBJECTS> <LINK_LIBRARIES>") > > 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: > > set(CMAKE_C_CREATE_SHARED_LIBRARY > "<CMAKE_LINKER> <CMAKE_SHARED_LIBRARY_C_FLAGS> > <LANGUAGE_COMPILE_FLAGS> < > LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> -soname <TARGET_SONAME> -o > <TARGET> <OBJECTS> <LINK_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): > > set(CMAKE_C_CREATE_SHARED_LIBRARY > "/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 libgt.so -o libgt.so > 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".