CMake


CMake官网Training Materials:

  • https://cmake.org/cmake/help/latest/guide/tutorial/index.html
  • https://cmake.org/cmake/help/book/mastering-cmake/

CMake官网Reference:https://cmake.org/documentation/

Make官网及文档:

  • http://www.gnu.org/software/make/
  • http://www.gnu.org/software/make/manual/

1. gcc、make和cmake简介

gcc(GNU Compiler Collection)将源文件编译(Compile)成可执行文件或者库文件;

而当需要编译的东西很多时,需要说明先编译什么,后编译什么。常用的工具是make,对应的定义构建(Build)过程的文件为Makefile;

而编写Makefile对于大型项目又比较复杂,通过CMake就可以使用更加简洁的语法定义构建的流程,CMake定义构建过程的文件为CMakeLists.txt。

src
CMakeLists.txt
MakeFile
Make
GCC
Bin

GCC可以换成其它编译器。

CMake提供cmake、ctest和cpack三个命令行工具分别负责构建、测试和打包。本文只关心cmake的使用。

除了makefile,现在cmake也能生成vs和xcode的项目文件。

2. cmake语法

命令文档:https://cmake.org/cmake/help/v3.22/manual/cmake-commands.7.html

CMake语言在项目配置中组织为三种源文件类型:

  • 目录:CMakeLists.txt,针对的是一个目录,描述如何针对目录(Source tree)生成构建系统,会用到项目配置命令;
  • 脚本:

2. cmake变量

PROJECT_BINARY_DIR, PROJECT_SOURCE_DIR

set指令可以设置变量。注意双引号,空格和分号的用法。

${}访问变量。

https://cmake.org/cmake/help/v3.10/manual/cmake-variables.7.html

3. 常用指令

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

一般用message输出信息。

注意不要用逗号来分隔参数!!!

4. 内外部构建

内部构建就是直接cmake . && make,会在当前目录产生很多临时文件。

外部构建需要先创建一个build文件夹,执行mkdir build && cd build && cmake .. && make

一般当然是外部构建。

5. 完整工程

mkdir src && mkdir build && touch COPYRIGHT README && touch doc && touch CMakeLists.txt && touch src/CMakeLists.txt

.
├── build
├── CMakeLists.txt
├── COPYRIGHT
├── doc
│   └── intro.txt
├── README
├── run.sh
└── src
     ├── 1.c
     └── CMakeLists.txt

doc, COPYRIGHT以及README,要拷贝到/usr/share/doc/cmake.

add_subdirectory指令可以指定src和bin目录。

外部CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)

# set the project name
PROJECT(Tutorial)

add_subdirectory(src bin)

MESSAGE(STATUS "Binary dir:" ${PROJECT_BINARY_DIR})
MESSAGE(STATUS "Source dir:" ${PROJECT_SOURCE_DIR})

src下CMakeLists.txt:

# add the executable
add_executable(Tutorial 1.c)

执行cd build && cmake ..,然后build下会生成许多文件,需要关注的是MakeFile。

然后执行make, bin下就会生成Tutorial可执行文件了。

6. 安装

cmake install指令:https://cmake.org/cmake/help/v3.10/command/install.html

cmake其它相关文档:

  • https://cmake.org/cmake/help/v3.10/variable/CMAKE_INSTALL_PREFIX.html
  • https://cmake.org/cmake/help/latest/guide/tutorial/Installing%20and%20Testing.html

几种make安装指令:

make install
make install DESTDIR=/tmp
make install ./configure -prefix=/tmp

make相关文档:http://www.gnu.org/software/make/manual/make.html#Directory-Variables

外部的CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)

# set the project name
PROJECT(Tutorial)

add_subdirectory(src bin)

MESSAGE(STATUS "Binary dir:" ${PROJECT_BINARY_DIR})
MESSAGE(STATUS "Source dir:" ${PROJECT_SOURCE_DIR})

install(FILES COPYRIGHT README DESTINATION share/doc/Tutorial)
install(DIRECTORY doc/ DESTINATION share/doc/Tutorial) # "doc/", not "doc"
install(PROGRAMS run.sh DESTINATION bin)

make之后执行make install

starr@starr-VirtualBox:~/projects/CMakeTest/build$ sudo make install
[sudo] password for starr: 
[100%] Built target Tutorial
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/share/doc/Tutorial/COPYRIGHT
-- Installing: /usr/local/share/doc/Tutorial/README
-- Up-to-date: /usr/local/share/doc/Tutorial
-- Installing: /usr/local/share/doc/Tutorial/intro.txt
-- Installing: /usr/local/bin/run.sh

7. 库

一般lib和src两个文件夹是分开的。lib下面也要有CMakeLists.txt.

add_library指令:https://cmake.org/cmake/help/v3.10/command/add_library.html

lib/libtest.h

#ifndef LIBTEST_H
#define LIBTEST_H

void PrintLib(char* pStr);

#endif

lib/libtest.c

#include <stdio.h>
#include "libtest.h"

void PrintLib(char* pStr)
{
	printf("I am %s\n", pStr);
}

CMakeLists.txt

add_subdirectory(src bin) 

# library
add_subdirectory(lib lib)

需要注意的是,不用的源码目录不能使用同一个binary_dir(因为会冲突), 所以这里生成目录为(build/)lib。

lib/CMakeLists.txt:

# library
set(LIB_SO_SRC libtest.c)	# Using set is a good habit
set(LIB_SO_NAME shared)
add_library(${LIB_SO_NAME} SHARED ${LIB_SO_SRC})
set_target_properties(${LIB_SO_NAME} PROPERTIES OUTPUT_NAME "libtest")
set_target_properties(${LIB_SO_NAME} PROPERTIES CLEAN_DIRECT_OUTPUT 1)
# .so usually has the build and API version
set_target_properties(${LIB_SO_NAME} PROPERTIES VERSION 1 SOVERSION 1) 

set(LIB_STATIC_SRC libtest.c)
set(LIB_STATIC_NAME static)
add_library(${LIB_STATIC_NAME} STATIC ${LIB_STATIC_SRC})
set_target_properties(${LIB_STATIC_NAME} PROPERTIES OUTPUT_NAME "libtest")	# same name as .so
set_target_properties(${LIB_STATIC_NAME} PROPERTIES CLEAN_DIRECT_OUTPUT 1)


# headers
install(FILES libtest.h DESTINATION include/libtest)
# ${CMAKE_INSTALL_PREFIX}/lib
install(TARGETS ${LIB_SO_NAME} 	   LIBRARY DESTINATION lib)
install(TARGETS ${LIB_STATIC_NAME} ARCHIVE DESTINATION lib)

一般一个项目会提供同名的动态库和静态库。

在构建libtest.a时,可能会清理掉libtest.so。set_target_properties可以规避这个问题。

install指令,LIBRARY对应.so,ARCHIVE对应.a。

starr@starr-VirtualBox:~/projects/CMakeTest/build/lib$ sudo make install
[sudo] password for starr: 
[ 50%] Built target static
[100%] Built target shared
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/include/libtest/libtest.h
-- Installing: /usr/local/lib/liblibtest.so.1
-- Installing: /usr/local/lib/liblibtest.so
-- Installing: /usr/local/lib/liblibtest.a

主程序调用

src/1.c:

#include <libtest.h>

int main(int argc, char **argv)
{
    PrintLib("hello");
}

src/CMakeLists.txt也要添加对库的链接:

# add the executable
add_executable(Tutorial 1.c)

target_include_directories(Tutorial PUBLIC
                          ${CMAKE_INSTALL_PREFIX}/${INCLUDE_DIR}
                          )
target_link_libraries(Tutorial liblibtest.a)
# target_link_libraries(Tutorial liblibtest.so)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值