cmake:cmake_examples/01_basics


学习经典的教程 cmake_examples

A_hello_cmake

A-hello-cmake$ tree
.
├── CMakeLists.txt
├── main.cpp

CMakeLists.txt:

cmake_minimum_required(VERSION 2.6)
project (hello_cmake) //会创建PROJIECT_NAME
add_executable(${PROJECT_NAME} main.cpp) //习惯上把程序名和项目名字一样

概念

  1. binary directory
    运行cmake命令的文件夹是CMAKE_BINARY_DIR。支持In-place Build&out-of-source。

B_hello_headers

B-hello-headers$ tree
.
├── CMakeLists.txt
├── include
│   └── Hello.h
└── src
    ├── Hello.cpp
    └── main.cpp

概念

  1. directory path
    CMAKE_SOURCE_DIR,CMAKE_CURRENT_SOURCE_DIR,PROJECT_SOURCE_DIR,CMAKE_BINARY_DIR,CMAKE_CURRENT_BINARY_DIR,PROJECT_BINARY_DIR.具体什么意思见Google。
  2. source files variable
# Create a sources variable with a link to all cpp files to compile
set(SOURCES
    src/Hello.cpp
    src/main.cpp
)

#上面的等价为
#file(GLOB SOURCES "src/*.cpp")

add_executable(${PROJECT_NAME} ${SOURCES})

现代的c++不推荐使用变量来标识源文件,一般是在add_xxx函数中直接声明

  1. including directories
target_include_directories(target
    PRIVATE
        ${PROJECT_SOURCE_DIR}/include
)

相当于在编译这个target的时候加入的指令-I/directory/pathPRIVATE是的作用见下一节。

C_static_library

$ tree
.
├── CMakeLists.txt
├── include
│   └── static
│       └── Hello.h
└── src
    ├── Hello.cpp
    └── main.cpp

概念

  1. adding a static library
add_library(hello_library STATIC
    src/Hello.cpp
)

会产生一个libhello_library.a名字的静态库。

如现代cmake,直接写出源文件,不使用变量

  1. Populating Including Directories
target_include_directories(hello_library
    PUBLIC
        ${PROJECT_SOURCE_DIR}/include
)
  • PUBLIC:编译这个目标和链接这个库的时候都要使用included directory。
  • PRIVATE
  • INTERFACE

推荐直接使用头文件的根目录,在包含头文件写如下的就好#include "static/Hello.h"

  1. linking a library
add_executable(hello_binary
    src/main.cpp
)

target_link_libraries( hello_binary
    PRIVATE
        hello_library
)

上面等价于(会自动的包含链接库的PUBLICINTERFACE对应的头文件目录

/usr/bin/c++ CMakeFiles/hello_binary.dir/src/main.cpp.o -o hello_binary -rdynamic libhello_library.a

D_shared_library

$ tree
.
├── CMakeLists.txt
├── include
│   └── shared
│       └── Hello.h
└── src
    ├── Hello.cpp
    └── main.cpp

概念

  1. adding a shared library
add_library(hello_library SHARED
    src/Hello.cpp
)

产生libhello_library.so的动态库。

  1. alias target
add_library(hello::library ALIAS hello_library)
  1. Linking a Shared Library
add_executable(hello_binary
    src/main.cpp
)

target_link_libraries(hello_binary
    PRIVATE
        hello::library
)

等价于:

/usr/bin/c++ CMakeFiles/hello_binary.dir/src/main.cpp.o -o hello_binary -rdynamic libhello_library.so -Wl,-rpath,/home/matrim/workspace/cmake-examples/01-basic/D-shared-library/build

注意这里动态库和静态库的不同!

E_installing

$ tree
.
├── cmake-examples.conf
├── CMakeLists.txt
├── include
│   └── installing
│       └── Hello.h
├── README.adoc
└── src
    ├── Hello.cpp
    └── main.cpp

概念

  1. installing

cmake可以设置make install目标去安装二进制文件,库和其他文件。CAMKE_INSTALL_PREFIX可以通过ccmake或cmake .. -DCMAKE_INSTALL_PREFIX=/install/location设置。

# 二进制
install (TARGETS cmake_examples_inst_bin
    DESTINATION bin)
# 动态库
install (TARGETS cmake_examples_inst
    LIBRARY DESTINATION lib)
# 上面不能再window下工作

# 头文件
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
    DESTINATION include)
# 其他文件
install (FILES cmake-examples.conf
    DESTINATION etc)

make install运行后会产生install_manifest.txt文件。

特别注记

  1. Overriding the default install location

CMAKE_INSTALL_PREFIX默认为/usr/local/
要改变默认地址,在顶层CMakeLists.txt在加入任何二进制文件和库之前添加:

if( CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT )
  message(STATUS "Setting default CMAKE_INSTALL_PREFIX path to ${CMAKE_BINARY_DIR}/install")
  set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE STRING "The path to use for make install" FORCE)
endif()

这里修改到build/install

  1. DESTDIR
make install DESTDIR=/tmp/stage

install path会修改为${DESTDIR}/${CMAKE_INSTALL_PREFIX}

  1. unistall
sudo xargs rm < install_manifest.txt

F_build_type

$ tree
.
├── CMakeLists.txt
├── main.cpp

概念

  1. set build type

编译项目的时候的默认配置,有Release,Debug,MinSizeRel,RelWithDebInfo四种选项。
有两种方法

  • gui工具
  • cmake .. -DCMAKE_BUILD_TYPE=Release
  1. set default build type

在顶层的CMakeLists.txt中加入

if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  message("Setting build type to 'RelWithDebInfo' as none was specified.")
  set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
  # Set the possible values of build type for cmake-gui
  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
    "MinSizeRel" "RelWithDebInfo")
endif()

G_compile_flags

$ tree
.
├── CMakeLists.txt
├── main.cpp

set per-Target c++ Flags

target_compile_definitions(cmake_examples_compile_flags
    PRIVATE EX3
)

如果是library可以用PUBLIC/INTERFACE

  1. Set Default C++ Flags

设置默认的编译flags需要在顶层的CMakeLists.txt中加入:

set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DEX2" CACHE STRING "Set C++ Compiler Flags" FORCE)

CACHE STRING "Set C++ Compiler Flags" FORCE的意思是强制在CMakeCache.txt文件中设置这个变量。

如果是c编译flags:CMAKE_C_FLAGS
链接器flags:CMAKE_LINKER_FLAGS

如果设置了CMAKE_CXX_FLAGS等就全部默认是这个了,推荐还是使用 target_compile_definitions

  1. Set CMake Flags

像上面一样有两种办法

  • gui
  • cmake … -DCMAKE_CXX_FLAGS=“-DEX3”

H_third_party_library

$ tree
.
├── CMakeLists.txt
├── main.cpp

概念

  1. finding a package
find_package(Boost 1.46.1 REQUIRED COMPONENTS filesystem system)

find_package会寻找CMAKE_MODULE_PATH(Linux默认是/usr/share/cmake/Modules)中的FindXXX.cmake

  1. Checking if the package is found

被包含的package会设置变量XXX_FOUND

if(Boost_FOUND)
    message ("boost found")
    include_directories(${Boost_INCLUDE_DIRS})
else()
    message (FATAL_ERROR "Cannot find Boost")
endif()
  1. Exported Variables

一个package被找到会export一些变量去告诉用户如何找到库,头文件,可执行文件。就像XXX_FOUND一样,会被记录在FindXXX.cmake的顶部。

  • Boost_INCLUDE_DIRS -boost的头文件路径 .
  1. Alias / Imported targets
  target_link_libraries( third_party_include
      PRIVATE
          Boost::filesystem
  )

上面的Boost::filesystem 会自动添加 Boost::boostBoost::system 依赖。

  1. Non-alias targets

如果没有上面的imported target,那么怎么办呢?

  • xxx_INCLUDE_DIRS:include目录的路径
  • xxx_LIBRARY:库的路径

如下使用:

# Include the boost headers
target_include_directories( third_party_include
    PRIVATE ${Boost_INCLUDE_DIRS}
)

# link against the boost libraries
target_link_libraries( third_party_include
    PRIVATE
    ${Boost_SYSTEM_LIBRARY}
    ${Boost_FILESYSTEM_LIBRARY}
)

I_compling_with_clang

$ tree
.
├── CMakeLists.txt
├── main.cpp

概念

  1. Compiler Option

Cmake提供了一些选项:

  • CMAKE_C_COMPILER
  • CMAKE_CXX_COMPILER
  • CMAKE_LINKER
  1. Setting Flags

你可以通过命令行和gui来设置。

下面是通过命令行:cmake .. -DCMAKE_C_COMPILER=clang-3.6 -DCMAKE_CXX_COMPILER=clang++-3.6

J_building_with_ninja

$ tree
.
├── CMakeLists.txt
├── main.cpp

概念

  1. generators

cmake包含了不同的generator,如Command-Line,IDE and Extra generators.

Command-Line Build Tool Generators:

  • Ninja
  • MMake Makefiles
  • Unix Makefiles
  • and so on…

IDE Build Tool Generators:

  • vs
  • Xcode

Extra Generators:

  • CodeBlocks
  • Sunlime Text 2
  1. Calling a Generator
$ cmake .. -G Ninja

$ ninja -v

$ ls
build.ninja  CMakeCache.txt  CMakeFiles  cmake_install.cmake  rules.ninja

K_import_targets

详细见H-third-party-library

L_cpp_standard

概念

有三种方式就不一一说明,下面是最普通的方法。

  1. Checking Compile flags
# 包含对应的函数
include(CheckCXXCompilerFlag)

# 检测是否支持,并把结果保存
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
  1. Adding the flag
if(COMPILER_SUPPORTS_CXX11)#
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)#
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
    message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值