CMake for Building and Linking
CMake is a powerful cross-platform build system that simplifies building C/C++ projects, especially when it comes to managing libraries and linking.
Here's a comprehensive look at using CMake for building and linking, complete with examples:
Project Setup
Create a directory for your project.
Inside the project directory, create a file named
CMakeLists.txt
. This is the heart of your CMake configuration.Create a build directory
Write your CMakeLists.txt
Move to build directory
Run
cmake ..
Run
make
Refer to CMake documentation for specific library names and linking instructions.
Create a separate build directory and run cmake
there.
Building a Simple Static Library
Explanation:
cmake_minimum_required(VERSION 3.0)
: This line specifies the minimum required version of CMake for this project.project(MyStaticLib)
: This line defines the project name, which is used for generating build files.add_library(MyStaticLib STATIC source1.cpp source2.cpp)
: This line creates a static library namedMyStaticLib
from the source filessource1.cpp
andsource2.cpp
.
Building an Executable and Linking with the Static Library
Explanation:
target_include_directories(MyProgram PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
: This line tells the compiler where to find header files. Since the static library might have headers, we include the current binary directory (where the library is built) in the search path.add_executable(MyProgram main.cpp)
: This line creates an executable namedMyProgram
from the source filemain.cpp
.target_link_libraries(MyProgram PRIVATE MyStaticLib)
: This line links the executableMyProgram
with the previously created static libraryMyStaticLib
. ThePRIVATE
keyword indicates that the library is private to this project and shouldn't be exposed to other projects linking against this executable.
Building a Shared Library
Explanation:
This line is similar to creating a static library, but instead of STATIC
, we use SHARED
to create a shared library named MySharedLib
.
Linking with External Libraries using find_package
Explanation:
find_package(Threads REQUIRED)
: This line attempts to find a package namedThreads
(replace with the actual library name, likeOpenSSL
orSDL2
). TheREQUIRED
keyword ensures CMake throws an error if the library is not found.target_include_directories(MyProgram PRIVATE "${CMAKE_THREAD_INCLUDE_DIRS}")
: This line includes the library's header directory (CMAKE_THREAD_INCLUDE_DIRS
) in the search path forMyProgram
.target_link_libraries(MyProgram PRIVATE Threads::Threads)
: This line links the executable with the external library's target (Threads::Threads
).
Advanced Linking Options and Flags
Visibility Control
You can control which symbols from a library are visible to linked programs using compiler flags like -fvisibility=hidden
(GCC) or /DEF:{symbol}
(MSVC).
CMake can help manage these flags through target properties:
Explanation:
The
if
statement checks the compiler ID.If it's GCC,
target_compile_properties
sets theCVISIBILITY_PRESET
property to "hidden" for the targetMyLib
, effectively hiding symbols by default.Custom Linker Flags: You can pass custom linker flags using
target_link_libraries
with theLINK_OPTIONS
clause:
Explanation:
This line links the program
MyProgram
withMyLib
and adds the linker flag-Wl,-rpath,/path/to/additional/libraries
, specifying an additional search path for libraries at runtime.
Cross-Platform Considerations
Toolchain Files: CMake allows defining toolchain files that specify compiler and linker settings for different platforms. This enables consistent builds across operating systems.
Platform-Specific Flags: Be mindful of platform-specific compiler and linker flags. CMake can handle some of these through built-in properties like
CMAKE_CXX_FLAGS
orCMAKE_EXE_LINKER_FLAGS
, but you might need to add custom flags for specific needs.
Example of a cross platform build:
Explanation:
CMake Minimum Version: We specify the minimum required CMake version.
Project Name: We define the project name.
Finding Threads Library: We use
find_package(Threads REQUIRED)
to attempt finding thepthread
library. This might require replacingThreads
with the actual package name for your target platform (e.g.,PkgConfig
on some Linux distributions).Include Directories: We set the include directories for our project headers and the headers from the
Threads
package.Source Files: We define the source files for our application.
Linking with Threads: We link the executable
MyProgram
with the targetThreads::Threads
from the found library.Platform-Specific Flags (Optional): We use conditional statements to add platform-specific linker flags. On Linux, we link with
-lpthread
, and on macOS, we link with the-framework pthread
framework.
Last updated