CMakeLists.txt cmake 学习

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}
        )

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值