【cmake】CMakeList添加库|添加头文件|添加路径|add_executable、add_library、target_link_libraries|添加编译选项|宏开关

目录

官网查阅

开胃菜例子

CMakeLists生成和添加依赖库

CMakeLists更多小例子

生成.so共享库文件

二、调用共享库文件

生成一个可执行程序的 CMakeList

生成一个.so动态库的 CMakeList 

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

包含文件的的目录include_directories

优化项|优化等级

Cmake设置优化等级| cmake 生成 debug和 release 版

设置默认构建类型

CMake设置编译参数/选项

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

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

CMake 关闭警告的方法

关闭编译器优化

Debug和Release 方案

About table

About question

CMakeLists 实现动态宏开关

去掉编译优化

CMake--List用法

CmakeLists.txt单行注释和多行注释 

CMakeList 通配符

其他未归类

add_custom_target  自定义命令

add_dependencies 

Cmake条件判断指令|if 判断优先级

设置编译时和程序运行时去哪个目录找动态库

#指定运行时动态库的加载路径

#指定链接时动态库的路径

cmake install 和打包设定


@bandaoyu:本文持续更新,本文链接:https://blog.csdn.net/bandaoyu/article/details/115165199

官网查阅

Search — CMake 3.22.0-rc1 Documentation

https://cmake.org/cmake/help/v3.23/manual/cmake-commands.7.html

 CMake Cookbook:前言 - 《CMake菜谱(CMake Cookbook中文版)》 - 书栈网 · BookStack

开胃菜例子

CMakeLists生成和添加依赖库

原文;cmake之生成动态库 - mohist - 博客园

1、目录结构

│  CMakeLists.txt
│  index.txt
│  
├─build
├─include
│      hello.h
│      hi.h
│      
└─src
        hello.cxx
        hi.cxx

2、CMakeLists.txt

cmake_minimum_required(VERSION 3.1)

#项目名
project(libhello)

# 1、指定库的目录变量
set(libhello_src src/hello.cxx)
# 指定头文件搜索路径
include_directories("${PROJECT_SOURCE_DIR}/include")



# 2、添加库(对应的两个项目)
add_library( hello_shared SHARED ${libhello_src})
add_library( hello_static STATIC ${libhello_src})
#  按照一般的习惯,静态库名字跟动态库名字应该是一致的,只是扩展名不同;
# 即:静态库名为 libhello.a; 动态库名为libhello.so ;
# 所以,希望 "hello_static" 在输出时,不是"hello_static",而是以"hello"的名字显示,故设置如下
# SET_TARGET_PROPERTIES (hello_static PROPERTIES OUTPUT_NAME "hello")


# 3、cmake在构建一个新的target时,会尝试清理掉其他使用这个名字的库,
# 因此,在构建libhello.a时,就会清理掉libhello.so.
# 为了回避这个问题,比如再次使用SET_TARGET_PROPERTIES定义 CLEAN_DIRECT_OUTPUT属性。
SET_TARGET_PROPERTIES (hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES (hello_shared PROPERTIES CLEAN_DIRECT_OUTPUT 1)


# 4、按照规则,动态库是应该包含一个版本号的,
# VERSION指代动态库版本,SOVERSION指代API版本。
SET_TARGET_PROPERTIES (hello_static PROPERTIES VERSION 1.1 SOVERSION 1)
SET_TARGET_PROPERTIES (hello_shared PROPERTIES VERSION 1.1 SOVERSION 1)


# 5、若将libhello.a, libhello.so.x以及hello.h安装到系统目录,才能真正让其他人开发使用,
# 本例中,将hello的共享库安装到/lib目录;
# 将hello.h安装/include/hello目录。
#INSTALL (TARGETS hello hello_shared LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
#INSTALL (TARGETS hello hello_static LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
#INSTALL (FILES hello.h DESTINATION include/hello)

3、configure and generate

xxx/to/path

cd build
cmake ..

4、其他设置

  若需要指定输出路径,尝试下面的示例指令:

# 设置VS会自动新建Debug和Release文件夹
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Bin)

# 设置分别设置Debug和Release输出目录
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/Lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/Lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/../../build/Debug)

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/Lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/Lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/Bin)

CMakeLists更多小例子

生成.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 
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 
#include 
#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:"<


那么在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_SO 
    /home/fan/dev/cmake/4-exer/build/libcalculate_shared.so)
 
INCLUDE_DIRECTORIES(${HELLO_INCLUE})
 
add_executable(main main.cpp)
 
target_link_libraries(main ${HELLO_SO})


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

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   https://www.cnblogs.com/chaofn/p/10160555.html

2、 【OpenCV】使用CMake链接自己路径下面的OpenCV库 https://blog.csdn.net/twt520ly/article/details/81981473

原文链接:https://blog.csdn.net/qq_37761077/article/details/88750711

生成一个可执行程序的 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
)


原文链接:https://blog.csdn.net/bandaoyu/article/details/115165199

grep -nR  "common"  ./  --include=*.txt|grep -vE "src_bak|boost|erasure-code|doc|link.txt"

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

生成静态库:

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

ADD_LIBRARY(static_lib STATIC ${DIR_SUB_SRCS})

生成动态库(加SHARED  ):
add_library(libsugan  SHARED  ${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)

连接库:

target_link_libraries(demo libsugan)

target_link_libraries(app libsort.a)  #生成app 链入 libsort.a静态库

TARGET_LINK_LIBRARIES(app libsort.a)

原例子:

add_library,target_link_libraries,set_target_properties,target_link_libraries使用联系_michaelhan3的博客-CSDN博客

#工程名字
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
)


原文链接:https://blog.csdn.net/michaelhan3/article/details/69568362

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

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

add_definitions 和add_compile_options的区别是:

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

此命令已被替代方案取代:
使用 add_compile_definitions() 添加预处理器定义。
使用 include_directories() 添加包含目录。
使用 add_compile_options() 添加其他选项。

add_definitions — CMake 3.22.0-rc1 Documentation

添加 -g编译参数/选项

方法一:add_definitions("-g")/ add_compile_options


在文件 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。

方法二:set

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

#判断编译器类型,如果是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)


原文链接:https://blog.csdn.net/qinglongzhan/article/details/80743731

包含文件的的目录include_directories

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

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

此命令已被替代方案取代:
使用 add_compile_definitions() 添加预处理器定义。
使用 include_directories() 添加包含目录。
使用 add_compile_options() 添加其他选项。

优化项|优化等级

更多和详细解释:https://blog.csdn.net/bandaoyu/article/details/123700034

-O0禁止编译器进行优化。默认为此项。
-O1尝试优化编译时间和可执行文件大小。

-O2更多的优化,会尝试几乎全部的优化功能,但不会进行“空间换时间”的优化方法。

-O3在 -O2 的基础上再打开一些优化选项:-finline-functions, -funswitch-loops 和 -fgcse-after-reload 。

-Os对生成文件大小进行优化。它会打开 -O2 开的除了会那些增加文件大小的全部选项。

可以通过下面的命令查找工程中设置优化项的地方:

grep -nR  "\-O"  ./  --include=*.txt

过滤掉含有 build、boost、erasure-code、doc、link.txt字样的结果

grep -nR  "\-O"  ./  --include=*.txt|grep  -vE  "build|src_bak|boost|erasure-code|doc|link.txt"

Cmake设置优化等级| cmake 生成 debug和 release 版

见文章:

https://blog.csdn.net/bandaoyu/article/details/123700034

    CMake 中有一个变量 CMAKE_BUILD_TYPE ,可以的取值是 Debug 、Release、 RelWithDebInfo 和 MinSizeRel。

当这个变量值为 Debug 的时候,CMake 会使用变量 CMAKE_CXX_FLAGS_DEBUG 和 CMAKE_C_FLAGS_DEBUG 中的字符串作为编译选项生成 Makefile ,

当这个变量值为 Release 的时候,工程会使用变量 CMAKE_CXX_FLAGS_RELEASE 和 CMAKE_C_FLAGS_RELEASE 选项生成 Makefile。

提供的级别为:

  • Release - Adds the -O3 -DNDEBUG flags to the compiler
  • Debug - Adds the -g flag
  • MinSizeRel - Adds -Os -DNDEBUG
  • RelWithDebInfo - Adds -O2 -g -DNDEBUG flags


链接:https://www.jianshu.com/p/d761232e8e90
 

CMakeCache.txt:89:CMAKE_ASM_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
CMakeCache.txt:92:CMAKE_ASM_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
CMakeCache.txt:95:CMAKE_ASM_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
CMakeCache.txt:123:CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
CMakeCache.txt:126:CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
CMakeCache.txt:129:CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG
CMakeCache.txt:150:CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG
CMakeCache.txt:153:CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG
CMakeCache.txt:156:CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG

 

cmake设置默认CMAKE_BUILD_TYPE

原文:[CMake] Set default build type in CMakeLists.txt

CMakeLists.txt里写入

IF (NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "Release" CACHE STRING
        "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
ENDIF()

设置默认构建类型

CMake提供的默认构建类型是不包含用于优化的编译器标志。对于某些项目,您可能需要设置默认生成类型,以便不必记住设置它。
为此,您可以将以下内容添加到CMakeLists.txt文件顶层

if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  message("Setting build type to 'RelWithDebInfo' as none was specified.")
  set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
  # Set the possible values of build type for cmake-gui
  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
    "MinSizeRel" "RelWithDebInfo")
endif()


作者:xingxingRealzyx
链接:https://www.jianshu.com/p/d761232e8e90

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等后续命令,这样就可以用指定的编译器版本了。

【已解决】CMake指定gcc,g++版本编译 | 勤奋的小青蛙

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 编译器可以为您提供关于警告的信息。

CMake和编译器警告 - IT屋-程序员软件开发技术分享社区

关闭编译器优化

(未验证)

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

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

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

也可以在上一层(调用本CMakeList.txt的)的CMakeList.txt中添加下面:

option (CMAKE_BUILD_TYPE "Use tutorial provided math implementation"  ON)

表示启用CMAKE_BUILD_TYPE 宏。

option (CMAKE_BUILD_TYPE "Use tutorial provided math implementation"  OFF) #表示关

参考:

c++ - Optimize in CMake by default - Stack Overflow

debugging - How to compile without optimizations -O0 using CMake - Unix & Linux Stack Exchange

例子

最近在工作中需要通过一份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 实现动态宏开关介绍完成。

原文链接:https://blog.csdn.net/qq_19734597/article/details/104461963

CMake--List用法

CMake--List用法 - narjaja - 博客园

CmakeLists.txt单行注释和多行注释 

单行注释:使用“#”
多行注释:使用“#[[ ]]”

【cmake】CMakeList添加库|添加头文件|添加路径|add_executable、add_library、target_link_libraries|添加编译选项|宏开关_第1张图片

CMakeList 通配符

  $

说明:

$¶
New in version 3.1.

List of objects resulting from build of objLib.
构建 objLib 产生的对象列表

add_executable(test   test.cc   $),表示使用 test.cc和构建A产生的对象 联合编译出test。

add_executable(test2   $  $ ),表示使用构建A产生的对象  和 构建B产生的对象 联合编译出test。

例子:某个工程如下

-  CMakeLists.txt
-  include
    -  a.hh
-  lib
    -  CMakeLists.txt
    -  a.cc
-  src
    -  CMakeLists.txt
    -  main.cc
-  test
    -  CMakeLists.txt
    -  test.cc

使用 CMake 使用命令编译 test.cc
add_executable(test test.cc $)

使用的A.o 的编译为
add_library(A   OBJECT  A.cc)

来自:https://stackoverflow.com/questions/35696103/cmake-wildcard-for-target-objects

其他未归类

add_custom_target  自定义命令

https://www.bookstack.cn/read/CMake-Cookbook/content-chapter5-5.4-chinese.md

add_custom_target(finish 
    COMMAND ${CMAKE_COMMAND} -E echo compile finish
    COMMAND ${CMAKE_COMMAND} -E copy_directory ${SOURCE_DIR}/config ${SOURCE_DIR}/etc
    COMMAND ${CMAKE_COMMAND} -E copy ${SOURCE_DIR}/log.txt ${SOURCE_DIR}/etc
    )

定义了一个自定义命令:finish ,执行该命令就会进行以下操作:

COMMAND ${CMAKE_COMMAND} -E echo compile finish
COMMAND ${CMAKE_COMMAND} -E copy_directory ${SOURCE_DIR}/config ${SOURCE_DIR}/etc
COMMAND ${CMAKE_COMMAND} -E copy ${SOURCE_DIR}/log.txt ${SOURCE_DIR}/etc

单独执行命令的方式是: cmake --build

[] [-- ]

cmake --build  /home/mydir   --target   finish

【cmake】CMakeList添加库|添加头文件|添加路径|add_executable、add_library、target_link_libraries|添加编译选项|宏开关_第2张图片

与 add_executable(main main.cpp) 、add_library(mylib mylib.cpp) 的不同是,这两个会生成(产出)main、mylib文件。add_custom_target(comandname  ……)只会执行列出的操作,不会产生comandname文件

add_dependencies 

如果main 依赖a.so b.so TARGET_LINK_LIBRARIES(main a.so b.so c.so d.so) 

而a.so b.so 的生成晚于main(即编译脚本的顺序把a.so b.so 安排在后面编译),则需要ADD_DEPENDENCIES(main a.so b.so) 提前为main编译a.so b.so,否则可能会报错:符号的定义找不到 (这些符号恰恰就在a.so 和 b.so中)

详情见:https://blog.csdn.net/KingOfMyHeart/article/details/112983922

Cmake条件判断指令|if 判断优先级

cmake(十六)Cmake条件判断指令:https://blog.csdn.net/wzj_110/article/details/116105719

一  基础语法

①  基本框架

【cmake】CMakeList添加库|添加头文件|添加路径|add_executable、add_library、target_link_libraries|添加编译选项|宏开关_第3张图片

②  优先级

③  条件的类型

【cmake】CMakeList添加库|添加头文件|添加路径|add_executable、add_library、target_link_libraries|添加编译选项|宏开关_第4张图片

【cmake】CMakeList添加库|添加头文件|添加路径|add_executable、add_library、target_link_libraries|添加编译选项|宏开关_第5张图片

【cmake】CMakeList添加库|添加头文件|添加路径|add_executable、add_library、target_link_libraries|添加编译选项|宏开关_第6张图片

【cmake】CMakeList添加库|添加头文件|添加路径|add_executable、add_library、target_link_libraries|添加编译选项|宏开关_第7张图片

设置编译时和程序运行时去哪个目录找动态库

#指定运行时动态库的加载路径


SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)  #Use the install path for the RPATH
SET(CMAKE_INSTALL_RPATH   "\${ORIGIN}/lib" )     #The rpath to use for installed targets.

https://cmake.org/cmake/help/v3.0/variable/CMAKE_INSTALL_RPATH.html?highlight=cmake_install_rpath

程序运行时,搜索动态库的顺序(优先级)优先级是这样的:

1. RPATH ,编译链接时加入 -rpath 参数 指定的目录
2. LD_LIBRARY_PATH  这个环境变量指定的目录
3. /etc/ld.so.conf 配置文件。
4. /usr/lib 、 /lib 和 /usr/local/lib ,系统默认路径。

所以我们设置了RPATH ,并且RPATH 下有要找的动态库,程序就首先加载它

注意:

可以看到,RPATH与RUNPATH中间隔着LD_LIBRARY_PATH。为了让用户可以通过修改LD_LIBRARY_PATH来指定.so文件,大多数编译器都将输出的RPATH留空,并用RUNPATH代替RPATH。

linux cmake分别指定编译/运行时动态库链接路径:https://blog.csdn.net/JCYAO_/article/details/102519998



探讨CMake中关于RPATH的使用(https://www.cnblogs.com/rickyk/p/3875084.html):

CMake在默认情况下是会给你的exe加入相关RPATH的,可能给你加入你不想要的一些RPATH(就是一些Cmake认为的你的程序应该去哪里寻找需要的动态库的目,可以用“readelf -d 你的程序”来查看,例子:

[root]readelf -d  /opt/bin/ceph-osd

Dynamic section at offset 0x10a36e8 contains 59 entries:
  Tag        Type                         Name/Value
 ……
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]
 0x000000000000000f (RPATH)              Library rpath: [/opt/lib_upgrade/osd:/opt/lib:/opt/lib_upgrade/ceph-common:/opt/lib:/opt/lib/ceph:/opt/lib/ceph/erasure-code:/opt/lib/ceph/compressor:/opt/lib/ceph/crypto:/opt/lib/rados-classes:/opt/lib_upgrade_reserve/ceph]
 0x000000000000000c (INIT)               0x34ffe0
 0x000000000000000d (FINI)               0xddee2c
……

仔细查阅寻找之后发现,CMake里面维护了3个比较重要的RPATH变量,即CMAKE_SKIP_RPATH,CMAKE_SKIP_BUILD_RPATH,CMKAE_INSTALL_RPATH.

CMAKE_SKIP_RPATH,简单说,就是强制CMake不在构建期间安装install期间给你加上它所认为的RPATH.

cmake .. -DCMAKE_SKIP_RPATH=TRUE或CMakelist中加set(CMAKE_SKIP_BUILD_RPATH TRUE)

   第二个和第三个变量也比较简单,就是分别在构建期间安装期间不允许CMake给你加入相关RPATH

cmake .. -DCMAKE_SKIP_BUILD_RPATH=TRUE 或CMakelist中加set(CMAKE_SKIP_BUILD_RPATH=TRUE)
cmake .. -DCMAKE_SKIP_INSTALL_RPATH=TRUE 或CMakelist中加set(CMAKE_SKIP_INSTALL_RPATH=TRUE)

当然了,如果你之后想要追加RPATH,只需要对这三个变量设置成FALSE就可以了。

再谈CMake与RPATH()https://www.cnblogs.com/rickyk/p/3884257.html再谈CMake与RPATH():
 

CMake为了方便用户的安装,默认在make install之后会自动remove删除掉相关的RPATH,如果我们在运行环境上有个目录:${CMAKE_INSTALL_PREFIX}/lib,我们希望执行make install 之后,RPATH可以自动添加它,我们就可以这么写

set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)

需要注意的是,这个变量是全局变量,意味着你所有的target的RPATH都会在install的时候被写成这个

有没有简单的针对某个target呢,聪明的你应该已经想到了
set_target_properties(myexe PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")

这样就可以保证只针对当前的target进行make install的时候RPATH的写入了。

(扩展:已经生成的可执行文件的RPATH可以用patchelf  工具修改https://blog.csdn.net/bandaoyu/article/details/113181179)

#指定链接时动态库的路径

###################################################################################################################
set(OPENCV_DYNAMIC_LIBS  "${CMAKE_CURRENT_SOURCE_DIR}/../lib")       # 动态 opencv native 库路径
add_library(libopencv_core SHARED IMPORTED )
set_target_properties(libopencv_core PROPERTIES   IMPORTED_LOCATION "${OPENCV_DYNAMIC_LIBS}/libopencv_core.so")
add_library(libopencv_highgui SHARED IMPORTED )
set_target_properties(libopencv_highgui PROPERTIES   IMPORTED_LOCATION "${OPENCV_DYNAMIC_LIBS}/libopencv_highgui.so")
add_library(libopencv_imgproc SHARED IMPORTED )
set_target_properties(libopencv_imgproc PROPERTIES   IMPORTED_LOCATION "${OPENCV_DYNAMIC_LIBS}/libopencv_imgproc.so")
add_library(libopencv_video SHARED IMPORTED )
set_target_properties(libopencv_video PROPERTIES   IMPORTED_LOCATION "${OPENCV_DYNAMIC_LIBS}/libopencv_video.so")

set(mOpenCV_LIBS  libopencv_core libopencv_highgui  libopencv_imgproc libopencv_video)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp ")
target_link_libraries(main ${mOpenCV_LIBS} )

类似上面,添加好所有需要的库,链接的时候就能找得到自定义路径lib下面的库了

linux cmake分别指定编译/运行时动态库链接路径:https://blog.csdn.net/JCYAO_/article/details/102519998

set_target_properties 设置目标属性语法是列出您要更改的所有文件,然后提供您接下来要设置的值。

set_target_properties:https://cmake.org/cmake/help/v3.0/command/set_target_properties.html?highlight=set_target_properties

cmake会先到*_DIR里指定.cmake文件里去找找不到了才会到/usr里去找

所以要小心cmake给你找的文件,如果在一台电脑里装了不止一个版本库(或:多个版本的源码编译后把库放到环境公共目录下)。

什么是RPATH?

程序运行时,搜索动态库的顺序(优先级)优先级是这样的:

1. RPATH ,编译链接时加入 -rpath 参数 指定的目录
2. LD_LIBRARY_PATH  这个环境变量指定的目录
3. /etc/ld.so.conf 配置文件。
4. /usr/lib 、 /lib 和 /usr/local/lib ,系统默认路径。

#其实在Linux环境下,使用动态链接的程序会先链接 ld.so 这个库(OS X上是 dyld),然后通过 ld.so 来查找链接其它的库。

Cmake和RPATH

部署程序到机器上后,程序依赖的动态库 机器上的系统内不一定会有,或者自带了的版本不对,所以一般会在程序文件夹内附带其依赖的链接库,所以最好还是把 RPATH 加上。

Cmake对RPATH提供了很多选项支持,我们一般只关注这几个变量就好了:

CMAKE_SKIP_BUILD_RPATH  (就是不在 可执行文件里面添加Cmake自认为的 RPATH)
CMAKE_BUILD_WITH_INSTALL_RPATH (build的时候连接动态库时去INSTALL_RPATH下去找
CMAKE_INSTALL_RPATH (上面的INSTALL_RPATH的值,就用这个啦设置
CMAKE_INSTALL_RPATH_USE_LINK_PATH (用LINK_PATH的值给INSTALL_RPATH

不使用Cmake默认RPATH设置,加上完整的RPATH

Cmake默认RPATH设置是这样的:

set(CMAKE_SKIP_BUILD_RPATH FALSE)            # FALSE-->设定编译时加上要RPATH
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)    # FALSE-->编译时RPATH不使用INSTALL_RPATH
set(CMAKE_INSTALL_RPATH "")                  # 设置INSTALL_RPATH为空
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) # FALSE-->INSTALL_RPATH不使用LINK_PATH,安装的执行文件不加上RPATH

Cmake在默认情况下, make install 会把安装的执行文件的 RPATH 删掉的(即执行文件搜索动态库是不是去RPATH 找),所以就会出现上面我执行安装好的执行文件报错的问题。

Cmake的默认设置我们肯定是不能使用的,我们需要安装的时候也要带上 RPATH 的设置。

set(INSTALL_LIB_DIR "${PROJECT_BINARY_DIR}/lib") # 假设安装目录在编译目录的lib子目录内
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

# 确保链接库不在 系统默认安装的目录 上时更改到项目lib上

list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES ${CMAKE_INSTALL_RPATH} isSystemDir)
if("${isSystemDir}" STREQUAL "-1")
set(CMAKE_INSTALL_RPATH "${INSTALL_LIB_DIR}")
endif("${isSystemDir}" STREQUAL "-1")

cmake install 和打包设定

cmake应用:安装和打包:https://zhuanlan.zhihu.com/p/377131996

CMakeLists.txt单行注释和多行注释

单行注释:使用“#”多行注释:使用“#[[ ]]”以下图为例

【cmake】CMakeList添加库|添加头文件|添加路径|add_executable、add_library、target_link_libraries|添加编译选项|宏开关_第8张图片

 

小伙子看完文章了,很努力呀,给你整点福利: 

【cmake】CMakeList添加库|添加头文件|添加路径|add_executable、add_library、target_link_libraries|添加编译选项|宏开关_第9张图片

你可能感兴趣的:(C/C++,管理,文档,cmake)