0

I am new to CMake and was going through the CMake documentations and tutorials. I was able to understand that the target_include_directories command is just the -I option for the compiler (gcc for me). I tried doing it adding the directories manually by using set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I <Path>") and it worked perfectly fine!!

My CMakeLists.txt looks something like this:

cmake_minimum_required(VERSION 3.6)
  
project(Project VERSION 1.0 DESCRIPTION "C Project" LANGUAGES C)
 
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I <path-to-header>")

add_library(basic file1.c file2.c)

#target_include_directories(basic PUBLIC "path-to-header") 
#target_include_directories() is commented out as CMAKE_C_FLAGS have been set

add_executable(main.out main.c)

target_link_libraries(main.out PRIVATE basic)

I wanted to know if there any similar and alternative for the target_link_libraries command using which we can pass -L and -l options to linker in CMake??

Pisers
  • 103
  • 5
  • 1
    This is not an alternative. What you did is not portable. Although `-I` works in Visual Studio build tools, `-l` will not work. `CMAKE_C_FLAGS` sets options to all targets, whereas not all targets require the same set of include search directories. – 273K May 30 '22 at 16:23
  • Yes, indeed it is not useful to manually set the CMAKE_C_FLAGS and adding -I (uppercase i) flag. Can you kindly elaborate a bit more on why -l (lowercase L) will not work?? – Pisers May 30 '22 at 16:39
  • See [Linker options](https://learn.microsoft.com/en-us/cpp/build/reference/linker-options?view=msvc-170) - neither `-L` nor `-l` is known to link.exe. – 273K May 30 '22 at 16:51

1 Answers1

2

To answer your question literally: There is the variable CMAKE_EXE_LINKER_FLAGS and its specializations CMAKE_EXE_LINKER_FLAGS_<CONFIG> for certain configurations like RELEASE or DEBUG or whatever configurations you might have defined. See the CMake documentation for more.

BUT, I highly disrecommend to use these unless you need to pass a very special compiler/linker option CMake does not know about, because these are specific to your compiler.

The point of using CMake is to describe the build process independent of the concrete compiler and platform, such that you can easily switch to another one or at least update your compiler without having to refactor your build code. So, better stick with the generic target_include_directories, target_link_libraries, and similar commands as much as possible.

If you really have to use CMAKE_C_FLAGS or CMAKE_EXE_LINKER_FLAGS I'd recommend to wrap them into an if clause making sure that you are building with the expected compiler on the expected platform and put a fatal error message into the else clause to make future users aware of a possible problem.

bjhend
  • 1,538
  • 11
  • 25
  • Setting `-l` option in variable `CMAKE_EXE_LINKER_FLAGS` won't work in most cases: When prepare a command line for the linker, CMake expands `CMAKE_EXE_LINKER_FLAGS` variable **before** the object files. Because of such ordering, you will get "undefined reference" error if any of that object files uses the library: https://stackoverflow.com/a/24675715/3440745. – Tsyvarev May 30 '22 at 18:00
  • Yes. Indeed I figured out CMAKE_EXE_LINKER_FLAGS by looking into the CMake documentation and tried the same. I got the same "undefined reference" error. Is there any way we can tackle this issue (kind of like ask CMake to restructure the inputs to linker)?? – Pisers May 30 '22 at 18:20
  • @Pisers What do you want to achieve by using `CMAKE_EXE_LINKER_FLAGS` instead of `target_link_libraries`? – bjhend May 30 '22 at 18:48
  • I am a newbie to CMake. Just wanted to know how the internals work!! :) – Pisers May 30 '22 at 18:56
  • That's a good intention but not the way to go. If you want to know how CMake works, have a look at the generated build system after the `cmake` call and search for the generated compile/link calls. Then alter your CMake code and see the effects on the build system. – bjhend May 30 '22 at 19:42