linux用cmake编译,CMake使用简介(forLinux)

cmake [选项]

cmake [选项]

因为source 目录在../  所以指定../为源码目录。

-G:指定构建系统,当前只想创建Linux/Unix系统标准Makefile。所以指定为Unix

Makefile.

具体支持何种构建系统:man

cmake

可以看到类似入下内容:

Generators

The following generators are available

on this platform:

Ninja

= Generates build.ninja files

(experimental).

Unix Makefiles

= Generates standard UNIX makefiles.

CodeBlocks - Ninja

= Generates CodeBlocks project

files.

CodeBlocks - Unix

Makefiles = Generates CodeBlocks project files.

Eclipse CDT4 -

Ninja  = Generates Eclipse CDT 4.0 project files.

Eclipse CDT4 - Unix

Makefiles

= Generates Eclipse CDT 4.0 project files.

KDevelop3

=

Generates KDevelop 3 project files.

KDevelop3 - Unix

Makefiles  = Generates KDevelop 3 project

files.

这个CMakeLists.txt

内容中,构成可执行文件的文件个数很少,但如果源文件很多,则最好如Makefile中一样,指定一个源文件列表:

cmake_minimum_required (VERSION 2.6)

project (V4L2_Utils)

set (SRC_LIST main.cpp v4l2_util.cpp tran_data.cpp)

message (${SRC_LIST})

add_executable(V4L2_Utils ${SRC_LIST})

(注1)

1.2:

编译一个静态库,并使用这个静态库和main.cpp,最终再生成一个可执行程序:

即先生成libv4l2_utils.a.

main.cpp使用libv4l2_utils.a中的符号并最终生成V4L2_Utils.

CMakeLists.txt:

cmake_minimum_required (VERSION

2.6)

project (V4L2_Utils)

set (LIB_SRC_LIST

v4l2_util.cpp tran_data.cpp)

set (EXEC_SRC_LIST

main.cpp)

add_library(V4L2_Utils STATIC

${LIB_SRC_LIST})

add_executable(Test_V4L2

${EXEC_SRC_LIST})

target_link_libraries(Test_V4L2

V4L2_Utils)

说明:

add_library( [STATIC | SHARED |

MODULE][EXCLUDE_FROM_ALL]source1 source2 ... sourceN)

创建一个名为 name 的库文件,STATIC,

SHARED指定为静态或动态库。

库文件由源文件列表生成。

add_library(V4L2_Utils STATIC

${LIB_SRC_LIST})

生成一个静态库libV4l2_Utils.a 由v4l2_util.cpp tran_data.cpp生成

add_executable(Test_V4L2 ${EXEC_SRC_LIST})

可执行程序由哪些.o组成。

target_link_libraries(Test_V4L2 V4L2_Utils)

可执行程序Test_V4L2需要链接库V4L2_Utils

target_link_libraries( [item1 [item2 [...]]]

[[debug|optimized|general] ] ...)

将给定的库链接到目标target上。

1.3:

编译一个动态库,并使用这个动态和main.cpp,最终再生成一个可执行程序:

cmake_minimum_required (VERSION

2.6)

project (V4L2_Utils)

set (LIB_SRC_LIST

v4l2_util.cpp)

set (EXEC_SRC_LIST

main.cpp)

add_library(V4L2_Utils SHARED

${LIB_SRC_LIST})

add_executable(Test_V4L2

${EXEC_SRC_LIST})

target_link_libraries(Test_V4L2

V4L2_Utils)

只变化了STATIC-->SHARED

1.4:

指定include 路径:

main.cpp中,需要include "v4l2_util.h"

但这个头文件并不在src目录内,而是在include目录

include,

src为同级别目录。则main.cpp会找不到头文件。

所以,实际的CMakeLists.txt文件写法为:

cmake_minimum_required (VERSION

2.6)

project (V4L2_Utils)

set (LIB_SRC_LIST

v4l2_util.cpp)

set (EXEC_SRC_LIST

main.cpp)

set

(INCLUDE_DIRECTORIES ../include)

include_directories(${INCLUDE_DIRECTORIES})

add_library(V4L2_Utils SHARED

${LIB_SRC_LIST})

add_executable(Test_V4L2

${EXEC_SRC_LIST})

target_link_libraries(Test_V4L2

V4L2_Utils)

将头文件目录添加进去。

1.5:

添加第三方库和库路径:

如果libV4L2.so是以第三方库形式出现。不需要编译,它放在resource目录下。则需要制定搜索库路径

cmake_minimum_required

(VERSION 2.6)

project

(V4L2_Utils)

set (EXEC_SRC_LIST

main.cpp)

set (INCLUDE_DIRECTORIES

../include)

set (LINK_DIR

../../resource)

include_directories(${INCLUDE_DIRECTORIES})

link_directories(${LINK_DIR})

add_executable(Test_V4L2

${EXEC_SRC_LIST})

target_link_libraries(Test_V4L2

V4L2_Utils)

说明:

link_directories 指定连接器查找库的路径。

link_directories(directory1 directory2

...)

1.6:创建Release和Debug版本:

#set (CMAKE_BUILD_TYPE Release)

set (CMAKE_BUILD_TYPE Debug)

分别指定为Release或者Debug模式。区别在于:

Release: -O3

-DNDEBUG

Debug:-g

也可以不加在txt内。在产生Makefile时才加入:

cmake -DCMAKE_BUILD_TYPE=Release

1.7:

增加编译和链接选项:

CMAKE_C_FLAGS

CMAKE_CXX_FLAGS

CMAKE_EXE_LINKER_FLAGS

分别相当于:CFLAGS, CXXFLAGS, LDFLAGS。

set (CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS}

-DEMBED")

这种写法的好处是,不会覆盖CMAKE_CXX_FLAGS本来的信息。只是把需要添加的内容添加进去。

1.8:

多目录结构的cmake 使用:

V4L2_Utils实际的目录结构其实并不是所有源码都存放在src目录内。

它的目录结构是:

src: 存放生成库的源码。v4l2_util.cpp,

tran_data.cpp

test:存放使用库的测试程序: main.cpp

include: 存放头文件: v4l2_util.h

resource: 存放第三方库

build:存放编译过程的文件

build/lib: 存放生成的libv4l2_utils.so

build/bin:存放main.cpp所产生的测试程序可执行文件。

此时,可以采用顶层目录和每个有源码的目录中均创建CMakeLists.txt的方式来处理(和Makefile处理方式类似)

顶层目录的CMakeLists.txt 内容如下:

cmake_minimum_required (VERSION

2.6)

project (V4L2_Utils)

add_subdirectory(src lib)

add_subdirectory(test bin)

说明:

add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

构建添加一个子路径。source_dir选项指定了CMakeLists.txt源文件和代码文件的位置。如果source_dir是一个相对路径,那么source_dir选项会被解释为相对于当前的目录,但是它也可以是一个绝对路径。binary_dir选项指定了输出文件的路径。如果binary_dir是相对路径,它将会被解释为相对于当前输出路径。

请注意两个相对路径的不同。因为Sam是在Build目录内执行cmake

..

source_dir算相对路径时,是从CMakeLists.txt算起。

所以src指的是当前 CMakeLists.txt所在路径下的src.

而bin, lib 指的是当前输出路径下的bin,lib. 也就是build/bin

build/lib

src

CMakeLists.txt :

set (LIB_SRC_LIST

v4l2_util.cpp)

set (CMAKE_BUILD_TYPE

Release)

include_directories(../include)

add_library(V4L2_Utils SHARED

${LIB_SRC_LIST})

test

CMakeLists.txt :

set (EXEC_SRC_LIST

main.cpp)

set (INCLUDE_DIRECTORIES

../include)

set (LINK_DIR

../../resource)

set (LINK_DIR "${LINK_DIR}

../../libs/")

set (CMAKE_BUILD_TYPE

Release)

include_directories(${INCLUDE_DIRECTORIES})

link_directories(${LINK_DIR})

add_executable(Test_V4L2

${EXEC_SRC_LIST})

target_link_libraries(Test_V4L2

V4L2_Utils)

这个做法一直不满意,其实有更好的做法

总结:

有了以下这些选项,写过Makefile的人可以很容易的使用CMake了。

生成可执行程序:

add_executable(Test_V4L2

${EXEC_SRC_LIST})

生成静态库

add_library(V4L2_Utils STATIC

${LIB_SRC_LIST})

生成动态库:

add_library(V4L2_Utils SHARED

${LIB_SRC_LIST})

指定头文件路径:  -I

include_directories(${INCLUDE_DIRECTORIES})

指定库文件路径:

-L

link_directories(${LINK_DIR})

指定链接库:

-l

target_link_libraries(Test_V4L2

V4L2_Utils)

CFLAGS,CXXFLAGS,LDFLAGS:

CMAKE_C_FLAGS,CMAKE_CXX_FLAGS,CMAKE_EXE_LINKER_FLAGS

2. Debug和Release版本:

关键在于三个CMake设置:

CMAKE_BUILD_TYPE

CMAKE_CXX_FLAGS_DEBUG

CMAKE_CXX_FLAGS_RELEASE

当CMAKE_BUILD_TYPE设置为Debug。

则编译时采用CMAKE_CXX_FLAGS_DEBUG。

当CMAKE_BUILD_TYPE设置为Release。

则编译时采用CMAKE_CXX_FLAGS_RELEASE

cmake_minimum_required (VERSION

2.6)

project (CMAKE_Test)

add_executable(CMAKE_Test

src/banchmark.cpp)

#set(CMAKE_BUILD_TYPE Debug)

set(CMAKE_BUILD_TYPE Release)

set(CMAKE_CXX_FLAGS_DEBUG

"$ENV{CXXFLAGS} -O0 -Wall -g -ggdb

-Wno-unused-but-set-variable")

set(CMAKE_CXX_FLAGS_RELEASE

"$ENV{CXXFLAGS} -O3 -Wall -Wno-unused-but-set-variable")

3. CMake的交叉编译:

CMake是用来生成Makefile的,如果要交叉编译,需要告知CMake以下信息:

A. 当前是交叉编译。

B. 所用C/C++编译器。

C. 头文件,库文件目录,CFlags等。

#告知当前使用的是交叉编译方式,必须配置

SET(CMAKE_SYSTEM_NAMELinux)

#指定编译工具,一定要设置

#或交叉编译器使用绝对地址

SET(CMAKE_C_COMPILER"arm-linux-gcc")

#指定C++交叉编译器

SET(CMAKE_CXX_COMPILER"arm-linux-g++")

#不一定需要设置

#指定交叉编译环境安装目录...

SET(CMAKE_FIND_ROOT_PATH "...")

#从来不在指定目录下查找工具程序

SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

#只在指定目录下查找库文件

SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)

#只在指定目录下查找头文件

SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

3.2:第三方库交叉编译实例:

思路:创建一个设置交叉编译的 xxx.cmake. 例如:ndk_clang.cmake, 或者armv7a.cmake. 用来分别针对NDK的clang编译器和ARMv7a指令集编译器。如此,则可以大致不修改CMakeLists.txt的同时,适配多种交叉编译平台。

然后在官方CMakeLists.txt中,include (xxx.cmake),注意,一定要include到project()后。

如:

project(libjpeg-turbo C)

set(VERSION 2.0.4)

include (ndk_sam_clang.cmake)

下面是ndk_sam_clang.cmake内容:

SET(CROSS_COMPILE 1)

IF(CROSS_COMPILE)

set(CMAKE_SYSTEM_NAME Linux)

set(NDK_PATH "/opt/android-ndk-r15c")

set(BUILD_TOOL "llvm")

set(BUILD_PLATFORM "linux-x86_64")

set(ANDROID_PLATFORM "android-23")

SET(TOOLCHAIN_DIR ${NDK_PATH}/toolchains/${BUILD_TOOL}/prebuilt/${BUILD_PLATFORM})

set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/bin/clang++)

message (${CMAKE_CXX_COMPILER})

set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/bin/clang)

set(GNU_FLAGS "-mfloat-abi=softfp -mfpu=vfpv3-d16")

set(CMAKE_CXX_FLAGS "${GNU_FLAGS} ")

set(CMAKE_C_FLAGS "${GNU_FLAGS} ")

set(CMAKE_SYSTEM_PROCESSOR "arm")

SET(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_DIR}

${NDK_PATH}/platforms/${ANDROID_PLATFORM}/arch-arm/include

${NDK_PATH}/platforms/${ANDROID_PLATFORM}/arch-arm/lib )

message("CMAKE__SYSTEM_PROCESSOR:" ${CMAKE_SYSTEM_PROCESSOR} )

ENDIF(CROSS_COMPILE)

注1:set

和message

set用来指定变量

如:

set (SRC_LIST main.cpp)

则变量SRC_LIST内容为main.cpp

${SRC_LIST} 则为取变量内容(与Bash类似)

message:用来显示变量

message (${SRC_LIST})

注2:

如何显示编译细节:

方法1:

在CMakeLists.txt中,

set(CMAKE_VERBOSE_MAKEFILE ON)

方法2:

有时不希望修改CMakeLists.txt文件,则可以在创建Makefile时加入:

cmake -DCMAKE_VERBOSE_MAKEFILE=ON

方法3:

有时连Makefile都不希望修改:

make VERBOSE=1

注2:相对路径问题:

set (LIBRARY_DIRECTORIES

../resource)

link_directories(${LIBRARY_DIRECTORIES})

这里会出警告:

This command specifies the relative

path

../resource

可以做如下处理:

set (LIBRARY_DIRECTORIES

../resource)

link_directories(${CMAKE_CURRENT_SOURCE_DIR}/${LIBRARY_DIRECTORIES})

注3:

https://cmake.org/

注4:

find_package()功能讲解:

例如:

find_package(Qt5Widgets)

可以被用来在系统中自动查找配置构建工程所需的程序库。在linux和unix类系统下这个命令尤其有用。CMake自带的模块文件里有大半是对各种常见开源库的find_package支持,支持库的种类非常多.

find_package( [version] [EXACT] [QUIET]

[[REQUIRED|COMPONENTS] [components...]]

[NO_POLICY_SCOPE])

查找并加载外来工程的设置。该命令会设置_FOUND变量,用来指示要找的包是否被找到了。如果这个包被找到了,与它相关的信息可以通过包自身记载的变量中得到。REQUIRED选项表示如果报没有找到的话,cmake的过程会终止,并输出警告信息

在REQUIRED选项之后,或者如果没有指定REQUIRED选项但是指定了COMPONENTS选项,在它们的后面可以列出一些与包相关的部件清单(components list)。

FIND_PACKAGE

每一个模块都会产生如下变量

_FOUND

_INCLUDE_DIR

_LIBRARY or _LIBRARIES

如果_FOUND为真,把_INCLUDE_DIR加入到INCLUDE_DIRECTORIES中,_LIBRARY加入到TARGET_LINK_LIBRARIES中。

就会有变量Qt5Widgets_FOUND,Qt5Widgets_INCLUDE_DIRS等相应的变量生效。

例如:

find_package(catkin REQUIRED

COMPONENTS

roscpp

rospy

std_msgs)

如果找到catkin package. 则catkin_FOUND

被设置为true. catkin_INCLUDE_DIRS, catkin_LIBRARIES 被设置。

如果没找到,因为有REQUIRED. 所以会抱错。

注5:

pkg_check_modules讲解:

pkg_check_modules( [REQUIRED]

[]*)

检测所有给出的modules

pkg_check_modules(PC_OPENNI2 libopenni2)

if (NOT PC_OPENNI2_FOUND)

pkg_check_modules(PC_OPENNI2 REQUIRED openni2)

endif()

PC_OPENNI2_INCLUDE_DIRS, PC_OPENNI2_LIBRARY_DIRS 等被设置。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值