My recommendation is to start simple, and then complicate your project further.

Let me try to explain how linking works in CMake. The idea is that you build modules in CMake, and link them together. Let's ignore header files for now, as they can be all included in your source files.

Say you have file1.cpp, file2.cpp, main.cpp. You add them to your project with:

ADD_LIBRARY(LibsModule 
    file1.cpp
    file2.cpp
)

Now you added them to a module called LibsModule. Keep that in mind. Say you want to link to pthread for example that's already in the system. You can combine it with LibsModule using the command:

target_link_libraries(LibsModule -lpthread)

And if you want to link a static library to that too, you do this:

target_link_libraries(LibsModule liblapack.a)

And if you want to add a directory where any of these libraries are located, you do this:

target_link_libraries(LibsModule -L/home/user/libs/somelibpath/)

Now you add an executable, and you link it with your main file:

ADD_EXECUTABLE(MyProgramExecBlaBla main.cpp)

(I added BlaBla just to make it clear that the name is custom). And then you link LibsModule with your executable module MyProgramExecBlaBla

target_link_libraries(MyProgramExecBlaBla LibsModule)

And this will do it.

What I see in your CMake file is a lot of redundancy. For example, why do you have texture_mapping, which is an executable module in your include directories? So you need to clean this up and follow the simple logic I explained. Hopefully it works.


In summary, it looks like this:

project (MyProgramExecBlaBla)  #not sure whether this should be the same name of the executable, but I always see that "convention"
cmake_minimum_required(VERSION 2.8)

ADD_LIBRARY(LibsModule 
    file1.cpp
    file2.cpp
)

target_link_libraries(LibsModule -lpthread)
target_link_libraries(LibsModule liblapack.a)
target_link_libraries(LibsModule -L/home/user/libs/somelibpath/)
ADD_EXECUTABLE(MyProgramExecBlaBla main.cpp)
target_link_libraries(MyProgramExecBlaBla LibsModule)

The most important thing to understand is the module structure, where you create modules and link them all together with your executable. Once this works, you can complicate your project further with more details. Good luck!


Note: Keep in mind that this is the simple way to use CMake. The better cross-platform way would be using find_package, which locates a package/library, and provides the libraries and includes in CMake variables so that you could link your program to them. Here's how to do this for boost, for example.

Answer from The Quantum Physicist on Stack Overflow
🌐
CMake
cmake.org › cmake › help › latest › command › target_link_libraries.html
target_link_libraries — CMake 4.3.0-rc3 Documentation
add_library(obj3 OBJECT obj3.c) target_compile_definitions(obj3 PUBLIC OBJ3) add_executable(main3 main3.c) target_link_libraries(main3 PRIVATE a3 $<TARGET_OBJECTS:obj3> b3) links executable main3 with object files from main3.c and obj3.c followed by the a3 and b3 libraries. main3.c is not compiled with usage requirements from obj3, such as -DOBJ3. This approach can be used to achieve transitive inclusion of object files in link lines as usage requirements. Continuing the above example, the code
🌐
CMake
cmake.org › cmake › help › v3.0 › command › target_link_libraries.html
target_link_libraries — CMake 3.0.2 Documentation
Specify libraries or flags to use when linking a given target. The named <target> must have been created in the current directory by a command such as add_executable() or add_library(). The remaining arguments specify library names or flags.
🌐
CMake
cmake.org › cmake › help › v3.2 › command › target_link_libraries.html
target_link_libraries — CMake 3.2.3 Documentation
Specify libraries or flags to use when linking a given target. The named <target> must have been created in the current directory by a command such as add_executable() or add_library(). The remaining arguments specify library names or flags.
🌐
Gitlab
cliutils.gitlab.io › modern-cmake › chapters › basics.html
Introduction to the basics — Modern CMake
The one benefit to this is that you can make libraries with :: in the name (which you’ll see later). [3] Now we’ve specified a target, how do we add information about it? For example, maybe it needs an include directory: ... target_include_directories adds an include directory to a target. PUBLIC doesn’t mean much for an executable; for a library it lets CMake know that any targets that link to this target must also need that include directory.
Top answer
1 of 1
227

My recommendation is to start simple, and then complicate your project further.

Let me try to explain how linking works in CMake. The idea is that you build modules in CMake, and link them together. Let's ignore header files for now, as they can be all included in your source files.

Say you have file1.cpp, file2.cpp, main.cpp. You add them to your project with:

ADD_LIBRARY(LibsModule 
    file1.cpp
    file2.cpp
)

Now you added them to a module called LibsModule. Keep that in mind. Say you want to link to pthread for example that's already in the system. You can combine it with LibsModule using the command:

target_link_libraries(LibsModule -lpthread)

And if you want to link a static library to that too, you do this:

target_link_libraries(LibsModule liblapack.a)

And if you want to add a directory where any of these libraries are located, you do this:

target_link_libraries(LibsModule -L/home/user/libs/somelibpath/)

Now you add an executable, and you link it with your main file:

ADD_EXECUTABLE(MyProgramExecBlaBla main.cpp)

(I added BlaBla just to make it clear that the name is custom). And then you link LibsModule with your executable module MyProgramExecBlaBla

target_link_libraries(MyProgramExecBlaBla LibsModule)

And this will do it.

What I see in your CMake file is a lot of redundancy. For example, why do you have texture_mapping, which is an executable module in your include directories? So you need to clean this up and follow the simple logic I explained. Hopefully it works.


In summary, it looks like this:

project (MyProgramExecBlaBla)  #not sure whether this should be the same name of the executable, but I always see that "convention"
cmake_minimum_required(VERSION 2.8)

ADD_LIBRARY(LibsModule 
    file1.cpp
    file2.cpp
)

target_link_libraries(LibsModule -lpthread)
target_link_libraries(LibsModule liblapack.a)
target_link_libraries(LibsModule -L/home/user/libs/somelibpath/)
ADD_EXECUTABLE(MyProgramExecBlaBla main.cpp)
target_link_libraries(MyProgramExecBlaBla LibsModule)

The most important thing to understand is the module structure, where you create modules and link them all together with your executable. Once this works, you can complicate your project further with more details. Good luck!


Note: Keep in mind that this is the simple way to use CMake. The better cross-platform way would be using find_package, which locates a package/library, and provides the libraries and includes in CMake variables so that you could link your program to them. Here's how to do this for boost, for example.

🌐
VisualGDB
visualgdb.com › tutorials › linux › cmake › target_link_libraries
Using the target_link_libraries() statement to control the linked libraries – VisualGDB Tutorials
June 14, 2019 - Once you have located the library, add its full path to the Linked Libraries field under the VS properties for your main CMake target. Note that if the project is built on the Windows side, you would need to use the ${CMAKE_SYSROOT} prefix to refer to the sysroot directory (a copy of the Raspberry Pi’s file system that is bundled with the toolchain). In this example the library path would be ${CMAKE_SYSROOT}/usr/lib/arm-linux-gnueabihf/libsqlite3.a:
🌐
GitHub
github.com › retifrav › cmake-target-link-libraries-example
GitHub - retifrav/cmake-target-link-libraries-example: An example of CMake target_link_libraries() scopes effects
$ cd /path/to/cmake-target-link-libraries-example/tl $ mkdir build && cd $_ $ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="../install" \ -DCMAKE_PREFIX_PATH="/path/to/cmake-target-link-libraries-example/prjct/install;/path/to/cmake-target-link-libraries-example/dpndnc/install" \ ..
Author   retifrav
🌐
CMake
cmake.org › cmake › help › latest › command › link_libraries.html
link_libraries — CMake 4.3.0-rc2 Documentation
Specify libraries or flags to use when linking any targets created later in the current directory or below by commands such as add_executable() or add_library().
Find elsewhere
🌐
CMake
cmake.org › cmake › help › latest › prop_tgt › LINK_LIBRARIES_STRATEGY.html
LINK_LIBRARIES_STRATEGY — CMake 4.3.0-rc1 Documentation
Entries of LINK_LIBRARIES may be reordered, de-duplicated, and intermixed with indirect link dependencies. This may result in more efficient link lines, but does not give projects any control of ordering among independent entries. In the above example, this strategy computes a link line for main by re-ordering its original entries A B C to satisfy the dependencies of B and C on A.
🌐
MIT
stuff.mit.edu › afs › athena › software › root_v6.12 › arch › amd64_linux26 › doc › cmake › html › command › target_link_libraries.html
target_link_libraries — CMake 3.10.1 Documentation
See the cmake-buildsystem(7) manual for more on defining buildsystem properties. target_link_libraries(<target> <PRIVATE|PUBLIC|INTERFACE> <item>... [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
🌐
CMake
cmake.org › cmake › help › latest › command › target_link_directories.html
target_link_directories — CMake 4.2.3 Documentation
The named <target> must have been created by a command such as add_executable() or add_library() and must not be an ALIAS target. The INTERFACE, PUBLIC and PRIVATE keywords are required to specify the scope of the items that follow them. PRIVATE and PUBLIC items will populate the LINK_DIRECTORIES property of <target>. PUBLIC and INTERFACE items will populate the INTERFACE_LINK_DIRECTORIES property of <target> (IMPORTED targets only support INTERFACE items).
🌐
Decovar
decovar.dev › blog › 2023 › 07 › 22 › cmake-target-link-libraries-scopes
CMake target_link_libraries() scopes | Declaration of VAR
November 15, 2024 - $ cd /path/to/cmake-target-link-libraries-example/prjct $ mkdir build && cd $_ $ cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="../install" \ -DCMAKE_PREFIX_PATH="/path/to/cmake-target-link-libraries-example/dpndnc/install" ...
🌐
CMake
cmake.org › cmake › help › latest › prop_tgt › INTERFACE_LINK_LIBRARIES.html
INTERFACE_LINK_LIBRARIES — CMake 4.3.0-rc3 Documentation
Contents of INTERFACE_LINK_LIBRARIES may use "generator expressions" with the syntax $<...>. See the cmake-generator-expressions(7) manual for available expressions. See the cmake-buildsystem(7) manual for more on defining buildsystem properties. ... A call to target_link_libraries(<target> ...) may update this property on <target>. If <target> was not created in the same directory as the call then target_link_libraries() will wrap each entry with the form ::@(directory-id);...;::@, where the ::@ is literal and the (directory-id) is unspecified.
🌐
ICS
ics.com › blog › find-and-link-libraries-cmake
Find and Link Libraries with CMake | ICS
June 21, 2023 - This will look for a CMakeLists.txt file in that directory so we will write that next. We also need to link our target to the library that we are going to create. To do this, we call target_link_libraries.
🌐
GitHub
hsf-training.github.io › hsf-training-cmake-webpage › 04-targets › index.html
Working with Targets – More Modern CMake
January 28, 2026 - Once you have several targets, you can describe the relationship between them with target_link_libraries and a keyword; one of PUBLIC, PRIVATE, and INTERFACE. Don’t forget this keyword when making a library! CMake goes into an old compatibility mode for this target that generally breaks things.
🌐
CMake
cmake.org › cmake › help › latest › prop_tgt › LINK_LIBRARIES_ONLY_TARGETS.html
LINK_LIBRARIES_ONLY_TARGETS — CMake 4.2.1 Documentation
This property is initialized by the value of the CMAKE_LINK_LIBRARIES_ONLY_TARGETS variable when a non-imported target is created. The property may be explicitly enabled on an imported target to check its link interface. In the following example, CMake will halt with an error at configure time because miLib is not a target:
🌐
CMake
cmake.org › cmake › help › latest › guide › tutorial › Getting Started with CMake.html
Step 1: Getting Started with CMake — CMake 4.3.0-rc3 Documentation
Continue to edit files from Step1. Start on TODO 7 and complete through TODO 9. In this exercise, we need to add the MathFunctions target to the Tutorial target's linked libraries using target_link_libraries().
🌐
CMake
cmake.org › cmake › help › latest › guide › tutorial › In-Depth CMake Target Commands.html
Step 4: In-Depth CMake Target Commands — CMake 4.3.0-rc3 Documentation
When target_link_libraries() is given an argument which does not map to a target name, it will add the string directly to the link line as a library to be linked into the build (prepending any appropriate flags, such a -l).
🌐
Mirkokiefer
mirkokiefer.com › cmake-by-example-f95eb47d45b1
CMake by Example - Mirko Kiefer
add_subdirectory makes the library test defined in libtest_project available to the build. In target_link_libraries we tell CMake to link it to our executable.
🌐
Schneide Blog
schneide.blog › 2016 › 04 › 08 › modern-cmake-with-target_link_libraries
Modern CMake with target_link_libraries – Schneide Blog
April 8, 2016 - Of course, it’s all in the CMake documentation, but mentioned implicitly at best. The gist is this: Using target_link_libraries to link A to an internal target B will not only add the linker flags required to link to B, but also the definitions, include paths and other settings – even transitively – if they are configured that way.