CMAKE: https://blog.csdn.net/kai_zone/article/details/82656964
官方:https://cmake.org/cmake/help/v3.1/
参考文献:https://blog.csdn.net/bigdog_1027/article/details/79113342
https://www.cnblogs.com/cv-pr/p/6206921.html
https://www.cnblogs.com/ph829/p/4759124.html
常见使用情况如下:
mkdir build
cd build
cmake ..
make
cmake ..
会根据CMakeLists.txt在所在目录(比如build里面生成一些配置文件包含Makefile)
两种方法最大的不同在于执行cmake和make的工作路径不同。第一种方法中,cmake生成的所有中间文件和可执行文件都会存放在项目目录中;而第二种方法中,中间文件和可执行文件都将存放再build目录中。第二种方法的优点显而易见,它最大限度的保持了代码目录的整洁。同时由于第二种方法的生成、编译和安装是发生在不同于项目目录的其他目录中,所以第二种方法就叫做“外部构建”。
.. 表示基于上层目录去执行
make
根据Makefile 进行编译
一个例子hello world 例子
新建文件hello
文件内新建main.c内容如下:
#include"stdio.h"
int main(void)
{
printf("hello world\n");
return 0;
}
新建CMakeLists.txt内容如下:
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(HELLO) #项目名称
#把当前目录(.)下的所有源代码文件和头文件加入变量SRC_LIST
AUX_SOURCE_DIRECTORY(. SRC_LIST)
#生成应用程序hello(在windows下会自动生成hello.exe)
ADD_EXECUTABLE(hello ${SRC_LIST})
mkdir build #在hello文件夹内新建build文件
此时目录结构如下:
hello/
|– CMakeLists.txt
|– build /
– main.c
cd build
cmake ..
make
aaron@Aaron-PC:~/Downloads/temp/hello/build$ cmake ..
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- 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
-- Detecting C compile features
-- Detecting C compile features - 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
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/aaron/Downloads/temp/hello/build
aaron@Aaron-PC:~/Downloads/temp/hello/build$ make
Scanning dependencies of target hello
[ 50%] Building C object CMakeFiles/hello.dir/main.c.o
[100%] Linking C executable hello
[100%] Built target hello
aaron@Aaron-PC:~/Downloads/temp/hello/build$
如上结果则没问题, 进行执行hello程序
aaron@Aaron-PC:~/Downloads/temp/hello/build$ ./hello
hello world
aaron@Aaron-PC:~/Downloads/temp/hello/build$
多文件夹管理:
./step2
|--- main.cpp
|--- src
.Test1.h
.Test1.cpp
其中src 目录下的文件要编译成一个链接库。
.
├── build
├── CMakeLists.txt
├── include
│ └── b.h
└── src
├── b.c
└── main.c
CMakeLists.txt 内容如下
CMAKE_MINIMUM_REQUIRED(VERSION 3.2)
PROJECT(test_sqrt)
#包含头文件的目录
INCLUDE_DIRECTORIES(include)
#源文件目录 这里是src
AUX_SOURCE_DIRECTORY(src DIR_SRCS)
#set environment variable 设置环境变量编译用到的源文件全部要放到这里不然编译可以
通过,但是执行的时候会出现各种问题, 比如"symbol lookup error xxxxxxxxx, undefined symbol"
SET(TEST_MATH ${DIR_SRCS})
#添加需要编译的可执行文件
ADD_EXECUTABLE(${PROJECT_NAME} ${TEST_MATH}) #也可以用${DIR_SRCS} 代替${TEST_MATH}
#添加可执行文件需要的库, 比如我们用到的数学库libm.so (命名规则: lib+name+.so), >就添加该库的名称
TARGET_LINK_LIBRARIES(${PROJECT_NAME} m)
main.cpp
#include"stdio.h"
#include"../include/b.h"
int main(void)
{
int hello_times = 5;
show_hello(hello_times);
double a = 49.0;
double b = 0.0;
b = cal_sqrt(a);
printf("sqrt result=%f\n", b);
return 0;
}
b.cpp
#include"iostream"
#include"../include/b.h"
void show_hello(int times)
{
for(int i=0; i< times; i++)
std::cout<<"你好!"<<std::endl;
};
double cal_sqrt(double value)
{
return sqrt(value);
};
b.h
#ifndef B_FILE_HEADER_INC
#define B_FILE_HEADER_INC
#include"math.h"
double cal_sqrt(double value);
void show_hello(int times);
#endif
5 | ADD_SUBDIRECTORY(src bin) |
ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])这个指令用于向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存放的位置。EXCLUDE_FROM_ALL 参数的含义是将这个目录从编译过程中排除。比如,工程的 example,可能就需要工程构建完成后,再进入 example 目录单独进行构建。
在我们的项目中,我们添加了src目录到项目中,而把对应于src目录生成的中间文件和目标文件存放到bin目录下,在上一节举例中“外部构建”的情况下,中间文件和目标文件将存放在build/srcobj目录下。
8 | SET(CMAKE_INSTALL_PREFIX /usr/local) |
现阶段,只需要了解SET命令可以用来显式的定义变量即可。在以上的例子中,我们显式的将CMAKE_INSTALL_PREFIX的值定义为/usr/local,如此在外部构建情况下执行make install命令时,make会将生成的可执行文件拷贝到/usr/local/bin目录下。
当然,可执行文件的安装路径CMAKE_INSTALL_PREFIX也可以在执行cmake命令的时候指定,cmake参数如下:
cmake -DCMAKE_INSTALL_PREFIX=/usr .. |
如果cmake参数和CMakeLists.txt文件中都不指定该值的话,则该值为默认的/usr/local。
4.6 INCLUDE_DIRECTORIES命令
1 | INCLUDE_DIRECTORIES(/usr/include/thrift) |
INCLUDE_DIRECTORIES类似gcc中的编译参数“-I”,指定编译过程中编译器搜索头文件的路径。当项目需要的头文件不在系统默认的搜索路径时,需要指定该路径。在我们的项目中,log4cpp所需的头文件都存放在/usr/include下,不需要指定;但thrift的头文件没有存放在系统路径下,需要指定搜索其路径。
4.7 ADD_EXECUTABLE和ADD_LIBRARY
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | SET(SRC_LIST main.cc rpc/CRMasterCaller.cpp rpc/CRNode_server.skeleton.cpp rpc/Schd_constants.cpp rpc/CRMaster.cpp rpc/CRNode.cpp rpc/Schd_types.cpp task/TaskExecutor.cpp task/TaskMoniter.cpp util/Const.cpp util/Globals.cc util/utils.cc util/Properties.cpp ) ADD_EXECUTABLE(CRNode ${SRC_LIST}) |
ADD_EXECUTABLE定义了这个工程会生成一个文件名为 CRNode 的可执行文件,相关的源文件是 SRC_LIST 中定义的源文件列表。需要注意的是,这里的CRNode和之前的项目名称没有任何关系,可以任意定义。
4.8 EXECUTABLE_OUTPUT_PATH和LIBRARY_OUTPUT_PATH
我们可以通过 SET 指令重新定义 EXECUTABLE_OUTPUT_PATH 和 LIBRARY_OUTPUT_PATH 变量来指定最终的目标二进制的位置(指最终生成的CRNode可执行文件或者最终的共享库,而不包含编译生成的中间文件)。
命令如下:
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) |
需要注意的是,在哪里 ADD_EXECUTABLE 或 ADD_LIBRARY,如果需要改变目标存放路径,就在哪里加入上述的定义。
4.9 TARGET_LINK_LIBRARIES命令
20 | TARGET_LINK_LIBRARIES(CRNode log4cpp thrift) |
这句话指定在链接目标文件的时候需要链接的外部库,其效果类似gcc的编译参数“-l”,可以解决外部库的依赖问题。
4.10 INSTALL命令
在执行INSTALL命令的时候需要注意CMAKE_INSTALL_PREFIX参数的值。该参数在3.5中已经有所介绍。其命令形式如下:
INSTALL(TARGETS targets... [[ARCHIVE|LIBRARY|RUNTIME] [DESTINATION < dir >] [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT < component >] [OPTIONAL] ] [...]) |
参数中的 TARGETS 后面跟的就是我们通过 ADD_EXECUTABLE 或者 ADD_LIBRARY 定义的目标文件,可能是可执行二进制、动态库、静态库。
https://www.cnblogs.com/coderfenghc/archive/2012/06/23/2559603.html
1. add_library
该指令的主要作用就是将指定的源文件生成链接文件,然后添加到工程中去。该指令常用的语法如下:
add_library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
[source1] [source2] [...])
其中<name>表示库文件的名字,该库文件会根据命令里列出的源文件来创建。而STATIC、SHARED和MODULE的作用是指定生成的库文件的类型。STATIC库是目标文件的归档文件,在链接其它目标的时候使用。SHARED库会被动态链接(动态链接库),在运行时会被加载。MODULE库是一种不会被链接到其它目标中的插件,但是可能会在运行时使用dlopen-系列的函数。默认状态下,库文件将会在于源文件目录树的构建目录树的位置被创建,该命令也会在这里被调用。
而语法中的source1 source2分别表示各个源文件。
例子:
2. link_directories
该指令的作用主要是指定要链接的库文件的路径,该指令有时候不一定需要。因为find_package和find_library指令可以得到库文件的绝对路径。不过你自己写的动态库文件放在自己新建的目录下时,可以用该指令指定该目录的路径以便工程能够找到。
例子如下:
link_directories(
lib
)
实战
Clion opencv工程
cmake_minimum_required(VERSION 3.13)
project(test)
find_package( OpenCV 3 REQUIRED )
set(CMAKE_CXX_STANDARD 14)
add_executable(test main.cpp)
target_link_libraries(test ${OpenCV_LIBS})
实战2 caffe ssd
注意把build里面的./build/src/caffe/proto的文件放在 caffe基本目录./src/caffe/proto里面
cmake_minimum_required(VERSION 3.13)
project(test)
set(CMAKE_CXX_STANDARD 14)
find_package( OpenCV 3 REQUIRED )
#find_package( Boost 1.58 REQUIRED )
#if (NOT Boost_FOUND)
# message(FATAL_ERROR "没找到boost")
#endif ()
set(Caffe_Root /home/aaron/mydisk/envs/caffe_lib/caffe)
set(Caffe_INCLUDE_DIRS
${Caffe_Root}/include
${Caffe_Root}/src
/usr/local/cuda/include)
set(Caffe_LIBRARIES
caffe
glog
protobuf)
set(TOOLS_LIBRARIES
boost_system
boost_filesystem
gflags)
include_directories(
${Caffe_INCLUDE_DIRS}
${OpenCV_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}
/usr/include
/usr/local/include
# ${Boost_INCLUDE_DIRS}
)
LINK_DIRECTORIES(
${Caffe_Root}/build/lib
# ${Boost_LIBRARY_DIRS}
)
#add_library(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR})
AUX_SOURCE_DIRECTORY(. SRC_LIST)
ADD_EXECUTABLE(run main.cpp ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(run
${PROJECT_NAME}
${OpenCV_LIBS}
${Caffe_LIBRARIES}
${TOOLS_LIBRARIES}
)