Cmakelists 使用 gcc/g++

转载 https://blog.csdn.net/afei__/article/details/81201039

常用变量

预定义变量

PROJECT_SOURCE_DIR:工程的根目录
PROJECT_BINARY_DIR:运行 cmake 命令的目录,通常是 ${PROJECT_SOURCE_DIR}/build
PROJECT_NAME:返回通过 project 命令定义的项目名称
CMAKE_CURRENT_SOURCE_DIR:当前处理的 CMakeLists.txt 所在的路径
CMAKE_CURRENT_BINARY_DIR:target 编译目录
CMAKE_CURRENT_LIST_DIR:CMakeLists.txt 的完整路径
CMAKE_CURRENT_LIST_LINE:当前所在的行
CMAKE_MODULE_PATH:定义自己的 cmake 模块所在的路径,SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake),然后可以用INCLUDE命令来调用自己的模块
EXECUTABLE_OUTPUT_PATH:重新定义目标二进制可执行文件的存放位置
LIBRARY_OUTPUT_PATH:重新定义目标链接库文件的存放位置

环境变量

使用环境变量

 $ENV{Name}

写入环境变量

 set(ENV{Name} value) # 这里没有“$”符号

系统信息

CMAKE_MAJOR_VERSION:cmake 主版本号,比如 3.4.1 中的 3
­CMAKE_MINOR_VERSION:cmake 次版本号,比如 3.4.1 中的 4
­CMAKE_PATCH_VERSION:cmake 补丁等级,比如 3.4.1 中的 1
­CMAKE_SYSTEM:系统名称,比如 Linux-­2.6.22
­CMAKE_SYSTEM_NAME:不包含版本的系统名,比如 Linux
­CMAKE_SYSTEM_VERSION:系统版本,比如 2.6.22
­CMAKE_SYSTEM_PROCESSOR:处理器名称,比如 i686
­UNIX:在所有的类 UNIX 平台下该值为 TRUE,包括 OS X 和 cygwin
­WIN32:在所有的 win32 平台下该值为 TRUE,包括 cygwin

主要开关选项

BUILD_SHARED_LIBS:这个开关用来控制默认的库编译方式,如果不进行设置,使用 add_library 又没有指定库类型的情况下,默认编译生成的库都是静态库。如果 set(BUILD_SHARED_LIBS ON) 后,默认生成的为动态库
CMAKE_C_FLAGS:设置 C 编译选项,也可以通过指令 add_definitions() 添加
CMAKE_CXX_FLAGS:设置 C++ 编译选项,也可以通过指令 add_definitions() 添加

指定编译器

#使用默认的编译器
# SET(CMAKE_C_COMPILER "gcc")
# SET(CMAKE_CXX_COMPILER "g++")

#使用指定的编译器
# SET(CMAKE_C_COMPILER "/usr/local/bin/gcc")
# SET(CMAKE_CXX_COMPILER "/usr/local/bin/g++")

添加数学库 pthread

target_link_libraries 的时候直接添加 m pthread

target_link_libraries(test
m # 数学库
pthread #pthread
)

主要编写步骤

在当前工程文件夹下创建 CMakeLists.txt

#指定 cmake 的最小版本
cmake_minimum_required(VERSION 3.4.1)
#项目名称
project(demo)
//添加自定义的cmake文件
list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

add_executable(demo demo.cpp) # 生成可执行文件
#add_library(common STATIC util.cpp) # 生成静态库
#add_library(common SHARED util.cpp) # 生成动态库或共享库
#指定生成库的需要用的cpp文件
add_library(demo STATIC demo.cpp test.cpp util.cpp)
aux_source_directory(. SRC_LIST) # 搜索当前目录下的所有.cpp文件
add_library(demo ${SRC_LIST})
{
自定义搜索规则
file(GLOB SRC_LIST "*.cpp")
file(GLOB SRC_PROTOCOL_LIST "protocol/*.cpp")
add_library(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST})
}

find_library( # Sets the name of the path variable.
              log-lib
 
              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )
#设置包括的头文件
include_directories(
        ${CMAKE_CURRENT_SOURCE_DIR}
        ${CMAKE_CURRENT_BINARY_DIR}
        ${CMAKE_CURRENT_SOURCE_DIR}/include
 )
 
#设置搜索的库目录
link_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}/libs
)
target_link_libraries( # 目标库
                       demo
 
                       # 目标库需要链接的库
                       # log-lib 是上面 find_library 指定的变量名
                       ${log-lib} )
#设置变量
set(SRC_LIST main.cpp test.cpp)
#追加变量
set(SRC_LIST ${SRC_LIST} test.cpp)
##追加或者删除变量
list(APPEND SRC_LIST test.cpp)
list(REMOVE_ITEM SRC_LIST main.cpp)
add_executable(demo ${SRC_LIST})

当前工作文件夹创建build文件夹

mkdir build
cd build
执行cmake 命令
cmake ..

find_package 基本原理

https://blog.csdn.net/sen873591769/article/details/90183015
如果我们在cmake某个程序的时候,经常会提示找不到某个所依赖的库,那么这是时候我们就需要检查我们引入依赖库的路径对不对了, Cmake中一个自动寻找函数find_package()可以帮我们实现这个功能。

概括来说,以opencv为例:find_package()函数,如果找到了相关的头文件和库文件,则会相应保存在OpenCV_INCLUDE_DIRS 和OpenCV_LIBRARIES (OpenCV_LIBS) 中。
我们可以输出一下看看上面两个cmake变量是什么内容,在上述文件后面加如下

//以slam十四讲中的joinMap程序Cmake文件为例:
cmake_minimum_required( VERSION 2.8 )
project( joinMap )

set( CMAKE_BUILD_TYPE Release )
set( CMAKE_CXX_FLAGS "-std=c++11 -O3" )

# opencv 
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )

# eigen 
include_directories( "/usr/include/eigen3/" )

# pcl 
find_package( PCL REQUIRED COMPONENT common io )
include_directories( ${PCL_INCLUDE_DIRS} )
add_definitions( ${PCL_DEFINITIONS} )

list(REMOVE_ITEM PCL_LIBRARIES "vtkproj4")
add_executable( joinMap joinMap.cpp )
target_link_libraries( joinMap ${OpenCV_LIBS} ${PCL_LIBRARIES} )


message("!!!!!!!!OpenCV_INCLUDE_DIRS:" ${OpenCV_INCLUDE_DIRS})
message("!!!!!!!!OpenCV_LIBRARIES:" ${OpenCV_LIBRARIES} )

关键字解析

version和EXACT: 都是可选的,version指定的是版本,如果指定就必须检查找到的包的版本是否和version兼容。如果指定EXACT则表示必须完全匹配的版本而不是兼容版本就可以。
QUIET 可选字段,表示如果查找失败,不会在屏幕进行输出(但是如果指定了REQUIRED字段,则QUIET无效,仍然会输出查找失败提示语)。
MODULE可选字段。前面提到说“如果Module模式查找失败则回退到Config模式进行查找”,但是假如设定了MODULE选项,那么就只在Module模式查找,如果Module模式下查找失败并不回落到Config模式查找。
CONFIG可选字段。直接在Config模式中查找。下文会介绍什么是Moudule模式什么是Config模式。
REQUIRED可选字段。表示一定要找到包,找不到的话就立即停掉整个cmake。而如果不指定REQUIRED则cmake会继续执行。
COMPONENTS:可选字段,表示查找的包中必须要找到的组件(components),如果有任何一个找不到就算失败,类似于REQUIRED,导致cmake停止执行。上面的例子中find_package( PCL REQUIRED COMPONENT common io )我们就利用了该关键字寻找了common和io包。
OPTIONAL_COMPONENTS:可选的模块,找不到也不会让cmake停止执行。

find_package原理

首先,cmake本身不提供任何搜索库的便捷方法,所有搜索库并给变量赋值的操作必须由cmake代码完成,比如FindXXX.cmake和XXXConfig.cmake。只不过,库的作者通常会提供这两个文件,以方便使用者调用。
find_package采用两种模式搜索库:

Module模式:搜索CMAKE_MODULE_PATH指定路径下的FindXXX.cmake文件,执行该文件从而找到XXX库。其中,具体查找库并给XXX_INCLUDE_DIRS和XXX_LIBRARIES两个变量赋值的操作由FindXXX.cmake模块完成(先搜索当前项目里面的Module文件夹里面提供的FindXXX.cmake,然后再搜索系统路径/usr/local/share/cmake-x.y/Modules/FindXXX.cmake)
Config模式:搜索XXX_DIR指定路径下的XXXConfig.cmake文件,执行该文件从而找到XXX库。其中具体查找库并给XXX_INCLUDE_DIRS和XXX_LIBRARIES两个变量赋值的操作由XXXConfig.cmake模块完成。
对于可能没有***.cmake和***Config.cmake的库文件,可以直接找到其头文件和库文件所在文件夹,直接进行路径赋值:

link_directories

这种情况下会出错,说找不到引用,原因是ADD_EXECUTABLE出现在LINK_DIRECTORIES之前。正确的做法是将LINK_DIRECTORIES放在ADD_EXECUTABLE之前。

LINK_DIRECTORIES(/tmp/t3/lib)

ADD_EXECUTABLE(main main.cpp)

TARGET_LINK_LIBRARIES(main libhello.so)

INCLUDE_DIRECTORIES(/tmp/t3/include/hello /tmp/t3/lib)

link_directories, LINK_LIBRARIES, target_link_libraries的区别
INCLUDE_DIRECTORIES(添加头文件目录)
LINK_DIRECTORIES(添加需要链接的库文件目录)
LINK_LIBRARIES (添加需要链接的库文件路径,注意这里是全路径)
TARGET_LINK_LIBRARIES (设置要链接的库文件的名称)

target_link_libradies

g++ 使用这个可以
target_link_libraries(test
m # 默认 = -lm
-pthread #pthread
libqxwz-pssdk-1.9.1-20210425-qa-x86-64-linux-gcc-4.8.4-default-production-release.a
)
gcc 使用
target_link_libraries(test
m # 默认 = -lm
pthread #pthread
libqxwz-pssdk-1.9.1-20210425-qa-x86-64-linux-gcc-4.8.4-default-production-release.a
)

gcc g++ 区别

gcc和g++的区别总结:
gcc: GNU C Compiler
g++: GNU C++ Compiler

共同点:
均属于the GNU Compiler Collection,gcc是鼻祖,后来才有了g++

g++ == gcc -xc++ -lstdc++ -shared-libgcc

(gcc后面两项都是链接选项,表示g++要相比gcc链接其他库函数)

差异点:

1.g++会自动链接C++标准库,比如algorith,string,vector等。
2.gcc会根据文件后缀(.c,.cpp)自动识别是C文件还是C++文件,g++均认为是C++文件。
3.gcc编译C文件少很多宏定义,gcc编译C++会多一些宏定义。
如下:

#define GXX_WEAK 1
#define __cplusplus 1
#define __DEPRECATED 1
#define GNUG 4
#define __EXCEPTIONS 1
#define private_extern extern

g++ -lpthread 会失败

应该写成g++ -pthread

gcc 生成静态库动态库

三、GCC生成动态库和静态库

1)动态库生成
1.单个源文件/目标直接生成动态库

a.
gcc -fPIC -shared xxx.c -o libxxx.so
b.
gcc -fPIC -shared xxx.o -o libxxx.so

2.多个源文件/目标生成动态库

a.
gcc -fPIC -shared xxx1.c xxx2.c xxx3.c -o libxxx.so
b.
gcc -fPIC -shared xxx1.o xxx2.o xxx3.o -o libxxx.so

2)静态库生成
1.单个源文件/目标直接生成静态库

a.
ar -rc libxxx.a xxx.o(正确方法)
b. ar -rc libxxx.a xxx.c (静态库可以生成;当运行连接了该静态库的可执行程序会报错:could not read symbols:Archive has no index;run ranlib
to add one)

2.多个源文件/目标生成静态库

a.
ar -rc libxxx.a xxx1.o xxx2.o xxx3.o (正确方法)
b.
ar -rc libxxx.a xxx1.c xxx2.c xxx3.c (静态库可以生成;当运行连接了该静态库的可执行程序会报错:could not read symbols:Archive has no index;run ranlib to add one)

四、多个源文件生成一个可执行文件

gcc xxx1.c xxx2.c xxx3.c xxx4.c main.c -o main

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值