1. Resource to Learn CMake
2. Starting Template
3. Common Commands
-
- Declare a target called
onethat refers to the current directory, and list all sources files to be compiled. Only the compilation unittwo.cppwill be compiled, we include the headers for IDE only.
- Declare a target called
-
-
Same as
add_library, it adds a target that refers to the current directory, and that target points to an executable. -
We cannot use
add_libraryandadd_targetat the same time. In other words, we should separatemain.cppand "source files" in separate folder. -
For example, we can separate like
some_proj/app/main.cppandsome_proj/src/some_lib/some_file.cppThen writesome_proj/app/CMakeLists.txtsome_proj/src/CMakeLists.txtsome_proj/src/some_lib/CMakeLists.txtseparately. Note thatsome_proj/src/CMakeLists.txtcan be as simple as just one line
as it helps point out which directory contains a
CMakeLists.txtto look at.
-
-
- It tells cmake compiler which directory to look for and execute a
CMakeLists.txt. If the directorysrccontains noCMakeLists.txtfile,cmakewill give an exception.
- It tells cmake compiler which directory to look for and execute a
-
-
It tells cmake our source files in the target
onehave included header files in other diectory such as../../include. -
We don't need to include it again in other target that links to
one, by simplytarget_link_libraries(we introduce it right below) we can directly include header files in source code thatonehave already included. -
If the include dir contains
include/four/five.h, then we can includefour/five.hin our source code.Note that the string to include our header file is independent of the target name we name in cmake.
-
In general,
target_include_directoriesis used when the header files are from other directory.
-
-
-
This is to build dependency between different targets. Which means that the target
anotherand its downstream linkers will need libraryonein the compilation process. -
Ya we have included the
includedirectory but very likely it just contains function declarations, we need the function body definitions by linking those libraries linking the source files. -
if
PUBLICis replaced byPRIVATE, it indicates that the downstream linkers ofanotherdo not need the libraryone, andanotheris the only target that needsone.
-
-
- Target library
onewe have a constantSOME_CONSTANTdefined by using#definein the header.
- Target library
-
- Require specific feature for a target.
-
-
SOME_CONSTANTis the variable name. -
We set
""as a default value. -
The value
<value>can also be passed by-Dargument: -
STRINGdefined the data type of the cached value<value>.
-
-
- This is a standard if statement.
-
- It defines a boolean for cmake files to use.
- We can pass this variable in command line by
4. Include Predefined CMake Functions
Usually every cmake project contains a cmake/ folder that contains custom cmake script:
CMAKE_MODULE_PATHpoints to that cmake folderincludeis used to include the cmake filecmake/AddGitSubmodule.cmake. Exmaple of a.cmakefile:
5. Which Folder to Create CMakeLists.txt?
CMakeLists.txt?- Root directory.
- Set all necessary variables and add appropriate
add_subdirectory's to look forCMakeLists.txt.
- Set all necessary variables and add appropriate
- Source file directory
src.- It can consists of simply the
add_subdirectorycommands.
- It can consists of simply the
- Source file subdirectories
src/one,src/two, ....- Each of the subdirectory should consists of
add_libraryfor linkage andtarget_include_directoriesto include corresponding header files. - If the project structure is simpler, the rules to
src/<lib_name>/CMakeLists.txtcan be moved down tosrc/CMakeLists.txt.
- Each of the subdirectory should consists of
- Directory that does not need
CMakeLists.txt.- Directory that contains just header files needs no
CMakeLists.txt, as they will be included intarget_include_directoriessomewhere else once needed.
- Directory that contains just header files needs no
6. Show all Constants in a CMake Project
7. Special Functions to Check Variables in CMakeLists.txt
- The
printfunction will print defined constant andprint_envwill print the defined environment variable.
8. Graph Visualization of Dependencies Between cmake Files
cmake Files8.1. Install graphviz
For windows we can download a .msi file for installation HERE. For mac we run brew install graphviz.
8.2. MakeFile
8.2.1. Scrips
We create a file called MakeFile:
and run cmake dependency.
The prepare script is also included here, it is a default command that can be run by simply calling cmake.
From my own experience on a simple hello-world project I have:
8.2.2. Cmake Erorr: incompatible versions of the cygwin DLL
It is a known problem in windows, go to C:\Program Files\Git\usr\bin and rename msys-2.0.dll to _msys-2.0.dll to temporarily mitigate the problem.
Later you may need to rename it back since it affects commands such as npm and yarn.
9. Cross Platform Built Command
9.1. Source of Study
9.2. How to Build a CMake Project
9.3. How to Know Which Generator (specified by -G) is Available?
By
apart from the list of available arguments, it also prints a list of available generators for us.
In my case, I get
10. External Library (CMake Project)
10.1. By Direct Cloning
and then add_subdirectory(external/some_name) to seek for and execute the CMakeLists.txt.
10.2. By FetchContent
By adding include(FetchContent) in our CMakeLists.txt we can import functions
FetchContent_DeclareFetchContent_MakeAvailable
For example, suppose that we want to import the following CMake projects hosted in github:
where the GIT_TAG can be found in the release page of the corresponding repository. These library will be downloaded in build/_deps directory when we execute cmake build command.
To let our target (executable target or library target) link to these library, we run
The naming convention of the target is
<project_name>:<library_name>The<project_name>and<library_name>can be traced by looking theCMakeLists.txtof the repo.
Now our target LIBRARY_MY_LIB or any target that links to it can run the following preprocessor directives:
10.3. By conan
10.3.1. Files to Create
Create a virtual environment in Python, which I name it conan, then conda activate conan and pip install conan.
As if requirements.txt in Python we have an analog in conan, we create a text file conanfile.txt in project root and add the following content:
-
project_root/conanfile.txt -
project_root/CMakeLists.txt
In Makefile of project root directory we add
and run make prepare_conan.
10.3.2. Remarks to conan
I myself fail to work with conan in windows, maybe unix based system can make it work.
In general the database of conan usually lag behind to the latest release for at least half year, it is suggested not to use it when FetchContent suffices to serve the purpose.
11. CMake Examples
11.1. ChatClient TCP Server
11.1.1. Repo and Video
The whole project implementes a chatting function between multiple clients.
This blog post focuses on the CMakeLists.txt files.
11.1.2. Outermost CMakeLists.txt, the Project Level
11.1.3. The Main Library: Networking
11.1.4. NetClient
11.1.5. NetServer
11.2. Examples from Other Project
11.2.1. Sockets
This is a CMakeLists.txt file inside a directory called Sockets.
From the section The-Main-Library:-Networking we have read a use case
and plugged this into add_library. However, the Do's and Don'ts states that Don't GLOB files because:
Make or another tool will not know if you add files without rerunning CMake. Note that CMake 3.12 adds a
CONFIGURE_DEPENDSflag that makes this far better if you need to use it.
In other words, listing the source files explicitly will be a better practice.












