How to set the LDFLAGS in CMakeLists.txt? - gcc

I set the CFLAGS in CMake by CMAKE_C_FLAGS.
Is something like this to set LDFLAGS?

It depends a bit on what you want:
A) If you want to specify which libraries to link to, you can use find_library to find libs and then use link_directories and target_link_libraries to.
Of course, it is often worth the effort to write a good find_package script, which nicely adds "imported" libraries with add_library( YourLib IMPORTED ) with correct locations, and platform/build specific pre- and suffixes. You can then simply refer to 'YourLib' and use target_link_libraries.
B) If you wish to specify particular linker-flags, e.g. '-mthreads' or '-Wl,--export-all-symbols' with MinGW-GCC, you can use CMAKE_EXE_LINKER_FLAGS. There are also two similar but undocumented flags for modules, shared or static libraries:
CMAKE_MODULE_LINKER_FLAGS
CMAKE_SHARED_LINKER_FLAGS
CMAKE_STATIC_LINKER_FLAGS

Look at:
CMAKE_EXE_LINKER_FLAGS
CMAKE_MODULE_LINKER_FLAGS
CMAKE_SHARED_LINKER_FLAGS
CMAKE_STATIC_LINKER_FLAGS

If you want to add a flag to every link, e.g. -fsanitize=address then I would not recommend using CMAKE_*_LINKER_FLAGS. Even with them all set it still doesn't use the flag when linking a framework on OSX, and maybe in other situations. Instead use link_libraries():
add_compile_options("-fsanitize=address")
link_libraries("-fsanitize=address")
This works for everything.

You can specify linker flags in target_link_libraries.

For linking against libraries see Andre's answer.
For linker flags - the following 4 CMake variables:
CMAKE_EXE_LINKER_FLAGS
CMAKE_MODULE_LINKER_FLAGS
CMAKE_SHARED_LINKER_FLAGS
CMAKE_STATIC_LINKER_FLAGS
can be easily manipulated for different configs (debug, release...) with the ucm_add_linker_flags macro of ucm

Related

CMake set Visual Studio Linker ->Command Line-> Additional Options [duplicate]

When linking a binary I can use CMAKE_EXE_LINKER_FLAGS to add a flag (let's say -Wl,-as-needed). However, if I link a library this extra flag will not be taken into account. I would need something like CMAKE_LIB_LINKER_FLAGS but I can't find it.
How should I do this?
Note: modern CMake has a better solution than mentioned below (see updates for details).
You can use CMAKE_SHARED_LINKER_FLAGS like:
set (CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed")
This question looks like related.
UPD
Thanks to #Bruce Adams who points out that since v3.13 CMake has special command for such purpose: add_link_options.
UPD 2
Thanks to #Alex Reinking who points out that modern CMake doesn't recommend using global settings. It is suggested to give the preference to the property settings before the global ones, so instead of add_link_options that has a global scope, the target_link_options should be used. See Alex's answer for details.
This is how you add linker flags to a target in modern CMake (3.13+):
# my_tgt can be an executable, library, or module.
target_link_options(my_tgt PRIVATE "LINKER:-as-needed")
Note that CMake always passes flags to the configured compiler. Thus, to forward your intended link flags to the linker, you must use the LINKER: prefix. CMake will take care of expanding it to -Wl,-as-needed on GCC, and to -Xlinker -as-needed on Clang.
See the documentation here: https://cmake.org/cmake/help/latest/command/target_link_options.html
It looks like this problem is related to the one I had in CLION. I solved it by adding
{set(CMAKE_CXX_STANDARD_LIBRARIES -ljpeg)}
to CMakeLists.txt.
In CMake 3.10.2, the suggested answer of
set (CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed")
did not work for me. The workaround I employed was to use set_target_properties instead.
My CMakeLists.txt file had a line of this sort:
add_library(libraryname MODULE a.cc b.cc c.cc)
After that line, I added this:
set_target_properties(libraryname PROPERTIES LINK_FLAGS "-Wl,-znodelete")
Check out the ucm_add_linker_flags macro of ucm - it deals with appending linker flags to the appropriate CMake variables.
Note that you need to add your linker option without the "-Wl,", namely:
Good:
-DCMAKE_SHARED_LINKER_FLAGS="-fstack-protector"
Wrong:
-DCMAKE_SHARED_LINKER_FLAGS="-Wl,-fstack-protector"
target_link_libraries(target-name PRIVATE -lexpat)
i used this for linking the XML dependencies in my project. replace -lexpat with -l(library name)

GCC/G++ : Enable -std=c++11 from environment variable

I have some OpenCV/C++ application which compiles with a CMake definitions file, in which I did not find a way to pass flags to the compiler.
I know that there are the flags C_INCLUDE_PATH CPLUS_INCLUDE_PATH, and all the rest of their friends...
But, is there an environment variable for definition of any other flags, in which I'd be able to define -std=c++11 ?
If you're using CMake, equally easy and nicer solution will be to pass
-DCMAKE_CXX_STANDARD=11 -DCMAKE_CXX_STANDARD_REQUIRED=ON
to CMake.
The easiest but certainly not nicest solution if you want to force it by hand would be:
add_compile_options(-std=c++11)
However CMake should be able to pick the necessary standard for you. Have a look to this answer:
How to detect c++11 support of a compiler with cmake

GNU GCC/LD : Which libraries are linked by default?

I am a regular C programmer, and there's something I have wondered for some time about GNU GCC/LD internals.
I have noticed that, when passing a sequence of object files to GCC (e.g gcc main.o otherfile.o), GCC automatically links libc.a library file without my explicitly specifying -lc in the options. Similarly, when I compile a program using ncurses, I just need to specify -lncurses and libtinfo.a gets linked automatically (no need to specify -ltinfo). In other words, even though ncurses functions use functions from libtinfo (for instance, unctrl()), I don't need to explicitly link libtinfo.
How can it be possible?
Does GCC/LD have a list of "default libraries" where it looks for missing symbols when linking? If such a table exists, where is it and how can it be configured?
A direct answer is that you can see what libraries are linked by command line options by adding -v to the linking command line. This will show you the commands as they are executed.
The C library and the GCC support library or libraries are linked automatically; other libraries have to be specified manually.
The case of -lncurses and libtinfo.a (libtinfo.so?) is rather different. There, the link command used to build libncurses.so tells the linker that this library also needs -ltinfo, so it automatically picks up the extra library.

Force CMake to use static libraries

[Shamelessly cross-posted from the CMake help list]
I'm trying to create binaries as statically as possible. The fortran code I've got has got X11 and quadmath as dependencies, and I've come across a number of issues (maybe each of these issues should be in a different question?):
My variables are currently
set(CMAKE_LIBRARY_PATH /usr/X11/lib /usr/X11/include/X11 ${CMAKE_LIBRARY_PATH})
find_package(X11 REQUIRED)
find_library(X11 NAMES X11.a PATHS /usr/X11/include/X11/ /usr/X11/lib)
find_library(X11_Xaw_LIB NAMES Xaw Xaw /usr/X11/include/X11/ /usr/X11/lib ${X11_LIB_SEARCH_PATH})
find_library(Xaw Xaw7 PATHS ${X11_LIB_SEARCH_PATH})
set(CMAKE_LIBRARY_PATH /usr/lib/gcc/x86_64-linux-gnu/4.7 /usr/lib/gcc/x86_64-linux-gnu/4.7/x32 /usr/lib/gcc/x86_64-linux-gnu/4.7/32 ${CMAKE_LIBRARY_PATH})
find_library(quadmath NAMES quadmath.a)
set(BUILD_SHARED_LIBS ON)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(LINK_SEARCH_START_STATIC TRUE)
set(LINK_SEARCH_END_STATIC TRUE)
set(SHARED_LIBS OFF)
set(STATIC_LIBS ON)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
Using these, CMake attempts to build every program statically (as expected) - however, it fails because I don't have Xaw.a - I can't find out whether this actually should exist. I have installed the latest libxaw7-dev which I was expecting to fix it. One option would be to compile the X11 libraries myself, but I don't really want to do that...
if I comment out only set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static"), then CMake compiles everything, but uses shared libraries for every program, even though I specify the location of .a X11 libraries in my find_library() calls. I was expecting CMake to use the .a files where it could and then only use shared libraries - is there a way to force this behaviour?
does anyone know yet of a fix for the bug described here: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46539; whereby gfortran seemingly can't statically link libquadmath? I tried the fix using gcc but I can't get CMake to recognise the libgfortran flag:
cmake -DCMAKE_Fortran_COMPILER=gcc -DCMAKE_Fortran_FLAGS=-gfortran
results in
-- The Fortran compiler identification is unknown
-- Check for working Fortran compiler: /usr/bin/gcc
-- Check for working Fortran compiler: /usr/bin/gcc -- broken
CMake Error at /usr/share/cmake-2.8/Modules/CMakeTestFortranCompiler.cmake:54 (message):
The Fortran compiler "/usr/bin/gcc" is not able to compile a simple test program.
However, as you might have noticed, I set the location of the libquadmath.a; when I build a program which doesn't use X11 but does use quadmath when I use
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
then the program does compile successfully (running ldd reports 'not a dynamic executable') - does this mean that the bug has been fixed, or does it only work because I set the location in CMake?
I was having a similar problem. Turns out that cmake was implicitly linking against libgfortran and libquadmath. To fix this I put the following in my top level CMakeLists.txt:
unset(CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES)
I could then explicitly link again the libraries using:
SET_TARGET_PROPERTIES(main_f PROPERTIES LINKER_LANGUAGE "C"
LINK_FLAGS
"/usr/local/Cellar/gcc/7.1.0/lib/gcc/7/libgfortran.a
/usr/local/Cellar/gcc/7.1.0/lib/gcc/7/libquadmath.a -lm -lgcc"
)
The static version of libgfortran is necessary because the shared library also depends on libquadmath. The added "-lm" and "-lgcc" bring in the system dynamic versions of these libraries. On a mac system, you would want to use the full path to your libm.a as well.
I guess your questions are not that much related, I don't know the answer for all of them.
For your static linking problems, since you're using GCC, you can pass multiple -static and -dynamic flags to it:
set(CMAKE_EXE_LINKER_FLAGS "-static ${STATIC_LIBS} -dynamic ${EVERYTHING ELSE} -static ${MORE_STATIC_LIBS}")
I don't know why Xaw.a isn't available on your system, probably because the package maintainer of your Linux distribution didn't really make them available.
Also, compiling everything static might make things not compatible between all distros out there and you cripple the ability for others to use improved, up-to-date libraries with your program, it might not be what you want.
If you intend to make a self-contained package of your program, it might be better just to include the shared libraries you used together, like Dropbox and many other proprietary applications do (Humble Bundle games are other example).

Use -isystem instead of -I with CMake

Is there any way in CMake to force a path specified via include_directories (or perhaps through a different function) to use the -isystem flag instead of the -I flag when building with gcc?
See http://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html#Directory-Options for details on -I and -isystem.
Yes you force a path to be a system include by using the optional SYSTEM flag
include_directories(SYSTEM path)
https://cmake.org/cmake/help/latest/command/include_directories.html
Starting with CMake 2.8.12 you can use the new target_include_directories to include system directory includes at the target level, while leveraging the new usage requirement features of cmake:
target_include_directories(foo SYSTEM PUBLIC path)
Now target foo will use path as a system include, and anything that links to foo will also use path as automatically as a system include. You can control the propagation of these usage requirements by changing the PUBLIC keyword to PRIVATE or INTERFACE.
https://cmake.org/cmake/help/latest/command/target_include_directories.html
As stated already, the correct way to include system paths is:
include_directories(SYSTEM path1 path2)
However as of CMake 2.8.4 and Makefiles, This is only used for C++ and not C, I looked into it and GNU.cmake does not initialize: CMAKE_INCLUDE_SYSTEM_FLAG_C
So you can set this yourself right after calling project().
if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-isystem ")
endif()
Update:
The CMake developers have fixed this in 2.8.5
You could try using CMAKE_C_FLAGS and CMAKE_CXX_FLAGS to add additional flags.

Resources