Initial users of CMake or those who don't know much about it may often be stumbled by such issues as path inclusion, library search paths, link paths, RPath, which are easy tasks when performing gcc manually or writing makefile s.
In fact, I had a lot of doubts, but after a long time of practice and reading manual, I finally got a relatively clear understanding.
- How to use manual
cmake's help organization is still very regular, understand its rules, find what you want will be very simple, so personal feel this may be the most important. Its help system is probably of several types:
- command
This is the longest used in the practical process, equivalent to the basic grammar in the general foot language, including defining variables, foreach, string, if, builtin command are all here.
You can use these commands to get help:
cmake --help-commands
This command will give detailed help to all the built-in commands of cmake, which can be used when you don't know what you're looking for or want to flip randomly.
My usual and more common approach is to redirect it to less and search for keywords in the editor.
In addition, the search scope can be reduced layer by layer by layer by using the following methods:
cmake --help-command-list
cmake --help-command-list | grep find
skyscribe@skyscribe:~/program/ltesim/bld$ cmake --help-command-list | grep find
find_file
find_library
find_package
find_path
find_program
cmake --help-command find_library
cmake version 2.6-patch 4
------------------------------------------------------------------------------
SingleItemfind_library
Find a library.find_library(<VAR> name1 [path1 path2 ...])
This is the short-hand signature for the command that is sufficient in
many cases. It is the same as find_library(<VAR> name1 [PATHS path1
path2 ...])find_library(
<VAR>
name | NAMES name1 [name2 ...]
[HINTS path1 [path2 ... ENV var]]
[PATHS path1 [path2 ... ENV var]]
[PATH_SUFFIXES suffix1 [suffix2 ...]]
[DOC "cache documentation string"]
[NO_DEFAULT_PATH]
[NO_CMAKE_ENVIRONMENT_PATH]
[NO_CMAKE_PATH]
[NO_SYSTEM_ENVIRONMENT_PATH]
[NO_CMAKE_SYSTEM_PATH]
[CMAKE_FIND_ROOT_PATH_BOTH |
ONLY_CMAKE_FIND_ROOT_PATH |
NO_CMAKE_FIND_ROOT_PATH]
)
- variable
and command The help is similar, but you can find it here. cmake You define the variables that you can use directly, for example OSName,Is it? Windows,Unix And so on.
One of my most common examples is:
cmake --help-variable-list | grep CMAKE | grep HOST
CMAKE_HOST_APPLE
CMAKE_HOST_SYSTEM
CMAKE_HOST_SYSTEM_NAME
CMAKE_HOST_SYSTEM_PROCESSOR
CMAKE_HOST_SYSTEM_VERSION
CMAKE_HOST_UNIX
CMAKE_HOST_WIN32
Find all of them here. CMake Self-defined builtin Variables; generally related to the system platform.
If you want to place all generated executable files and libraries in the same directory, you can do this:
The target_dir here is an absolute path set for implementation. (There are fewer problems with absolute paths in CMake than with relative paths, if possible with absolute paths)
# Targets directory
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${target_dir}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${target_dir}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${target_dir}/bin)
- property
Property Very few direct changes are required unless you want to modify some default behavior, such as modifying the generated dynamic library files. soname And so on.
For example, if you need to generate both dynamic and static libraries in the same directory, by default, cmake According to what you provided target Names automatically generate similar libtarget.so, libtarget.a,But the same project There can only be one at the same time, because target Must be unique.
At this point, you can modify it. taget The corresponding file name can generate both dynamic and static libraries.
For example:
cmake --help-property-list | grep NAME
GENERATOR_FILE_NAME
IMPORTED_SONAME
IMPORTED_SONAME_<CONFIG>
INSTALL_NAME_DIR
OUTPUT_NAME
VS_SCC_PROJECTNAME
skyscribe@skyscribe:~$ cmake --help-property OUTPUT_NAME
cmake version 2.6-patch 4
------------------------------------------------------------------------------
SingleItem
OUTPUT_NAME
Sets the real name of a target when it is built.
Sets the real name of a target when it is built and can be used to
help create two targets of the same name even though CMake requires
unique logical target names. There is also a <CONFIG>_OUTPUT_NAME
that can set the output name on a per-configuration basis.
- module
Used to find commonly used modules, such as boost,bzip2, python And so on. By simple include Commands contain predefined modules, so you can get some variables defined after the module is executed, which is very convenient.
For example, commonly used boost The library can be used in the following ways:
# Find boost 1.40
INCLUDE(FindBoost)
find_package(Boost 1.40.0 COMPONENTS thread unit_test_framework)
if(NOT Boost_FOUND)
message(STATUS "BOOST not found, test will not succeed!")
endif()
Generally, the first part of the explanation is quite useful, which can satisfy 80.%Demand:
cmake --help-module FindBoost | head -40
cmake version 2.6-patch 4
------------------------------------------------------------------------------
SingleItem
FindBoost
Try to find Boost include dirs and libraries
Usage of this module as follows:
== Using Header-Only libraries from within Boost: ==
find_package( Boost 1.36.0 )
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(foo foo.cc)
endif()
== Using actual libraries from within Boost: ==
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
find_package( Boost 1.36.0 COMPONENTS date_time filesystem system ... )
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(foo foo.cc)
target_link_libraries(foo ${Boost_LIBRARIES})
endif()
The components list needs to contain actual names of boost libraries
- How to view some key information based on the intermediate files it generates
One advantage of CMake over Autotools is that the generated intermediate files are organized in a very orderly and clear way, unlike autotools, which can generate huge objects like Tianshu (10,000 + is not uncommon).
Generally, the Makefile corresponding to CMake has hierarchical structure, and the corresponding directory structure will be generated in the binary directory according to the relative structure between your CMake Lists. txt.
For example, for a target, a folder can be found under a binary tree: CMakeFiles/<targentName>.dir/, for example:
skyscribe@skyscribe:~/program/ltesim/bld/dev/simcluster/CMakeFiles/SIMCLUSTER.dir$ ls -l
total 84
-rw-r--r-- 1 skyscribe skyscribe 52533 2009-12-12 12:20 build.make
-rw-r--r-- 1 skyscribe skyscribe 1190 2009-12-12 12:20 cmake_clean.cmake
-rw-r--r-- 1 skyscribe skyscribe 4519 2009-12-12 12:20 DependInfo.cmake
-rw-r--r-- 1 skyscribe skyscribe 94 2009-12-12 12:20 depend.make
-rw-r--r-- 1 skyscribe skyscribe 573 2009-12-12 12:20 flags.make
-rw-r--r-- 1 skyscribe skyscribe 1310 2009-12-12 12:20 link.txt
-rw-r--r-- 1 skyscribe skyscribe 406 2009-12-12 12:20 progress.make
drwxr-xr-x 2 skyscribe skyscribe 4096 2009-12-12 12:20 src
Here, each file is a very short text file, the content is quite clear. build.make generally contains dependency rules for intermediate generated files, and DependInfo.cmake generally contains dependency rules for source files themselves.
More importantly, flags.make and link.txt generally contain information similar to GCC - I, such as search path, macro definition, etc. The latter includes linkage information and library search path when target is finally generated.
This information is a good aid for debugging when problems arise.
-
File lookup, path correlation
- include
Commonly used are:
include_directories()Inclusive search paths for adding header files
cmake --help-command include_directories
cmake version 2.6-patch 4
------------------------------------------------------------------------------
SingleItem
include_directories
Add include directories to the build.
include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)
Add the given directories to those searched by the compiler for
include files. By default the directories are appended onto the
current list of directories. This default behavior can be changed by
setting CMAKE_include_directories_BEFORE to ON. By using BEFORE or
AFTER you can select between appending and prepending, independent
from the default. If the SYSTEM option is given the compiler will be
told that the directories are meant as system include directories on
some platforms.
link_directories()Search Path for Adding Find Library Files
cmake --help-command link_directories
cmake version 2.6-patch 4
------------------------------------------------------------------------------
SingleItem
link_directories
Specify directories in which the linker will look for libraries.
link_directories(directory1 directory2 ...)
Specify the paths in which the linker should search for libraries.
The command will apply only to targets created after it is called.
For historical reasons, relative paths given to this command are
passed to the linker unchanged (unlike many CMake commands which
interpret them relative to the current source directory).
- library search
Generally, there are two ways to link external libraries. One is to display the adding path, using link_directories(), and the other is to find the absolute path of the corresponding library through find_library().
The latter method is better because it can reduce many potential conflicts.
In general, find_library searches for files according to some default rules. If found, it will set the first variable parameter passed in. Otherwise, the corresponding parameter will not be defined, and an x xxx-NOTFOUND is defined. This way, you can debug whether the library search is successful.
For the names of Library files, libxxx.so (xxxx.dll) is automatically searched when searching for dynamic libraries, while libxxx.a (x xxx.lib) is used for static libraries. In the case of mixed use of dynamic libraries and static libraries, some confusion may arise, which requires extra care; in general, matching links should be made as far as possible.
- rpath
The so-called rpath is related to the loading and running of dynamic libraries. I usually replace the default rpath by the following way:
# RPATH and library search setting
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/nesim/lib")
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)