3

I'm adding support for gperftools in my project to profile the cpu and memory. Gperftools needs the library tcmalloc to be linked last for each binary.

Is there a way with cmake to append a library to every binary targets of my project without having to edit each CMakeLists.txt?

I've found a similar question here: link library to all targets in cmake project, but it does not answered. It is suggested to overcome the problem using macros, but it is not explained how this could be achieved.

Community
  • 1
  • 1
Falco
  • 277
  • 5
  • 12
  • 1
    You ask `Is there a way with cmake...` and the question you refers has a [comment](http://stackoverflow.com/questions/30819041/link-library-to-all-targets-in-cmake-project#comment49685024_30819041): `There is nothing builtin that removes this.`. It is just an answer to your question. Or do you prefer a formal answer(not a comment)? – Tsyvarev Dec 07 '15 at 10:45
  • It says there is nothing builtin but lets an open door to alternate ways such as a macro, I'm thinking in that way but have yet no idea how to do this properly. – Falco Dec 07 '15 at 11:15
  • 1
    I think you should first all collect a list of all existing targets. Unfortunately, this is yet another not built in capability of CMake https://cmake.org/pipermail/cmake/2011-January/042079.html It seems though that you can override the standard `add_library` command https://cmake.org/pipermail/cmake/2010-September/039388.html – Antonio Dec 07 '15 at 11:17
  • 2
    Could you please add CMake code snippets of what you have tried so far and maybe what has worked already for a single target? One possibility would be - besides overwriting `add_executable()` - to modify/extend [`CMAKE_CXX_LINK_EXECUTABLE`](https://cmake.org/cmake/help/v3.3/variable/CMAKE_LANG_LINK_EXECUTABLE.html), [`CMAKE_CXX_IMPLICIT_LINK_LIBRARIES`](https://cmake.org/cmake/help/v3.3/variable/CMAKE_LANG_IMPLICIT_LINK_LIBRARIES.html) or [`CMAKE_STANDARD_LIBRARIES`](https://cmake.org/cmake/help/v3.3/variable/CMAKE_STANDARD_LIBRARIES.html). – Florian Dec 07 '15 at 11:44

1 Answers1

6

As @Florian suggested, you can use CMAKE_CXX_STANDARD_LIBRARIES variable for library which should be linked to every target as system, so it will be effectively last in link list.

There are a couple of things with this variable:

  1. Unlike to what is written in CMake documentation, the variable's name contains <LANG> prefix.

  2. While using this variable expects full path to the additional library, in case that additional library is not under LD_LIBRARY_PATH, executable will not work with Cannot open shared object file error error. For me, with C compiler (and corresponded prefix in the variable's name), link_directories() helps. With C++, only RPATH setting helps.

Example:

CMakeLists.txt:

# Assume path to the additional library is <a-dir>/<a-filename>
set(CMAKE_CXX_STANDARD_LIBRARIES <a-dir>/<a-filename>)
set(CMAKE_INSTALL_RPATH <a-dir>)

add_executable(hello hello.cpp)
install(TARGETS hello DESTINATION bin)

hello.cpp:

#include <stdlib.h>
int main(void)
{
    void p = malloc(10);
    if(p) free(p);
}

Assuming, e.g., that additional library replaces malloc function, executable will use that replacement.

Tested with CMake 2.8 and 3.4 on Linux (Makefile generator).

Update:

As suggested by @Falco, in case of gcc compiler additional library can be specified with -l: prefix:

set(CMAKE_CXX_STANDARD_LIBRARIES -l:<full-library-path>)

With such prefix gcc will link executable with given library using its full path, so the executable will work without additional RPATH settings.

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
  • This solution works and and fits my needs. You can improve it by using it this way: set(CMAKE_CXX_STANDARD_LIBRARIES -l:/) The "-l:" makes gcc link to a full path lib, this avoids the need to have the lib in system path or adding it to LD_LIBRARY_PATH – Falco Dec 07 '15 at 14:26
  • Thanks for the hint, I have added it to the post. – Tsyvarev Dec 07 '15 at 17:30