The complete guide to CMake. Part Two: Build system

The complete guide to CMake. Part Two: Build system  
Introduction 3r38282.
 
This article discusses the use of the CMake build system used in an enormous number of C /C ++ projects. It is strongly recommended to read 3r32424. The first part is 3r3687. guidelines to avoid misunderstanding CMake syntax, which appears throughout the article. 3r3694. official site 3r3687. . 3r3694.
 
The principle of operation 3r38282.
 
CMake build system
is a shell over other platform-dependent utilities (for example, 3r3338. Ninja
or 3r3403. Make
). Thus, in the assembly process itself, however paradoxical it may sound, it does not directly participate. 3r3694.
 
The CMake build system accepts as input. CMakeLists.txt with a description of the assembly rules in the formal language CMake, and then generates intermediate and native assembly files in the same directory adopted on your platform. 3r3694.
 

The generated files will contain specific names of system utilities, directories and compilers, while CMake commands operate only the abstract notion of a compiler and are not tied to platform-dependent tools, which differ greatly on different operating systems. 3r3694.
 
3r3355. Check version CMake
 

Team 3r360. cmake_minimum_required checks the running version of CMake: if it is less than the specified minimum, then CMake completes its work with a fatal error. An example showing typical usage of this command at the beginning of any CMake file:


 
3r3658. 3r3659. # Set the third minimum version of CMake:
cmake_minimum_required (VERSION 3.0) 3r3668.
 

Project design 3r3-3822.
 

At the beginning of any 3r3r6767. CMakeLists.txt You should set the project characteristics with the command project 3r3r777. for better design of integrated environments and other development tools. 3r3694.
 
3r3658. 3r3659. # Set the characteristics of the project "MyProject":
project (MyProject VERSION ???.4 LANGUAGES C CXX) 3r36-377. 3r3668.
 

It is worth noting that if the keyword LANGUAGES omitted, the default languages ​​are C CXX . You can also turn off the indication of any languages ​​by writing the keyword NONE 3r3777. as a list of languages ​​or just leave an empty list. 3r3694.
 
3r3105. Running script files
 

Team include replaces the line of your call with the code of the specified file, acting similarly to the preprocessor command include C /C ++ languages. This example runs the script file MyCMakeScript.cmake described command: 3r3694.
 
3r3658. 3r3659. message ("'TEST_VARIABLE' is equal to[${TEST_VARIABLE}]")
# Run the `MyCMakeScript.cmake` script to run:
include (MyCMakeScript.cmake)
message ("'TEST_VARIABLE' is equal to[${TEST_VARIABLE}]")

3r3668.
 

In this example, the first message will notify that the variable is TEST_VARIABLE not yet defined, however, if the script is MyCMakeScript.cmake will determine this variable, the second message will already inform about the new value of the test variable. Thus, the script file included by the command include , does not create its own scope, as is aptly about. mentioned 3r3687. in the comments to r3r3424. previous article 3r3687. . 3r3694.
 
3r3148. Compiling executable files
 

Team 3r31616. add_executable compiles the executable file with the specified name from the source list. It is important to note that the final file name depends on the target platform (for example, .Exe Or just 3r3161. 3r336777.). A typical example of calling this command is


 
3r3658. 3r3659. # Compile the executable file "MyExecutable" of
# of source "ObjectHandler.c", "TimeManager.c" and "MessageGenerator.c":
add_executable (MyExecutable ObjectHandler.c TimeManager.c MessageGenerator.c)
3r3668.
 
3r3174. Compiling libraries 3r38282.
 

Team add_library compiles a library with the specified view and name from sources. It is important to note that the final library name depends on the target platform (for example, Lib .A Or .Lib 3r37777.). A typical example of calling this command is


 
3r3658. 3r3659. # Compile the static library "MyLibrary" of
# source codes "ObjectHandler.c", "TimeManager.c" and "MessageConsumer.c":
add_library (MyLibrary STATIC ObjectHandler.c TimeManager.c MessageConsumer.c) 3r3668.
 
3r33232.  
Static libraries are specified by the keyword STATIC 3r3777. the second argument is the archives of the object files associated with executable files and other libraries at compile time.  
Dynamic libraries are defined by the keyword SHARED 3r3777. the second argument is the binary libraries loaded by the operating system during program execution.  
Modular libraries are defined by the keyword MODULE 3r3777. the second argument is the binary libraries loaded by execution techniques by the executable file itself.  
Object libraries are defined by the keyword OBJECT the second argument is the set of object files associated with executables and other libraries at compile time.  

 

Adding source to goal 3r38282.
 

There are cases that require adding source files to the target. For this, the command is provided. target_sources , able to add source to the target many times. 3r3694.
 

The first argument is the command target_sources accepts the name of the target previously specified with the commands add_library or 3r31616. add_executable and the following arguments are the list of source files to be added. 3r3694.
 

Repeated command calls target_sources add source files to the target in the order in which they were called, so the bottom two blocks of code are functionally equivalent:


 
3r3658. 3r3659. # Set the executable file "MyExecutable" from sources
# "ObjectPrinter.c" and "SystemEvaluator.c":
add_executable (MyExecutable ObjectPrinter.c SystemEvaluator.c)
# Add to the target "MyExecutable" source "MessageConsumer.c":
target_sources (MyExecutable MessageConsumer.c)
# Add to the target "MyExecutable" source code "ResultHandler.c":
target_sources (MyExecutable ResultHandler.c) 3r3668.
 
3r3658. 3r3659. # Set the executable file "MyExecutable" from sources
# "ObjectPrinter.c", "SystemEvaluator.c", "MessageConsumer.c" and "ResultHandler.c":
add_executable (MyExecutable ObjectPrinter.c SystemEvaluator.c MessageConsumer.c
ResultHandler.c) 3r3668.
 

Generated files 3r38282.
 

The location of the output files generated by the commands 3-333616. add_executable and add_library , is determined only at the generation stage, however, this rule can be changed with several variables defining the final location of the binary files: 3r3694.
 
3r33232.  

Variables 3r3302. RUNTIME_OUTPUT_DIRECTORY and 3r3306. RUNTIME_OUTPUT_NAME determine the location of the objectives of the implementation.  
Variables LIBRARY_OUTPUT_DIRECTORY and LIBRARY_OUTPUT_NAME determine the location of libraries.  
Variables 3r3323. ARCHIVE_OUTPUT_DIRECTORY and 3r3328. ARCHIVE_OUTPUT_NAME determine the location of the archives.  

 

Executable files are always viewed as execution targets, static libraries as archive targets, and modular libraries as library targets. For non-DLL platforms, dynamic libraries are considered library targets, and for DLL platforms, execution targets. For object libraries, such variables are not provided, since this kind of libraries is generated in the depths of the 3r3-3676 catalog. CMakeFiles . 3r3694.
 

It is important to note that the "DLL-platforms" are all platforms based on Windows, including 3r33344. Cygwin . 3r3694.
 

Compiling with libraries 3r3r8282.
 

Team target_link_libraries Compiles a library or executable file with other provided libraries. The first argument is that this command takes the name of the target generated using the commands 3r-33616. add_executable or add_library , and the following arguments are the names of library targets or full paths to libraries. Example: 3r3694.
 
3r3658. 3r3659. # Compile the executable file "MyExecutable" with
# libraries "JsonParser", "SocketFactory" and "BrowserInvoker":
target_link_libraries (MyExecutable JsonParser SocketFactory BrowserInvoker) 3r3668.
 

It should be noted that modular libraries are not subject to lineup with executable files or other libraries, since they are intended solely for downloading by technicians. 3r3694.
 
3r33381. Add subprojects 3r38282.
 

Team 3r32020. add_subdirectory prompts CMake to immediately process the specified subproject file. The example below demonstrates the application of the described mechanism:


 
3r3658. 3r3659. # Add the "subLibrary" directory to the main project assembly,
# and place the generated files in the "subLibrary /build" directory:
add_subdirectory (subLibrary subLibrary /build) 3r3668.
 

In this example, the first argument of the command is add_subdirectory acts as subproject 3r3676. subLibrary , and the second argument is optional and informs CMake about the folder intended for the generated files of the included subproject (for example, CMakeCache.txt and cmake_install.cmake ). 3r3694.
 

It is worth noting that all variables from the parent scope are inherited by the added directory, and all variables defined and redefined in this directory will be visible only to it (if the keyword 3r3676. PARENT_SCOPE 3r3777. Was not determined by the argument of the command Set 3r3r???. Set. ). This feature mentioned 3r3687. in the comments to r3r3424. previous article 3r3687. . 3r3694.
 
3r33434. Search for packages 3r38282.
 

Team 3r33510. find_package finds and loads external project settings. In most cases, it is used for the subsequent linking of external libraries, such as 3r3438. Boost and 3r3442. GSL 3r3687. . This example invokes the described command to look for the 3r3442 library. GSL 3r3687. and subsequent linking:


 
3r3658. 3r3659. # Download the settings of the library package "GSL":
find_package (GSL 2.5 REQUIRED)
# Notify compiler about the "GSL" header directory:
include_directories ($ {GSL_INCLUDE_DIRS})
# Compile the executable file with the library "GSL":
target_link_libraries (MyExecutable GSL :: gsl)
3r3668.
 

In the example above, the command is 3r3-3510. find_package The first argument takes the package name, and then the required version. Option 3r3676. REQUIRED requires printing a fatal error and shutting down CMake if the required package is not found. The opposite is the option QUIET 3r37777. requiring CMake to continue its work, even if the package was not found. 3r3694.
 

Then the command is called. include_directories informing the compiler about the location of the GSL header files. Notice that the variable is used. GSL_INCLUDE_DIRS that stores the location of the headers I described (this is an example of the imported package settings). 3r3694.
 

Ultimately, the executable file is MyExecutable Linked to the GSL library with the command target_link_libraries using the variable GSL :: gsl encapsulating the location of the GSL itself. 3r3694.
 

You will probably want to check the result of the package search if you specified option 3r3r6767. QUIET 3r37777. . This can be done by checking the variable 3r33515. _FOUND automatically detected after completion of the command find_package . For example, if you successfully imported GSL settings into your project, variable GSL_FOUND will turn into the truth. 3r3694.
 

In general, the command is 3r3–3510. find_package It has two types of launch: modular and configuration. The example above applied a modular form. This means that during a call to CMake, it searches for a script file of the form Find 3r33515. .cmake in the directory CMAKE_MODULE_PATH , and then launches it and imports all the necessary settings (in this case, CMake launched the standard file 3r3676. FindGSL.cmake

). 3r3694.
 
3r33526. Installation of the project 3r38282.
 

Team 3r33531. install generates setup rules for your project. This command is able to work with goals, files, folders and much more. First, consider setting goals. 3r3694.
 

To set goals, you must pass the keyword as the first argument to the described function. TARGETS , followed by a list of targets to be set, and then the keyword DESTINATION with the location of the directory in which the specified goals. This example demonstrates a typical goal setting: 3r3694.
 
3r3658. 3r3659. # Set the "TimePrinter" and "DataScanner" targets to the "bin" directory:
install (TARGETS TimePrinter DataScanner DESTINATION bin) 3r3668.
 

The process of describing the installation of files is similar, except that instead of the keyword TARGETS should indicate r3r3676. FILES . An example demonstrating the installation of files:


 
3r3658. 3r3659. # Install the "DataCache.txt" and "MessageLog.txt" files in the "~ /" directory:
install (FILES DataCache.txt MessageLog.txt DESTINATION ~ /) 3r36777. 3r3668.
 

The process of describing the installation of folders is also similar, with the exception that instead of the keyword FILES should indicate r3r3676. DIRECTORY . It is important to note that the installation will copy the entire contents of the folder, and not just its name. An example of installing folders is as follows:


 
3r3658. 3r3659. # Set the "MessageCollection" and "CoreFiles" directories to the "~ /" directory:
install (DIRECTORY MessageCollection CoreFiles DESTINATION ~ /) 3r3668.
 

After the completion of CMake processing of all your files, you can install all the described objects with the command sudo make install (if CMake generates Makefile ), or execute this action with an integrated development environment that supports CMake. 3r3694.
 
3r3-3591. A good example of a project is 3-333682.
 

This manual would be incomplete without showing a real example of using the CMake build system. Consider a simple project diagram using CMake as the only build system:


 
3r3658. 3r3600. + MyProject
- CMakeLists.txt
- Defines.h
- StartProgram.c
+ core
- CMakeLists.txt
- Core.h
- ProcessInvoker.c
- SystemManager.c 3r3668.
 

The main assembly file 3r3676. CMakeLists.txt describes the compilation of the entire program: the command 3r3361616 is called first. add_executable compiling the executable file, then the command 3r33620 is called. add_subdirectory , prompting the processing of the subproject, and finally, the executable file is linked to the compiled library:


 
3r3658. 3r3659. # Set the minimum version of CMake:
cmake_minimum_required (VERSION 3.0)
# Indicate project characteristics:
project (MyProgram VERSION ??? LANGUAGES C)
# Add to the assembly executable file "MyProgram":
add_executable (MyProgram StartProgram.c)
# Require handling of the core /CMakeFiles.txt file:
add_subdirectory (core)
# Compile the executable file "MyProgram" with
# compiled static library "MyProgramCore":
target_link_libraries (MyProgram MyProgramCore)
# Install the executable file "MyProgram" in the directory "bin":
install (TARGETS MyProgram DESTINATION bin) 3r3668.
 

File 3r3676. core /CMakeLists.txt called by the main build file and compiles the static library. MyProgramCore for linking with executable file:


 
3r3658. 3r3659. # Set the minimum version of CMake:
cmake_minimum_required (VERSION 3.0)
# Indicate project characteristics:
project (MyProgramCore VERSION ??? LANGUAGES C)
# Add static library "MyProgramCore" to the assembly:
add_library (MyProgramCore STATIC ProcessInvoker.c SystemManager.c) 3r3668.
 

After a series of teams cmake. && make && sudo make install The CMake build system completes successfully. The first command prompts file processing CMakeLists.txt in the root of the project, the second command finally compiles the necessary binaries, and the third command installs the compiled executable file MyProgram into the system. 3r3694.
 
Conclusion 3r38282.
 
Now you are able to write your own and understand other people's CMake files, and you can read about other mechanisms in detail on 3r3686. official website 3r3687. . 3r3694.
 
The next article in this guide will be devoted to testing and packaging using CMake and will be released in a week. See you soon!
 
3r3694.
3r3699. ! function (e) {function t (t, n) {if (! (n in e)) {for (var r, a = e.document, i = a.scripts, o = i.length; o-- ;) if (-1! == i[o].src.indexOf (t)) {r = i[o]; break} if (! r) {r = a.createElement ("script"), r.type = "text /jаvascript", r.async =! ? r.defer =! ? r.src = t, r.charset = "UTF-8"; var d = function () {var e = a.getElementsByTagName ("script")[0]; e. ): d ()}}} t ("//mediator.mail.ru/script/2820404/"""_mediator") () (); 3r33700.

+ 0 -

Add comment