Today, we will delve into two heavyweight topics: package management installation configuration and best practices along with common issues.
Have you also encountered these situations:
-
Wrote a fantastic library but don’t know how to let others use it elegantly; -
After sharing the project, others always complain about “missing dependencies”; -
Clearly configured CMakeLists.txt, yet still falls into some strange “pits”.
Don’t worry, this article will guide you step by step to solve these problems and remove the stumbling blocks on your development path!
A mind map to help you quickly understand the whole picture of CMake:

Friendly Reminder: Original content is not easy to create. If you find this content helpful, don’t forget to like, share, or give a “look” for support! Thank you very much!🌟
14. CMake Package Management and Installation Configuration: Distributing Your Library Elegantly
Once you have written a library, the next step is to make it easy for others to use. This is not just about copying header files and library files, but also about how to automatically resolve dependencies and simplify the user experience.
CMake provides powerful package management and installation configuration capabilities. By effectively utilizing these mechanisms, you can achieve a professional distribution scheme, allowing others to easily find your library with <span>find_package()</span>
. Now, let’s go through a practical example and explain how to complete a full installation configuration step by step.
Scenario Restoration: You Developed a Math Library
Assume you wrote a simple math library <span>MathLib</span>
that can perform addition and subtraction. The code structure is as follows:
MathLib/
├── CMakeLists.txt # Top-level CMake configuration file
├── include/
│ └── MathLib.h # Header file
├── src/
│ └── MathLib.cpp # Source file
└── main.cpp # Example program (for testing)
The goal is simple:
-
Package the library and header files together; -
Allow others to find and use your library with <span>find_package(MathLib)</span>
easily; -
Ensure that this library works smoothly without pitfalls after installation.
1. Project Initialization: Writing CMakeLists.txt
First, tell CMake that this is a library project and set the header file path:
cmake_minimum_required(VERSION 3.14)
project(MathLib VERSION 1.0.0)
# Define static library target
add_library(MathLib STATIC src/MathLib.cpp)
# Set header file path
target_include_directories(MathLib PUBLIC
$<build_interface:${cmake_source_dir} include=""> # Used during build
$<install_interface:include> # Used after installation
)
</install_interface:include></build_interface:${cmake_source_dir}>
Interpretation:
-
<span>add_library(MathLib STATIC src/MathLib.cpp)</span>
: This tells CMake that we want to generate a static library named<span>MathLib</span>
; -
<span>target_include_directories</span>
: Sets the header file path. -
<span>BUILD_INTERFACE</span>
indicates the use of the<span>include/</span>
folder during the build phase; -
<span>INSTALL_INTERFACE</span>
indicates that the library and header files will be copied to the user-specified installation path after installation, such as /usr/local/include or a custom /path/to/install/include.
In simple terms, this way, users can find the header files whether they are using them during development or after installation.
2. Installing Library and Header Files
Now that the library can be compiled normally in the project, to make it easier for others to use, we need to create an “installation package.” The goal of the installation is to organize the library and header files and place them in a location that is easy for users to find.
In <span>CMakeLists.txt</span><span>, we need to add installation rules:</span>
# Install library files
install(TARGETS MathLib
EXPORT MathLibTargets # Export target configuration
ARCHIVE DESTINATION lib # Static library installed to lib directory
LIBRARY DESTINATION lib # Dynamic library (if any) installed to lib directory
RUNTIME DESTINATION bin # Executable files (if any) installed to bin directory
INCLUDES DESTINATION include # Install header file path
)
# Install header files
install(DIRECTORY include/ DESTINATION include)
What does this code do?
1.<span>install(TARGETS MathLib ...)</span>
This defines the installation rules for the library files, for example:
-
The static library ( <span>libMathLib.a</span>
) will be installed to the<span>lib/</span>
directory; -
If it is a dynamic library ( <span>libMathLib.so</span>
), it will also be placed in the<span>lib/</span>
; -
Executable files (if any) will be placed in the <span>bin/</span>
; -
The header file path will also be exported to help users find it.
2.<span>install(DIRECTORY include/ DESTINATION include)</span>
This line is straightforward: it copies the header files in the <span>include/</span>
directory to the installation path’s <span>include/</span>
.
Where is the installation path?
CMake will by default install these files to a “root path,” which is the path you specify when running the install command with <span>--prefix</span><span>. For example, if you execute the following command:</span>
cmake --install build --prefix /path/to/install
The final installation result will look like this:
/path/to/install/
├── lib/ # Library files
│ └── libMathLib.a
├── include/ # Header files
│ └── MathLib.h
Note:
-
<span>lib/</span>
and<span>include/</span>
are relative paths defined by<span>install()</span>
; -
<span>--prefix</span>
specifies the installation root directory, and the final path is the concatenation of the two.
After completing this step, the library and header files are ready for distribution.
3. Generating Configuration Files
To allow users to find the library with <span>find_package(MathLib)</span><span>, we need to generate two configuration files:</span>
-
MathLibTargets.cmake: Automatically generated by CMake to record detailed information about the library; for example:
-
Where the library files are located ( <span>libMathLib.a</span>
or<span>libMathLib.so</span>
); -
Where the header file path ( <span>include/MathLib.h</span>
is located).
<span>MathLibTargets.cmake</span><span>. When users call </span><code><span>find_package(MathLib)</span><span>, CMake will first load </span><code><span>MathLibConfig.cmake</span><span>, and then find the detailed information about the library through it.</span>
In <span>CMakeLists.txt</span><span>, add the following content:</span>
# Export MathLibTargets.cmake
install(EXPORT MathLibTargets
FILE MathLibTargets.cmake # Exported file name
NAMESPACE MathLib:: # Namespace, users will access your library using MathLib::MathLib
DESTINATION lib/cmake/MathLib # Installation path
)
# Install MathLibConfig.cmake
install(FILES cmake/MathLibConfig.cmake DESTINATION lib/cmake/MathLib)
What does this code do?
<span>install(EXPORT MathLibTargets ...)</span>
:-
Tells CMake to automatically generate a <span>MathLibTargets.cmake</span>
file; -
The file will record the library path, header file path, and other information; -
Sets the namespace <span>MathLib::</span>
, allowing users to use your library through<span>MathLib::MathLib</span>
.
<span>install(FILES ...)</span>
:-
Installs the handwritten <span>MathLibConfig.cmake</span>
file to the same directory as<span>MathLibTargets.cmake</span>
; -
<span>MathLibConfig.cmake</span>
is responsible for including<span>MathLibTargets.cmake</span>
.
Then, create a new file named <span>MathLibConfig.cmake</span>
in the <span>cmake/</span>
directory with the following content:
# Load MathLibTargets.cmake
include("${CMAKE_CURRENT_LIST_DIR}/MathLibTargets.cmake")
Explain the code:
-
<span>${CMAKE_CURRENT_LIST_DIR}</span>
: Represents the directory where the current file (<span>MathLibConfig.cmake</span>
) is located; -
<span>include(...)</span>
: Loads the<span>MathLibTargets.cmake</span>
in the same directory, passing the detailed information of the library to CMake.
In simple terms, the purpose of this file is to tell CMake where <span>MathLibTargets.cmake</span>
is located.
Then, create a new file in the <span>cmake/</span>
directory named <span>MathLibConfig.cmake</span>
with the content:
# Load MathLibTargets.cmake
include("${CMAKE_CURRENT_LIST_DIR}/MathLibTargets.cmake")
The purpose of this file is to load <span>MathLibTargets.cmake</span>
, allowing users to find the target using <span>find_package(MathLib)</span>
.
4. Handling Dependency Libraries
Sometimes, your library may depend on other libraries, such as Boost or OpenCV. To ensure that users do not need to configure these dependencies when using your library, you can handle them in the following two steps:
1. Declare Dependencies in the Configuration File
Append the following content to <span>MathLibConfig.cmake</span><span>:</span>
include(CMakeFindDependencyMacro)
find_dependency(Boost REQUIRED) # Declare dependency on Boost
include("${CMAKE_CURRENT_LIST_DIR}/MathLibTargets.cmake")
Explanation:
-
<span>include(CMakeFindDependencyMacro)</span>
: Introduces a macro specifically for declaring dependencies. -
<span>find_dependency(Boost REQUIRED)</span>
: Tells CMake that<span>MathLib</span>
depends on Boost.
When users call <span>find_package(MathLib)</span><span>, CMake will automatically attempt to load Boost.</span>
2. Bind Dependencies to Targets
In <span>CMakeLists.txt</span><span>, tell CMake that </span><code><span>MathLib</span>
uses Boost:
target_link_libraries(MathLib PUBLIC Boost::Boost)
-
<span>PUBLIC</span>
: Indicates that Boost is a public dependency of<span>MathLib</span>
, and any target that links to<span>MathLib</span>
(such as the user’s program) will automatically inherit this dependency.
3. Final Effect
When users use your library in their projects, they only need to write the following code:
find_package(MathLib REQUIRED)
target_link_libraries(MyApp PUBLIC MathLib::MathLib)
-
CMake will automatically load <span>MathLib</span>
and its dependency Boost; -
Users do not need to configure Boost separately, making the usage process very smooth!
5. How Users Use Your Library
5.1 Developer Installs the Library and Distributes It to Users
First, the developer (yourself) needs to run the installation command to organize the library and distribute it to users. Suppose you want to install it to <span>/path/to/install</span><span>:</span>
cmake -S . -B build
cmake --install build --prefix /path/to/install
After executing this command, the installation result may look like this:
/path/to/install/
├── include/ # Header files
│ └── MathLib.h
├── lib/ # Library files
│ └── libMathLib.a
└── lib/cmake/MathLib/ # Configuration files
├── MathLibConfig.cmake
└── MathLibTargets.cmake
This directory contains your library, header files, and configuration files. Users only need to obtain this directory to conveniently use it in their own projects.
5.2 How Do Users Obtain the Library?
This step is very important. Users can obtain your library in the following ways:
-
The developer directly distributes the installation directory: You compress <span>/path/to/install/MathLib</span>
into a package (like<span>MathLib-1.0.0.zip</span>
) and send it to the user. After the user unzips it, they can directly use this library. -
The developer provides an installation package (generated by CPack): If you created a <span>.zip</span>
,<span>.deb</span>
, or<span>.rpm</span>
installation package using CPack, users can directly unzip or install it to their system using package management tools.
Next, users only need to configure the project to let CMake know where to find this library.
5.3 User’s CMakeLists.txt Configuration
Assuming the user’s project directory structure is as follows:
MyApp/
├── CMakeLists.txt # User's CMake configuration
├── main.cpp # User's code
The user needs to tell CMake where to find your library in their <span>CMakeLists.txt</span><span>:</span>
cmake_minimum_required(VERSION 3.14)
project(MyApp)
# Specify the path to MathLib
list(APPEND CMAKE_PREFIX_PATH "/path/to/install")
# Find MathLib
find_package(MathLib REQUIRED)
# Define the user's executable
add_executable(MyApp main.cpp)
target_link_libraries(MyApp PRIVATE MathLib::MathLib)
What does this code do?
-
<span>list(APPEND CMAKE_PREFIX_PATH ...)</span>
: This line is crucial! It tells CMake to look in the<span>/path/to/install</span>
directory for<span>MathLib</span>
.If this line is missing, CMake will not know where your library is and will throw an error. -
<span>find_package(MathLib REQUIRED)</span>
: This line will load the<span>MathLibConfig.cmake</span>
file, which will then load your library target (<span>MathLibTargets.cmake</span>
) and configure the path. -
<span>target_link_libraries</span>
: Finally, the user links their program<span>MyApp</span>
with<span>MathLib</span>
.
5.4 User Compiles the Project
Users can directly run the following commands to compile their project:
cmake -S . -B build # Configure the project and generate build files in the build/ directory
cmake --build build # Compile the project using the build/ directory's build files
These steps will accomplish:
-
CMake finds <span>MathLib</span>
in the<span>CMAKE_PREFIX_PATH</span>
; -
Loads <span>MathLibConfig.cmake</span>
and the library target information; -
Links the user’s program <span>main.cpp</span>
with your library to generate the executable.
Summary:
Through the above steps, you have completed a professional library distribution scheme:
1. Install Library and Header Files: Package the library files and header files together;
2. Generate Configuration Files: Allow others to automatically find it using <span>find_package(MathLib)</span>
;
3. Easy for Users: Users only need to set <span>CMAKE_PREFIX_PATH</span>
and link the library.
After reading, don’t you think CMake package management and installation configuration isn’t that difficult? Give it a try!
15. CMake Best Practices and Common Issues
CMake is a powerful tool, but if not used carefully, it can lead to pitfalls, especially when the project scales up or dependencies become complex. To help you use CMake more efficiently and reliably, here are some best practices and solutions to common problems, presented clearly for easy implementation!
Best Practices: Make Your CMake Project More Elegant
1. Clearly Define Minimum Version Requirements
Always write <span>cmake_minimum_required</span>
at the beginning of your <span>CMakeLists.txt</span><span>, specifying the minimum version number.</span>
cmake_minimum_required(VERSION 3.14)
-
Why is it important? Different versions of CMake may have different features, and clearly stating the version can avoid inexplicable errors in lower version environments.
2. Clear Project Structure
Manage code, header files, third-party libraries, and build files separately. You can refer to the following structure:
MyProject/
├── CMakeLists.txt # Top-level configuration file
├── src/ # Source code
├── include/ # Header files
├── third_party/ # Third-party libraries
├── tests/ # Test code
└── cmake/ # Custom CMake modules
Recommendation: Use <span>include/</span>
to manage public header files, and place only private code in <span>src/</span>
. This way, when others use your project, they won’t be polluted by private implementations.
3. Use <span>target_*</span>
Series Commands
Try to use <span>target_*</span>
series commands (like <span>target_include_directories</span>
, <span>target_link_libraries</span>
) instead of global variables (like <span>CMAKE_CXX_FLAGS</span>
). This ensures that configurations are target-independent, reducing interference.
# Recommended: Set options for each target separately
target_compile_options(my_target PRIVATE -Wall -Wextra)
# Not recommended: Directly modify global compiler options
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
4. Modular Management of Multiple Subprojects
If your project has multiple modules or subprojects, you can use <span>add_subdirectory()</span><span> to integrate them.</span>
MyProject/
├── CMakeLists.txt # Top-level CMake configuration
├── src/
│ ├── ModuleA/
│ │ ├── CMakeLists.txt
│ │ └── ...code...
│ ├── ModuleB/
│ │ ├── CMakeLists.txt
│ │ └── ...code...
Top-level CMake file:
cmake_minimum_required(VERSION 3.14)
project(MyProject)
# Add subprojects
add_subdirectory(src/ModuleA)
add_subdirectory(src/ModuleB)
Subproject CMake file:
add_library(ModuleA module_a.cpp)
target_include_directories(ModuleA PUBLIC ${CMAKE_SOURCE_DIR}/include)
5. Explicitly Set Standards (C++11/14/17/20, etc.)
Clearly specify the C++ standard to avoid relying on the compiler’s default settings.
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
Almost all modern C++ projects require this setting.
6. Use <span>find_package</span>
to Manage Dependencies
For third-party libraries, prefer using <span>find_package()</span><span>, which allows CMake to automatically find and link the library:</span>
find_package(Boost REQUIRED)
target_link_libraries(my_target PRIVATE Boost::Boost)
If there is no existing <span>find_package</span>
configuration, you can use <span>FetchContent</span>
to dynamically pull it:
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.12.1
)
FetchContent_MakeAvailable(googletest)
7. Use <span>CMAKE_INSTALL_PREFIX</span>
to Define Installation Paths
Do not hard-code paths
Writing fixed paths like below can cause permission issues and inflexibility:
install(TARGETS MyLib DESTINATION /usr/local/lib)
install(DIRECTORY include/ DESTINATION /usr/local/include)
Recommended Writing:
Use relative paths, allowing users to customize the installation location through <span>CMAKE_INSTALL_PREFIX</span><span>:</span>
install(TARGETS MyLib DESTINATION lib)
install(DIRECTORY include/ DESTINATION include)
Users specify the path:
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/path/to/install
cmake --build build
cmake --install build
-
The files will be installed to <span>/path/to/install/lib</span>
and<span>/path/to/install/include</span>
. -
More flexible, no need for administrator permissions, and works well across platforms!
8. Define Installation Rules
Clearly define the installation paths for your library, header files, and configuration files for easy distribution and integration:
install(TARGETS my_library
EXPORT MyLibraryTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
INCLUDES DESTINATION include
)
9. Clearly Define Build Types
-
By default, CMake builds may not have a specific build type (Debug, Release, etc.) set. -
It is recommended to set a default build type in <span>CMakeLists.txt</span><span> to avoid accidentally using an unoptimized build.</span>
Example:
# Default build type is Release
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the build type" FORCE)
endif ()
-
Users can set it through the command line:
cmake -DCMAKE_BUILD_TYPE=Debug ..
10. Enable Unit Testing
Use CMake’s testing features (like <span>CTest</span><span>) to integrate testing frameworks like Google Test:</span>
enable_testing()
# Add test executable
add_executable(my_test test.cpp)
target_link_libraries(my_test PRIVATE gtest gtest_main)
# Register tests
add_test(NAME MyTest COMMAND my_test)
You can quickly run all tests using the <span>ctest</span>
command:
ctest --output-on-failure
11. Use a Build Directory to Separate Build Files
Generating a separate <span>build</span>
directory is one of CMake’s best practices. The main benefit is to keep the source directory clean and manage builds flexibly.
Why use a build directory?
-
Clean source code: All build files (like <span>Makefile</span>
, intermediate files) are in the<span>build</span>
directory, keeping the source code unpolluted. -
Supports multiple build types: You can create <span>build-debug</span>
,<span>build-release</span>
, etc., to manage debug and release versions separately. -
Easy to clean: Deleting the <span>build</span>
directory allows for easy rebuilding without affecting the source code.
How to use it?
mkdir build && cd build
cmake -S .. -B .
make
-
<span>-S ..</span>
: Specifies the source directory. -
<span>-B .</span>
: Specifies the build directory (current directory).
In summary, using a <span>build</span>
directory for project builds is clean, worry-free, and easy to manage. Always start by creating a <span>build</span>
directory when using CMake!
12. Define Interface Libraries
If there are some header files without implementations (such as interfaces or pure abstract classes), you can manage them using an <span>INTERFACE</span>
library:
add_library(MyInterface INTERFACE)
target_include_directories(MyInterface INTERFACE ${CMAKE_SOURCE_DIR}/include)
Interface libraries (INTERFACE) are used to configure some public linking and compilation options. They may be less common in small projects but are common in large projects.
13. Provide Options to Users
Use <span>option()</span><span> to provide configurable feature switches, allowing users to use your project more flexibly.</span>
Example:
option(ENABLE_TESTS "Enable building tests" ON)
if (ENABLE_TESTS)
add_subdirectory(tests)
endif()
In this way, users can control whether to build tests through the command line:
cmake -DENABLE_TESTS=OFF ..
14. Use <span>GNUInstallDirs</span>
for Cross-Platform Installation
To adapt to different platform installation paths, use the <span>GNUInstallDirs</span>
module:
include(GNUInstallDirs)
install(TARGETS mylib
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
This ensures that your library is installed correctly on Linux, Windows, and macOS.
15. Support Multi-Platform Toolchains
If your project needs to support multiple platforms (like Windows, Linux, and macOS) or requires cross-compiling (like building for embedded devices), correctly setting up the toolchain file is key.
-
In cross-platform projects, ensure to correctly set the toolchain file. For example:
cmake -DCMAKE_TOOLCHAIN_FILE=path/to/toolchain.cmake ..
-
Example toolchain file:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_C_COMPILER /usr/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/arm-linux-gnueabihf-g++)
This makes it easy to support cross-compiling and multi-platform builds.
16. Optimize Build Time
Enable Parallel Builds
Enable parallel builds through <span>make</span>
or CMake commands:
cmake --build . -j$(nproc)
Build by Target
Compile only the specified target to avoid recompiling the entire project:
cmake --build . --target my_target
Common Problems and Solutions
1. Dependency Library Not Found
Problem: CMake reports <span>Could not find ...</span>
.
Solution:
<span>CMAKE_PREFIX_PATH</span><span>:</span>
cmake -DCMAKE_PREFIX_PATH=/path/to/dependency -S . -B build
<span>FetchContent</span><span>.</span>
2. Header File Path Confusion
Problem: Header files are not found, or multiple modules have the same header file name.
Solution:
<span>target_include_directories</span>
to clearly specify the header file path:By using <span>target_include_directories</span>
to specify the header file path for the target (like <span>my_target</span>
), the compiler knows where to look for header files.
target_include_directories(my_target PRIVATE src/)
-
<span>PRIVATE</span>
: Indicates that this header file path is only for<span>my_target</span>
and will not propagate to other targets.Applicable Scenario: If the header file is only used for implementation details and does not need to be exposed, use<span>PRIVATE</span>
.
If multiple modules (libraries) of the project need to share header files, you can place the header files in a public <span>include/</span>
directory and mark the path as <span>PUBLIC</span>
:
target_include_directories(my_target PUBLIC include/)
-
<span>PUBLIC</span>
: Indicates that this path is not only for<span>my_target</span>
, but will also propagate to other targets that link to<span>my_target</span>
.
3. Cross-Compilation Errors
Problem: CMake is using the host compiler instead of the cross-compiler.
Solution:
-
Use a toolchain file to specify the cross-compiler:
cmake -DCMAKE_TOOLCHAIN_FILE=path/to/toolchain.cmake -S . -B build
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
4. Problem: Files Not Updated During Build
Problem: Files were modified, but they were not recompiled during the build.
Solution:
-
Check if file dependencies are correct, ensuring that <span>add_custom_command</span>
has configured all related files in<span>DEPENDS</span>
. -
If you manually modified generated files, clear the build directory and regenerate:
cmake --build . --clean-first
5. Linkage Stage Cannot Find Symbols
Problem: Reports <span>undefined reference</span>
. This usually occurs during the linkage stage, indicating that the definitions of certain symbols (function or variable implementations) cannot be found.
Solution:
-
Ensure that the linked libraries include implementation files.
-
Check if <span>add_library</span>
has correctly added the implementation files:
add_library(my_library src/my_library.cpp)
-
Ensure that <span>target_link_libraries</span>
specifies this library:
target_link_libraries(my_target PRIVATE my_library)
In CMake, the order of linking libraries is crucial, especially for static libraries. If one library depends on another, the dependency must be placed after it:
target_link_libraries(my_target PRIVATE my_library dependency_library)
6. Problem: Build Time Too Long
Problem: Long build times for large projects.
Solution:
-
Enable parallel builds:
cmake --build . -j$(nproc) # Let CMake use all available CPU cores for parallel compilation.
<span>ccache</span><span> to cache compilation results:</span>
set(CMAKE_CXX_COMPILER_LAUNCHER ccache)
7. Runtime Cannot Find Dynamic Library
Problem: The program cannot find the dynamic library at runtime, reporting errors like:
-
Linux: <span>error while loading shared libraries: libMyLib.so: cannot open shared object file</span>
-
Windows: <span>DLL load failed</span>
-
macOS: <span>dyld: Library not loaded: @rpath/libMyLib.dylib</span>
Reason: The dynamic library path is not configured correctly, and the operating system cannot find the dynamic library.
Solution:
1. Set Environment Variables:
-
Linux/macOS: Use <span>LD_LIBRARY_PATH</span>
or<span>DYLD_LIBRARY_PATH</span>
:
export LD_LIBRARY_PATH=/path/to/lib:$LD_LIBRARY_PATH
-
Windows: Add the dynamic library path to the <span>PATH</span>
environment variable.
<span>RPATH</span>
: Set the runtime search path in CMake:set(CMAKE_INSTALL_RPATH "$ORIGIN")
Summary
CMake is a powerful tool, but to use it well, you need some skills and experience.
-
Package Management and Installation Configuration: The focus is on making your library easy to use and install. Write a good CMakeLists.txt, install the library, header files, and configuration files properly, handle the dependency issues, and finally provide users with a simple usage guide, so that your library can truly be considered “elegant”. -
Best Practices: Remember a few key points, such as clearly defining the minimum version, reasonably organizing the project structure, using <span>target_*</span>
to manage build configurations, clearly defining installation rules and build types. Don’t forget to support multiple platforms and optimize build times; these details can make your project look more professional. -
Common Issues: Issues like missing dependencies, confused paths, and cross-compilation errors ultimately boil down to configuration problems. Check libraries, paths, variables, and system environments, and you can usually resolve them. Problems like undefined symbols during linking or long build times often stem from a lack of dependency management or optimization steps.
In a nutshell, the essence of CMake is “norms” and “details.” As long as you follow the rules, you will encounter fewer pitfalls, and your efficiency will naturally improve!
You may also like:
A very lightweight embedded logging library!
An object-oriented C language framework!
A very lightweight embedded thread pool library!
Popular C language projects on GitHub!
Practical | Teach you to turn on lights via web in 10 minutes
WiFi6 + Bluetooth + Star Flash, a three-in-one development board, really fragrant!