1、 cmake基本指令解析及示例
cmake_minimum_required:cmake最低版本要求
PROJECT_SOURCE_DIR:CMakeLists.txt文件所在的当前目录
include_directories:用于包含源文件的头文件
EXECUTABLE_OUTPUT_PATH :执行文件输出路径
CMAKE_BUILD_TYPE:编译生成调试或者发布模式(debug 或者 release)
STREQUAL :字符串之间的等号
add_definitions:添加编译参数
CMAKE_CXX_FLAGS_DEBUG :c++调试模式编译参数设置
CMAKE_CXX_FLAGS_RELEASE:c++发布模式编译参数设置
aux_source_directory:添加自定义源文件路径
add_executable:生成可执行文件
$ENV:调用系统环境变量指令
CXXFLAGS:c++编译器的选项,由后面参数项设置
-O0:不做优化,在调试过程中需要知道运行的所有的信息,故不需要优化
-O3:最高优化,在生成发布版本时尽可能优化代码,去除不必要的的信息
-Wall:生成警告信息
-g -ggdb:启动调试功能gdb调试
-std=c++11:采用c++11标准
-fopenmp:开启并行多线程设置,需要在源码中设置OPENMP框架指令说明
# CMake 最低版本号要求
cmake_minimum_required(VERSION 2.8)
# 项目信息
project("main")
# include路径
include_directories(${PROJECT_SOURCE_DIR}/lib)
# 设置可执行文件生成路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../bin)
# 生成debug版本
SET(CMAKE_BUILD_TYPE "debug")
#SET(CMAKE_BUILD_TYPE "release")
if (CMAKE_BUILD_TYPE STREQUAL debug)
add_definitions(-D_DEBUG) #在gcc命令行添加DEBUG宏定义
endif ()
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb -std=c++11 -fopenmp")
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall -std=c++11 -fopenmp")
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_SRCS)
# . 表示当前路径
aux_source_directory(./src DIR_SRCS)
# 指定生成目标,
add_executable(main ${DIR_SRCS})
2、生成静态库和共享库
在c++工程中,并不是所有代码都会编译成可执行文件。只有带有main函数的文件才会生成可执行程序。而另一些代码,我们只想把他们打包成一个东西,供其他程序调用。这个东西叫做库。
一个库往往是许多算法程序的集合,本节将示例cmake如何生成库,并使用库中的函数。
先写一个hello world程序
文件名:helloworld.cpp
#include <iostream>
void printHello() {
std::cout<<"Hello World"<<std::endl;
}
这个库提供了一个printHello函数,调用此函数将输出一条信息。但是他没有main函数,这意味着这个库没有可执行文件。我们在CMakeLists.txt里添加如下内容:
add_library(hello helloworld.cpp)
这条指令告诉cmake,我们想把这个文件编译成一个叫作“hello”的库。然后,使用cmake编译整个工程:
mkdir build && cd build
cmake ..
make
这时,在build文件夹中就会生成一个libhello.a文件,这就是我们得到的库。
在linux中,库文件分为静态库和共享库两种。静态库以.a作为后缀名,共享库以.so结尾。所有库都是一些函数打包后的 集合,差别在于静态库每次被调用都会生成一个副本,而共享库则只有一个副本,更省空间。如果想生成共享库而非静态库,只需使用以下语句即可。
add_library(hello_shared SHARED helloworld.cpp)
此时得到的文件就是hello.so了。库文件是一个压缩包,里面有编译好的二进制函数。不过,如果仅有.a或.so库文件,那么我们并不知道里面的函数到底是什么,调用的形式又是什么样。为了让别人使用这个库,我们需要提供一个头文件,说明这个库里都有些什么。因此,对于库的使用者,只要拿到头文件和库文件,就可以调用这个库了。下面编写libhello的头文件
libhello.h
#ifndef LIBHELLO_H_
#define LIBHELLO_H_
void printHello();
#endif
这样,根据这个文件和我们刚才编译得到的库文件,就可以使用printHello函数了。下面写一个可执行程序调用这个函数:
useHello.cpp
#include "libHello.h"
int main(int argc,char** argv) {
printHello();
return 0;
}
然后,在CMakeLists.txt中添加一个可执行程序的生成命令,链接到刚才使用的库上:
add_executable(useHello useHello.cpp)
target_link_libraries(useHello hello_shared)
通过这两行语句,useHello程序就能顺利使用hello_shared库中的代码了。