CMake笔记

Cmake学习笔记

最基础的CMAKE文件

设定camke所需要的最低版本:

cmake_minimum_required(VERSION 3.5)

设置项目名字:

project ([$NAME]) 

添加带main函数的文件

add_executable([PROJECT_NAME] [FILE_NAME])

开始编译!

如果在Linux上运行,指令如下

cd [PROJECT_FOLDER]
mkdir build
cd build
cmake ..
###########
This will tell cmake to find CMakeFiles in the parent folder
###########
make

如果在windows上运行,需要安装minGW,然后进入MinGW下的bin文件夹, 把 mingw32-make.exe复制一份并且改名为make.exe,在PATH中设置环境变量为minGW的bin文件夹。然后还需要对上面的指令改成

cmake -G “MinGW Makefiles” ..

在windows上默认情况下,cmake会构建为Visual Studio的项目,可以打开.sin文件,然后运行项目,如果报错了,记得检查下有没有设置项目为活动项目。

另一个坑 :如果看到了报错

undefined reference to main //“WinMain” in win32

有几种情况:
- [ ] 没有main函数 - [ ] main写成了mian - [ ] main函数少了参数 main(int argc,char *argv[]).   如果按照上面说的建立一个最简单的helloworld小程序,那么应该会有如下输出

-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to:

添加头文件和库依赖

添加头文件

  举个详细的例子
  文件结构如下

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

CMakeLists如下

cmake_minimum_required(VERSION 3.8)

project(Hello)

file(GLOB SRC "src/**.cpp")

add_executable(Hello ${SRC})

target_include_directories(Hello
PRIVATE
${PROJECT_SOURCE_DIR}/include}
)

  在target_include_directories()函数中有三个参数,第一个是目标项目名;第二个是权限属性,简单的说就是依赖的传递性,一般和库的引用有关,后面会提到;第三个参数是include目标的文件夹,其中的${PROJECT_SOURCE_DIR}是cmake内置的变量,其他的内置变量可以看cmake的官方文档

添加库依赖

  在更加复杂的情况下还可能会需要编译、链接库,于是上面的代码又得改改


cmake_minimum_required(VERSION 3.8)

project(Hello)

add_library(hello_lib
	SHARED
	src/Hello.cpp
)
target_include_directories(hello_lib
	PRIVATE
	${PROJECT_SOURCE_DIR}/include
)
####################################
add_executable(Hello src/main.cpp)

target_link_library(Hello
	PRIVATE
	hello_lib
)

  此处,通过add_library()来添加一个库目标

add_library(targetName [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
source1 [source2 ...]
)

第一个参数是库目标名字,第二个定义库的类型,通过STATIC生成静态库,SHARED生成动态库,MODULE基本不用。
静态库就是把所有依赖一股脑包含进库文件里,在windows上的后缀为lib,在linux上为.a
动态库与之相反,不包含依赖,在windows上的后缀为.dll,linux上的后缀为.so
第三个个参数顾名思义就是排除些文件,不让他在其中自动编译,可以省略。

最后用target_link_library()来添加库依赖

target_link_libraries(<target>
                      <PRIVATE|PUBLIC|INTERFACE> <item>...
                     [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)

第二个参数是范围,如果在头文件中不包含依赖,而dll文件中包含依赖,那么可以设置为private

//in header a
void int a();

//in header b
void int b();

//in dll b
void int b()
{
	a();
}

如果在头文件中包含依赖,而dll文件中不包含依赖,那么可以用INTERFACE

//in header a
static int a;

//in header b
int c = a;
void int b();

//in dll b
void int b()
{
	//do something
}

PUBLIC可以看做PRIVATE和INTERFACE的结合体

//in header a
static int a;
void int aa();

//in header b
int c = a;
void int b();

//in dll b
void int b()
{
	void int aa();
}

安装库到指定位置

  用的指令如下:

# 将库文件,可执行文件,头文件安装到指定目录
install(TARGETS <target>... [...])
install(IMPORTED_RUNTIME_ARTIFACTS <target>... [...])
install({FILES | PROGRAMS} <file>... [...])
install(DIRECTORY <dir>... [...])
install(SCRIPT <file> [...])
install(CODE <code> [...])
install(EXPORT <export-name> [...])
install(RUNTIME_DEPENDENCY_SET <set-name> [...])

对前一章的代码加上几行

install(TARGETS hello_lib LIBRARY
DESTINATION lib)

install(TARGETS Hello 
DESTINATION bin)

install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ DESTINATION include)

在linux里,这些代码会把所有文件安装在 +${CMAKE_INSTALL_PREFIX}+下的相应文件夹下, +${CMAKE_INSTALL_PREFIX}+默认为/usr/local/
在windows里,则会安装到C:\Program Files (x86),当然,需要管理员权限。

执行make install来安装。

END