cmake could not find openssl_使用CMake构建C++项目

背景

现代CMake如今开始转向使用targets和properties,比如下面文章介绍的这样:

https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/​pabloariasal.github.io

然而仍然有很多C++项目基于传统CMake构建,阅读本文有助于理解传统CMake的使用。文中引用了libdeepvac项目的CMakeLists.txt来作为参考:

https://github.com/DeepVAC/libdeepvac​github.com

有现代CMake实践经验的同学也可以参与该项目,将上述CMakeLists.txt重构为基于targets和properties。

CMake语句

set

设置变量。你甚至可以直接把多个值直接set给一个变量:

set(SYSZUX_HEADERS
    include/detail/class.h
    include/detail/common.h
    include/detail/descr.h
    include/detail/init.h
    include/internals.h
    includedetail/typeid.h)

file

使用正则匹配文件,并将文件路径赋值给第一个参数(为变量),通常和GLOB搭配:

file(GLOB gemfield_src_list ${Root}/*/*.cpp ${Root}/*/*.h ${Root}/*/*.c)

list

针对list进行各种操作,如增删改查,比如:

list(REMOVE_ITEM ......)
list(APPEND ......)

project

设置项目的名字。

project(SYSZUXrtp)

#还可以设置更多的参数
project(
    libdeepvac
    LANGUAGES CXX
    VERSION "1.0.0")

add_library

#语法
add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            source1 [source2 ...])

#举例
add_library(gemfield_static STATIC ${gemfield_src_list})

Adds a library target called<name>to be built from the source files listed in the command invocation. The<name>corresponds to the logical target name and must be globally unique within a project.

aux_source_directory

#语法
aux_source_directory(<dir> <variable>)

Collects the names of all the source files in the specified directory and stores the list in the <variable> provided.

aux_source_directory(${gemfield_root}/include gemfield_src)

比如上面的例子就是,将${gemfield_root}/include目录下的所有源文件找到并且赋值给gemfield_src变量。

add_definitions

Adds -D define flags to the compilation of source files.比如:

add_definitions(-DENABLE_GEMFIELD)

add_executable

Add an executable to the project using the specified source files.

#语法:
add_executable(<name> [WIN32] [MACOSX_BUNDLE]
               [EXCLUDE_FROM_ALL]
               source1 [source2 ...])

Adds an executable target called<name>to be built from the source files listed in the command invocation. The<name>corresponds to the logical target name and must be globally unique within a project. The actual file name of the executable built is constructed based on conventions of the native platform (such as<name>.exeor just<name>.举例:

add_executable(gemfield_proxy ${gemfield_src_list})

target_link_libraries

Link a target to given libraries.

#语法
target_link_libraries(<target> [item1 [item2 [...]]]
                      [[debug|optimized|general] <item>] ...)

Specify libraries or flags to use when linking a given target. The named <target> must have been created in the current directory by a command such as add_executable() or add_library(). The remaining arguments specify library names or flags. Repeated calls for the same <target> append items in the order called.

If a library name matches that of another target in the project a dependency will automatically be added in the build system to make sure the library being linked is up-to-date before the target links. Item names starting with -, but not -l or -framework, are treated as linker flags.

比如:

target_link_libraries(
        gemfield_proxy
        shared_static
        json_static
        mpeg_static
        ${LINK_LIB_LIST})

意思是说,要链接出目标gemfield_proxy的时候,需要有后面的库(shared_static、json_static...)或者flag。

link_directories

指定要搜寻的库所在的目录,相当于link工具的 -L参数。

#语法
link_directories(directory1 directory2 ...)

注意,这个变量很少必须使用,最好用find_library()来替代。

find_library

寻找一个库,将找到的库的绝对路径赋值给变量。

#简单语法
find_library(<VAR> lib_name1 [path1 path2 ...])
#相当于
find_library(<VAR> lib_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]
            )

举例:

find_library(LIBGEMFIELD_PATH libgemfield.so PATHS ${CUDA_TOOLKIT_ROOT_DIR}/lib64/)

include_directories

将目录中加入搜索头文件时的路径,不支持通配符:

include_directories(${CMAKE_SOURCE_DIR}/gemfield/include)

include

CMake中的流程控制

if else

if else等条件控制,使用如下的语句:

#if
if(逻辑表达式)
...
endif()

#if else
if(逻辑表达式)
...
else()
...
endif()

#if elseif
if(逻辑表达式)
...
elseif(逻辑表达式)
...
endif()

if中的逻辑与为AND关键字,非为NOT关键字。

for循环

for循环使用如下语句:

foreach(变量 变量的列表)
...
endforeach()

CMake中的系统变量

  1. MAKE_MAJOR_VERSION : major version number for CMake, e.g. the "2" in CMake 2.4.3
  2. CMAKE_MINOR_VERSION : minor version number for CMake, e.g. the "4" in CMake 2.4.3
  3. CMAKE_PATCH_VERSION : patch version number for CMake, e.g. the "3" in CMake 2.4.3
  4. CMAKE_TWEAK_VERSION : tweak version number for CMake, e.g. the "1" in CMake X.X.X.1. Releases use tweak < 20000000 and development versions use the date format CCYYMMDD for the tweak level.
  5. CMAKE_VERSION : The version number combined, eg. 2.8.4.20110222-ged5ba for a Nightly build. or 2.8.4 for a Release build.
  6. CMAKE_GENERATOR : the generator specified on the commandline.
  7. BORLAND : is TRUE on Windows when using a Borland compiler
  8. WATCOM : is TRUE on Windows when using the Open Watcom compiler
  9. MSVC, MSVC_IDE, MSVC60, MSVC70, MSVC71, MSVC80, CMAKE_COMPILER_2005, MSVC90, MSVC10 (Visual Studio 2010) : Microsoft compiler
  10. CMAKE_C_COMPILER_ID : one of "Clang", "GNU", "Intel", or "MSVC". This works even if a compiler wrapper like ccache is used.
  11. CMAKE_CXX_COMPILER_ID : one of "Clang", "GNU", "Intel", or "MSVC". This works even if a compiler wrapper like ccache is used;
  12. cmake_minimum_required:设置所需CMake的最小版本;

CMake中编译相关的变量

  • CMAKE_CXX_STANDARD:设置C++标准;
  • CMAKE_CXX_FLAGS:设置C++编译参数;
  • CMAKE_C_FLAGS:设置C编译参数;
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -w")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
  • BUILD_SHARED_LIBS : if this is set to ON, then all libraries are built as shared libraries by default. SET(BUILD_SHARED_LIBS ON)
  • CMAKE_BUILD_TYPE : A variable which controls the type of build when using a single-configuration generator like the Makefile generator. It is case-insensitive;If you are using the Makefile generator, you can create your own build type like this:
SET(CMAKE_BUILD_TYPE distribution)
SET(CMAKE_CXX_FLAGS_DISTRIBUTION "-O3")
SET(CMAKE_C_FLAGS_DISTRIBUTION "-O3")

Note that CMAKE_BUILD_TYPE is not initialized with a readable value at configuration time. This is because the user is free to select a build type at build time. Use CMAKE_CFG_INTDIR if you need a variable that evaluates to the correct build time directory;

  • CMAKE_CONFIGURATION_TYPES : When using a multi-configuration generator, such as the one for Visual Studio, this variable contains a list of the available configurations.
  • CMAKE_C_COMPILER : the compiler used for C files. Normally it is detected and set during the CMake run, but you can override it at configuration time. Note! It can not be changed after the first cmake or ccmake run. Although the gui allows to enter an alternative, it will be ignored in the next 'configure' run. Use for example: CC=gcc-3.3 CXX=g++-3.3 cmake to set the compiler. (You can also set CMAKE_C_COMPILER_INIT, before any PROJECT() or ENABLE_LANGUAGE() command.) Any other way (like writing make CC=gcc-3.3 CXX=g++-3.3) will not work. When using distcc or similar tools, you need to write: CC="distcc gcc-3.3" CXX="distcc g++-3.3" cmake However, this will empty all your CMAKE_...FLAGS... above.
  • CMAKE_C_FLAGS : the compiler flags for compiling C sources. Note you can also specify switches with ADD_COMPILE_OPTIONS().
  • CMAKE_C_FLAGS_ : compiler flags for a specific build configuration. Replace "" in the name with a specific build configuration name.
  • CMAKE_C_OUTPUT_EXTENSION : what C object files end in. Typically .o or .obj.
  • CMAKE_CFG_INTDIR : meta-variable! Please note that this is an important variable, since on multi-configuration generators it will be generated into dynamically switched content based on the configuration that the user currently selected within the generated build environment. Indicates the name of the current configuration (~ directory) for the project. May be used for any purpose which needs per-configuration-dynamic switching of strings, not just OutputDir configuration. For multi-configuration generators (e.g. MSVC) the resulting strings are typically some of "Debug", "Release", "RelWithDebInfo", or "MinSizeRel". For other compiler generators (single-configuration ones) it is typically ".", as they don't use MSVC-style configuration directories.
  • CMAKE_CXX_COMPILER : the compiler used for C++ files. Normally it is detected and set during the CMake run, but you can override it at configuration time. Note! It can not be changed after the first cmake or ccmake run. See CMAKE_C_COMPILER above.
  • CMAKE_CXX_FLAGS : the compiler flags for compiling C++ sources. Note you can also specify switches with ADD_COMPILE_OPTIONS().
  • CMAKE_CXX_FLAGS_ : compiler flags for a specific configuration for C++ sources. Replace "" in the name with a specific build configuration name.
  • CMAKE_SHARED_LINKER_FLAGS : additional compiler flags for building shared libraries, e.g.:set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined") On Unix systems, this will make linker report any unresolved symbols from object files (which is quite typical when you compile many targets in CMake projects, but do not bother with linking target dependencies in proper order). On mac, the flag is -Wl,-undefined-error
  • CMAKE_SKIP_RULE_DEPENDENCY : set this to true if you don't want to rebuild the object files if the rules have changed, but not the actual source files or headers (e.g. if you changed the some compiler switches)
  • CMAKE_SKIP_INSTALL_ALL_DEPENDENCY : since CMake 2.1 the install rule depends on all, i.e. everything will be built before installing. If you don't like this, set this one to true.
  • CMAKE_INCLUDE_CURRENT_DIR : automatically add CMAKE_CURRENT_SOURCE_DIR and CMAKE_CURRENT_BINARY_DIR to the include directories in every processed CMakeLists.txt. It behaves as if you had used INCLUDE_DIRECTORIES in every CMakeLists.txt file or your project. The added directory paths are relative to the being-processed CMakeLists.txt, which is different in each directory. (See this thread for more details).
  • CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE : order the include directories so that directories which are in the source or build tree always come before directories outside the project.
  • CMAKE_VERBOSE_MAKEFILE : set this to true if you are using makefiles and want to see the full compile and link commands instead of only the shortened ones
  • CMAKE_SUPPRESS_REGENERATION : this will cause CMake to not put in the rules that re-run CMake. This might be useful if you want to use the generated build files on another machine.
  • CMAKE_COLOR_MAKEFILE : create Makefiles with colored output (defaults to on)
  • CMAKE_SKIP_PREPROCESSED_SOURCE_RULES : (since 2.4.4) if set to TRUE, the generated Makefiles will not contain rules for creating preprocessed files (foo.i)
  • CMAKE_SKIP_ASSEMBLY_SOURCE_RULES : (since 2.4.4) if set to TRUE, the generated Makefiles will not contain rules for creating compiled, but not yet assembled files (foo.s);
  • INCLUDE_DIRECTORIES:Add the given directories to those the compiler uses to search for include files. Relative paths are interpreted as relative to the current source directory;

CMake中路径相关的变量

CMake有两类变量,PROJECT_<var> 和 CMAKE_<var>,CMAKE_*系列变量指的是最顶层的CMakeLists.txt所在的目录或者所描述的东西;而PROJECT_*系列变量指的是最近的含有project()命令的CMakeLists.txt所在的目录或者所描述的东西。

  1. CMAKE_BINARY_DIR : if you are building in-source, this is the same as CMAKE_SOURCE_DIR, otherwise this is the top level directory of your build tree
  2. CMAKE_COMMAND : this is the complete path of the cmake which runs currently (e.g. /usr/local/bin/cmake). Note that if you have custom commands that invoke cmake -E, it is very important to use CMAKE_COMMAND as the CMake executable, because CMake might not be on the system PATH.
  3. CMAKE_CURRENT_BINARY_DIR : if you are building in-source, this is the same as CMAKE_CURRENT_SOURCE_DIR, otherwise this is the directory where the compiled or generated files from the current CMakeLists.txt will go to.
  4. CMAKE_CURRENT_SOURCE_DIR : this is the directory where the currently processed CMakeLists.txt is located in
  5. CMAKE_CURRENT_LIST_FILE : this is the full path to the listfile currently being processed.
  6. CMAKE_CURRENT_LIST_DIR : (since 2.8.3) this is the directory of the listfile currently being processed.
  7. CMAKE_CURRENT_LIST_LINE : this is linenumber where the variable is used.
  8. CMAKE_FILES_DIRECTORY : the directory within the current binary directory that contains all the CMake generated files. Typically evaluates to "/CMakeFiles". Note the leading slash for the directory. Typically used with the current binary directory, i.e. ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}
  9. CMAKE_MODULE_PATH : tell CMake to search first in directories listed in CMAKE_MODULE_PATH when you use FIND_PACKAGE() or INCLUDE() SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/MyCMakeScripts) FIND_PACKAGE(HelloWorld) ;directories specifying a search path for CMake modules to be loaded by the the include()or find_package()commands before checking the default modules that come with CMake. By default it is empty, it is intended to be set by the project;注意是被include和find_package命令所使用的搜索路径,为list类型(目录列表)。
  10. CMAKE_ROOT : this is the CMake installation directory
  11. CMAKE_SOURCE_DIR : this is the directory which contains the top-level CMakeLists.txt, i.e. the top level source directory
  12. PROJECT_NAME : the name of the project set by PROJECT() command.
  13. CMAKE_PROJECT_NAME : the name of the first project set by the PROJECT() command, i.e. the top level project.
  14. PROJECT_BINARY_DIR : contains the full path to the top level directory of your build tree;可以近似认为:执行编译时所在的目录,在哪个目录下编译就是哪个目录。
  15. PROJECT_SOURCE_DIR : contains the full path to the root of your project source directory, i.e. to the nearest directory where CMakeLists.txt contains the PROJECT() command;
  16. LIBRARY_OUTPUT_PATH:旧的用法,指定library的路径;现在已经被ARCHIVE_OUTPUT_DIRECTORY、LIBRARY_OUTPUT_DIRECTORY和RUNTIME_OUTPUT_DIRECTORY代替了;
  17. EXECUTABLE_OUTPUT_PATH:旧的用法,指定可执行文件的路径;现在已经被RUNTIME_OUTPUT_DIRECTORY代替了;

CMake中的环境变量

有一些环境变量影响CMake的行为;另外,你也可以在CMake脚本中主动读取环境变量的值。实际上,你可以在CMake命令执行后,在CMakeCache.txt中看到打印的各种CMake变量的值。

  1. CMAKE_INCLUDE_PATH : This is used when searching for include files e.g. using the FIND_PATH() command. If you have headers in non-standard locations, it may be useful to set this variable to this directory (e.g. /sw/include on Mac OS X). If you need several directories, separate them by the platform specific separators (e.g. ":" on UNIX);
  2. CMAKE_LIBRARY_PATH : This is used when searching for libraries e.g. using the FIND_LIBRARY() command. If you have libraries in non-standard locations, it may be useful to set this variable to this directory (e.g. /sw/lib on Mac OS X). If you need several directories, separate them by the platform specific separators (e.g. ":" on UNIX);
  3. CMAKE_PREFIX_PATH : (since CMake 2.6.0) This is used when searching for include files, binaries, or libraries using either the FIND_PACKAGE(), FIND_PATH(), FIND_PROGRAM(), or FIND_LIBRARY() commands. For each path in the CMAKE_PREFIX_PATH list, CMake will check "PATH/include" and "PATH" when FIND_PATH() is called, "PATH/bin" and "PATH" when FIND_PROGRAM() is called, and "PATH/lib" and "PATH" when FIND_LIBRARY() is called. See the documentation for FIND_PACKAGE(), FIND_LIBRARY(), FIND_PATH(), and FIND_PROGRAM() for more details;
  4. CMAKE_INSTALL_ALWAYS : If set during installation CMake will install all files whether they have changed or not. The default when this is not set is to install only files that have changed since the previous installation. In both cases all files are reported to indicate CMake knows they are up to date in the installed location;
  5. $ENV{name} : This is not an environment variable , but this is how you can access environment variables from cmake files. It returns the content of the environment variable with the given name (e.g. $ENV{PROGRAMFILES});
  6. DESTDIR : If this environment variable is set it will be prefixed to CMAKE_INSTALL_PREFIX in places where it is used to access files during installation. This allows the files to be installed in an intermediate directory tree without changing the final installation path name. Since the value of CMAKE_INSTALL_PREFIX may be included in installed files it is important to use DESTDIR rather than changing CMAKE_INSTALL_PREFIX when it is necessary to install to a intermediate staging directory;

CMake中变量的打印

可以用MESSAGE语句打印CMake变量:

# if you are building in-source, this is the same as CMAKE_SOURCE_DIR, otherwise
# this is the top level directory of your build tree
MESSAGE( STATUS "CMAKE_BINARY_DIR:         " ${CMAKE_BINARY_DIR} )

# if you are building in-source, this is the same as CMAKE_CURRENT_SOURCE_DIR, otherwise this
# is the directory where the compiled or generated files from the current CMakeLists.txt will go to
MESSAGE( STATUS "CMAKE_CURRENT_BINARY_DIR: " ${CMAKE_CURRENT_BINARY_DIR} )

# this is the directory, from which cmake was started, i.e. the top level source directory
MESSAGE( STATUS "CMAKE_SOURCE_DIR:         " ${CMAKE_SOURCE_DIR} )

# this is the directory where the currently processed CMakeLists.txt is located in
MESSAGE( STATUS "CMAKE_CURRENT_SOURCE_DIR: " ${CMAKE_CURRENT_SOURCE_DIR} )

# contains the full path to the top level directory of your build tree
MESSAGE( STATUS "PROJECT_BINARY_DIR: " ${PROJECT_BINARY_DIR} )

# contains the full path to the root of your project source directory,
# i.e. to the nearest directory where CMakeLists.txt contains the PROJECT() command
MESSAGE( STATUS "PROJECT_SOURCE_DIR: " ${PROJECT_SOURCE_DIR} )

......

CMake的编译过程中详细log的查看

我们知道,对于GNU Make来说,要想看编译的详细日志(也就是具体的源文件路径、编译参数、输入路径等),可以使用make命令的VERBOSE参数:

make VERBOSE=1

而因为CMake封装了make,那么如何通过CMake达到同样的效果呢?

选项1:自然而然的,还是上面的方法

cmake .
make VERBOSE=1

选项2:在cmake命令行上加参数-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON

cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON .
make

#如果想要减少一些信息量少的打印信息:
cmake -DCMAKE_RULE_MESSAGES:BOOL=OFF -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON .
make --no-print-directory

选项3:修改CMakeLists.txt

在CMakeLists.txt中加上:

set(CMAKE_VERBOSE_MAKEFILE ON)

缺点是要修改文件,还要修改每个CMakeLists.txt文件。

CMake使用subdirectory

参考下面项目的CMakeLists.txt,其重度使用了add_subdirectory:

https://github.com/DeepVAC/libdeepvac/blob/master/CMakeLists.txt​github.com

CMake的Installation

使用install语句。一个生动的例子可以参考:

https://github.com/DeepVAC/libdeepvac/blob/master/CMakeLists.txt​github.com

集成一个CMake项目到另外的CMake项目

为了让别的C++项目在CMakeLists.txt中使用find_package来引用自己的C++项目,则需要在自己项目的CMakeLists.txt中使用EXPORT语法和install(EXPORT ...)语法。一个生动的例子可以参考:

https://github.com/DeepVAC/libdeepvac/blob/master/CMakeLists.txt​github.com

和:

DeepVAC/libdeepvac​github.com
1c390c63ddb86c4595ed48b9a2283cfb.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值