目录

​官网查阅​

​开胃菜例子​

​CMakeLists生成和添加依赖库​

​add_library(生成库),target_link_libraries(生成目标连接的库),set_target_properties​

​CMAKE 添加编译选项|-g编译参数/选项​

​包含文件的的目录​

​CMake设置编译参数/选项​

​如何在cmakelists中加入-ldl编译选项​

​CMake指定gcc,g++版本编译​

​CMake 关闭警告的方法​

​关闭编译器优化​

​Debug和Release 方案​

​About table​

​About question​

​CMakeLists 实现动态宏开关​

​去掉编译优化​



官网查阅

​https://cmake.org/cmake/help/latest/search.html?q=add_library​

开胃菜例子

生成一个可执行程序的 CMakeList

#添加包含文件的的目录
include_directories(${cppzmq_INCLUDE_DIR})

#用${SOURCE_FILES}指定的文件,生成可执行文件sample_project
add_executable(sample_project ${SOURCE_FILES})

#生成可执行文件sample_project 需要连接 ${CMAKE_THREAD_LIBS_INIT}指定的库
target_link_libraries (sample_project ${CMAKE_THREAD_LIBS_INIT})

生成一个.so动态库的 CMakeList 

#用${SRC_LISTS}指定的所有的源文件生成一个库,名字叫libsugan
add_library(libsugan ${SRC_LISTS})

#生成libsugan库需要链接 ${OpenCV_LIBS}、 ${PROJECT_SOURCE_DIR}/lib/libCommonUtilities.so、${PROJECT_SOURCE_DIR}/lib/libInuStreams.so
target_link_libraries(libsugan
${OpenCV_LIBS}
${PROJECT_SOURCE_DIR}/lib/libCommonUtilities.so
${PROJECT_SOURCE_DIR}/lib/libInuStreams.so
)

CMakeLists生成和添加依赖库

Opencv依赖库的添加:

cmake_minimum_required( VERSION 2.8 )
project( imageBasics )

# 添加c++ 11标准支持
set( CMAKE_CXX_FLAGS "-std=c++11" )

# 寻找OpenCV库
set(OpenCV_DIR /home/chaofan/opt/opencv-3.4.4/release)
find_package( OpenCV 3 REQUIRED )
# 添加头文件
include_directories( ${OpenCV_INCLUDE_DIRS} )

add_executable( imageBasics imageBasics.cpp )
# 链接OpenCV库
target_link_libraries( imageBasics ${OpenCV_LIBS} )

上面说明了添加依赖库的主要步骤:

第一个: 添加头文件

第二个:找到源文件

第三个:与目标链接起来

若工程中需要指定不同版本的opencv,则可以按照一下方法操作:

1.指定库路径

file(GLOB_RECURSE Opencv3.0_LIB "/home/LiuMC/software/third_lib/opencv3.0-install/lib/*.so")

2.指定头文件路径

set(Opencv3_INLCUDE_DIRS "/home/LiuMC/software/third_lib/opencv3.0-install/include")

3.添加头文件到工程

include_directories(include
${Opencv3_INLCUDE_DIRS}
)

4.添加库文件到工程

target_link_libraries(rovioLib  ${Opencv3.0_LIB})

注意:为了避免不必要的麻烦,尽量将头文件和库文件加再第一项,如:

target_link_libraries(rovioLib  
${Opencv3.0_LIB}
${Opencv3.0_HAL_LIB}
${catkin_LIBRARIES}
)

link_libraries(dcn_v2_cuda_forward_v2) 和target_link_libraies的区别?

简单例子:

一、生成.so共享库文件

下面是我的几个文件:

1hello.cpp

//hello.cpp
int Calculate_sum_Of_Two_Number(int x,int y)
{
int z=0;
z=x+y;
return (z);
}

2hello.hpp

//hello.hpp
#ifndef __HELLO_H
#define __HELLO_H
int Calculate_sum_Of_Two_Number(int x,int y);
#endif

3 main.cpp

//main.cpp
#include "hello.hpp"
#include <stdio.h>
int main(void)
{
int a=0,b=0,c=0;
printf("please input two parameter:");
scanf("%d",&a);
scanf("%d",&b);
c=Calculate_sum_Of_Two_Number(a,b);
printf("the sum is : %d",c);
return 0;
}

4 CMakeLists.txt

#要求的Cmake最低版本
CMAKE_MINIMUM_REQUIRED( VERSION 2.8)

#工程名称
PROJECT(main)

#设置编译器编译模式:
set( CMAKE_BUILD_TYPE "Debug" )

#生成共享库
#get the shared package
#here needs no .hpp
add_library(calculate_shared SHARED hello.cpp)

#生成可以执行的文件
add_executable(main main.cpp)

#连接共享库
target_link_libraries(main calculate_shared)

上面CmakeLists.txt里面, 共享库的名称是calculate_shared,这个是我们可以自己更改的。生成的可执行文件是main, 这个名称也是可以更改的。

不过需要注意的是,hello.cpp里面不用在包含hello.hpp 了。(汗,因为这个导致出错,提示说是重复定义函数了);

编译生成:

mkdir build

cd    build

cmake ..

make

我们就可以看到build生成了 如下的文件:

CMakeCache.txt  cmake_install.cmake     main

CMakeFiles      libcalculate_shared.so  Makefile

 libcalculate_shared.so就是生成的共享库文件。

他们的路径是:/home/fan/dev/cmake/4-exer/

下面有build文件夹,以及main.cpp, hello.cpp, hello.hpp, 

build文件夹下面有共享库 libcalculate_shared.so.so

二、调用共享库文件

所有的外部依赖库都是这样的,比如opencv ,openni, eigen等等,原理是一样的,只不过他们已经安装在系统里面了,可以查找,而这个则是需要我们自己去配置。

即我上面生成的共享库文件本质上和opencv的库是相同的。只不过这个共享库需要自己手动配置。

比如我又新建了一个工程,需要调用上面的共享库 libcalculate_shared.so。

main.cpp如下:

//main.cpp
#include <stdio.h>
#include <iostream>
#include "hello.hpp"
using namespace std;
int main(void)
{
int x=2,y=3;
int z=0;
z=Calculate_sum_Of_Two_Number(x,y);
cout<<"the result is:"<<z<<endl;
return 0;
}

那么在CMakeLists.txt里面,我需要告诉CMake, 这个头文件可以在哪里找到,头文件所定义的函数又可以在哪里找到。

上面hello.hpp的路径是:/home/fan/dev/cmake/4-exer/hello.hpp

libcalculate_shared.so的路径是/home/fan/dev/cmake/4-exer/build/libcalculate_shared.so

则CMakeLists.txt如下:

CMAKE_MINIMUM_REQUIRED( VERSION 2.8)

PROJECT(main)
#设置编译器编译模式:
SET( CMAKE_BUILD_TYPE "Debug" )

SET(HELLO_INCLUE
/home/fan/dev/cmake/4-exer/)

SET(HELLO_SRC
/home/fan/dev/cmake/4-exer/build/libcalculate_shared.so)

INCLUDE_DIRECTORIES(${HELLO_INCLUE})

add_executable(main main.cpp)

target_link_libraries(main ${HELLO_SRC})

这里要注意一些细节(对于我这个渣渣来说的)

1、${   }这种形式代表一个变量,比如上面的,HELLO_INCLUE ,就是我自己定义的一个变量。

2、头文件包含到头文件所在的文件夹,即 /home/fan/dev/cmake/4-exer/

3、共享库要指明具体的共享库 ,精确到.so

其实主要的就是指明这个调用这个共享库的时候,使用的头文件,以及共享库本身所在的位置,然后包含链接就可以了。

安装过的共享库(例如opencv)就不用这么麻烦了,因为它的地址都放在了变量里面。

Opencv的依赖添加

比如Opencv, 它的头文件和.so文件都已经放在了系统变量里面,不用向上面自己定义了(上面例子里面的头文件和共享库文件的地址都是我自己设置的)

它的CMakeLists.txt如下:

find_package(OpenCV REQUIRED)

include_directories(${OPENCV_INCLUDE_DIRS})

target_link_libraries(MAIN ${OpenCV_LIBS})

只需要查找就可以了,OpenCV_LIBS  和  OPENCV_INCLUDE_DIRS  都是系统帮我们已经定义好的,所以比较容易

参考博客:

1、如何写自己的CmakeLists.txt 

2、 【OpenCV】使用CMake链接自己路径下面的OpenCV库

add_library(生成库),target_link_libraries(生成目标连接的库),set_target_properties

add_library(libsugan ${SRC_LISTS})    #用${SRC_LISTS}生成静态库libsugan

target_link_libraries(libsugan      #生成静态库libsugan还需链接依赖库${OpenCV_LIBS}…

    ${OpenCV_LIBS}

    ${PROJECT_SOURCE_DIR}/lib/libCommonUtilities.so

    ${PROJECT_SOURCE_DIR}/lib/libInuStreams.so

)

#上面的配置生成名字为libsugan的静态库,但Linux下对库的存储格式是lib+name.a,所以库libsugan存储出来的结果就是liblibsugan.a,看着很别扭。用下面这句,保证了存储出来的静态库叫做libsugan.a:

set_target_properties(libsugan PROPERTIES OUTPUT_NAME "sugan")

#但是请千万注意,在整个CmakeLists.txt里

#如果想链接生成的这个库必须使用    “add_library(libsugan ${SRC_LISTS})”指明的名字。

set_target_properties(libsugan PROPERTIES OUTPUT_NAME "sugan")

add_executable(demo ./src/main.cpp)

target_link_libraries(demo libsugan)

原例子:​

#工程名字
project(Camera_sugan)

#编译最低cmake版本
cmake_minimum_required(VERSION 2.6)

#设置c++编译器
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" )

#在整个电脑上找opencv包
find_package(OpenCV REQUIRED)

#包含头文件路径
include_directories(
./include/inudev/
./src/
)

#将所有的源文件列为一个集合,集合名字叫做SRC_LISTS
set(SRC_LISTS
./src/inuitive.cpp
./src/runCamera_Qfeeltech.cpp
)

#将集合里的所有的源文件生成一个静态库,该静态库的名字libsugan,
注意,在整个CmakeLists里都要用libsugan这个
add_library(libsugan ${SRC_LISTS})

#名字来代替之前那个集合生成的库。
target_link_libraries(libsugan #链接静态库需要的依赖库
${OpenCV_LIBS}
${PROJECT_SOURCE_DIR}/lib/libCommonUtilities.so
${PROJECT_SOURCE_DIR}/lib/libInuStreams.so
)

原文链接:javascript:void(0)

CMAKE 添加编译选项|-g编译参数/选项

add_definitions 和add_compile_options,二者添加的编译选项是针对所有编译器的(包括c和c++编译器)。

add_definitions 和add_compile_options的区别是:

add_definitions 可用于添加任何标志,但旨在添加预处理器定义。

此命令已被替代方案取代:

使用 add_compile_definitions() 添加预处理器定义。

使用 include_directories() 添加包含目录。

使用 add_compile_options() 添加其他选项。

​https://cmake.org/cmake/help/latest/command/add_definitions.html​

添加 -g编译参数/选项

在文件 CMakeLists.txt添加下面一条语句

add_definitions("-g")

添加其他编译参数/选项

例如下面的代码

#判断编译器类型,如果是gcc编译器,则在编译选项中加入c++11支持

if(CMAKE_COMPILER_IS_GNUCXX)
    add_compile_options(-std=c++11)
    message(STATUS "optional:-std=c++11")   
endif(CMAKE_COMPILER_IS_GNUCXX)
 


使用add_compile_options添加-std=c++11选项,是想在编译c++代码时加上c++11支持选项。但是因为add_compile_options是针对所有类型编译器的,所以在编译c代码时,就会产生如下warning

J:\workspace\facecl.gcc>make b64
[ 50%] Building C object libb64/CMakeFiles/b64.dir/libb64-1.2.1/src/cdecode.c.obj
cc1.exe: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C
[100%] Building C object libb64/CMakeFiles/b64.dir/libb64-1.2.1/src/cencode.c.obj
cc1.exe: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C
Linking C static library libb64.a
[100%] Built target b64

虽然并不影响编译,但看着的确是不爽啊,要消除这个warning,就不能使用add_compile_options,而是只针对c++编译器添加这个option。

所以如下修改代码,则警告消除。

#判断编译器类型,如果是gcc编译器,则在编译选项中加入c++11支持

if(CMAKE_COMPILER_IS_GNUCXX)

    set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")

    message(STATUS "optional:-std=c++11")   

endif(CMAKE_COMPILER_IS_GNUCXX)


包含文件的的目录

include_directories(${cppzmq_INCLUDE_DIR})  //添加包含文件的的目录

add_definitions 可用于添加任何标志,但旨在添加预处理器定义。

此命令已被替代方案取代:

使用 add_compile_definitions() 添加预处理器定义。

使用 include_directories() 添加包含目录。

使用 add_compile_options() 添加其他选项。

CMake设置编译参数/选项

而set命令设置CMAKE_C_FLAGS或CMAKE_CXX_FLAGS变量则是分别只针对c和c++编译器的

对c编译器的

set(CMAKE_C_FLAGS"-O3 -fopenmp -fPIC -Wno-deprecated -Wenum-compare -std=c++14")

针对c++编译器的

set(CMAKE_CXX_FLAGS "-O3 -fopenmp -fPIC -Wno-deprecated -Wenum-compare -std=c++14")

如何在cmakelists中加入-ldl编译选项

cmakelists.txt中,在增加可执行程序后增加TARGET_LINK_LIBRARIES

eg:

add_executable(xx ${ALL_F} ${WE_F})

TARGET_LINK_LIBRARIES(dl)

TARGET_LINK_LIBRARIES(m)

set(CMAKE_C_FLAGS "-ldl")

在add_executable(${PROJECT_NAME} "main.cpp")后面添加

target_link_libraries(${PROJECT_NAME} dl)

target_link_libraries(exe1 -Wl, - -whole-archive lib1 -Wl, -  no-whole-archive)

CMake指定gcc,g++版本编译

系统默认的gcc/g++在/usr/bin目录下。

我们升级安装的gcc目录在/usr/local/bin目录下,现在我们希望使用升级后的gcc。

通过百度搜索出来的结果,大多是如下操作:

在CMakeLists.txt中调用编译器之前添加:


1

2



​SET(CMAKE_C_COMPILER ​​​​"/usr/local/bin/gcc"​​​​)​

​SET(CMAKE_CXX_COMPILER ​​​​"/usr/local/bin/g++"​​​​)​


然而经过本人亲自实践,该方法不起作用,正确的做法是:

执行cmake命令之前,在shell终端先设置如下两个变量:


1

2



​export​​ ​​CC=​​​​/usr/local/bin/gcc​

​export​​ ​​CXX=​​​​/usr/local/bin/g​​​​++​


然后再执行cmake等后续命令,这样就可以用指定的编译器版本了。

​http://www.jyguagua.com/?p=3261​

CMake 关闭警告的方法

在CMakeLists.txt中添加add_definitions(-w)

应用于单个target

  if(CMAKE_COMPILER_IS_GNUCC)
target_compile_options(main PRIVATE"-Wall")
endif()
if(MSVC)
target_compile_options(main PRIVATE"/ W4")
endif()

应用于所有target

  if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_CXX_FLAGS"$ {CMAKE_CXX_FLAGS} -Wall")
endif()
if(MSVC)
set(CMAKE_CXX_FLAGS"$ {CMAKE_CXX_FLAGS} / W4")
endif()

注意:为GCC或/ WX添加-Werror以便MSVC将所有警告视为错误。这会将所有警告视为错误。这对于新项目来说可以方便地执行严格的警告。

另外, -Wall 并不意味着"所有错误";从历史意义上讲,它意味着"每个人都可以达成一致的所有错误""。从 -Wall -Wextra 开始,然后仔细阅读您的版本的GCC手册,并找到 else 编译器可以为您提供关于警告的信息。

关闭编译器优化

(未验证)

1)add_compile_options(-fno-elide-constructors)    #关闭编译器优化

2)set(CMAKE_CXX_FLAGS "-fno-elide-constructors ${CMAKE_CXX_FLAGS}")

Debug和Release 方案

About table

Configurations in terms of gcc/clang compilers (CMake 3.4.1):

  • Debug: -g
  • Release: -O3 -DNDEBUG
  • RelWithDebInfo: -O2 -g -DNDEBUG
  • MinSizeRel: -Os -DNDEBUG

It means:

  +---------------+--------------+--------------+----------+
| | optimization | assert works | stripped |
+---------------+--------------+--------------+----------|
| Debug | no | yes | no |
| Release | full | no | yes |
| RelWithDebInfo| good | no | no |
| MinSizeRel | size | no | yes |
+---------------+--------------+--------------+----------+

So I don't agree with your MinSizeRel description because in this case I think both MinSizeRel and Release are stripped.

About question

As far as I understand you want no extra flags at all (no -g, -O* or -DNDEBUG). For Makefile-like generators:

> cmake -H. -B_builds -DCMAKE_BUILD_TYPE=MyConf -DCMAKE_CXX_FLAGS_MYCONF=""
> cmake --build _builds

CMakeLists 实现动态宏开关

去掉编译优化

在CMakeList中添加:

if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()

set(CMAKE_CXX_FLAGS "-Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")

执行的时候

cmake  -DCMAKE_BUILD_TYPE=Release

参考:

​https://stackoverflow.com/questions/41361631/optimize-in-cmake-by-default​

​https://unix.stackexchange.com/questions/187455/how-to-compile-without-optimizations-o0-using-cmake​

例子

最近在工作中需要通过一份C代码控制逻辑走向,网上找了一下资料,发现可以通过在CMakeLists文件中动态定义宏开关,从而能够达到编译出不同逻辑流的代码。

具体步骤:

首先,我在src代码里编写了若干debug的输出:

#IFDEF DEBUG

 

    some print command;

 

#ENDIF

然后,在CMakeLists文件中添加DEBUG的定义:

IF (CMAKE_BUILD_TYPE STREQUAL DEBUG)

    ADD_DEFINITIONS(-DDEBUG)

ENDIF()

最后,在cmake的时候设置参数 -DCMAKE_BUILD_TYPE 为 DEBUG:

$ cmake .. -DCMAKE_BUILD_TYPE=DEBUG

$ make -j4

这样再运行可执行文件时就会打印出some print command的debug信息了。如果不想看到debug信息,只需在参数中不设置DEBUG参数,或者将DEBUG参数设置为其它值即可(以下两种方式二者选其一):

$ cmake ..

$ cmake .. -DCMAKE_BUILD_TYPE=RELEASE

到此 CMakeLists 实现动态宏开关介绍完成。