跳转至

cmake

导言

ipcc初赛的项目代码有些混乱,只是简单分类。想好好学习一下cmake和make。规范项目结构,优化编译运行流程,提高效率。

cmake简介

CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。

自动生成CMakeLists.txt

ccmake

sudo apt-get install cmake-curses-gui
ccmake ..

打印详细编译信息

  • 方法1: 执行命令cmake时追加:-DCMAKE_VERBOSE_MAKEFILE=ON
  • 方法2: 在CMakeLists.txt中添加:set(CMAKE_VERBOSE_MAKEFILE ON)
  • 方法3: make时追加: VERBOSE=1

list all option

查看cmake选项

mkdir build
cd build
cmake ..
cmake -LA | awk '{if(f)print} /-- Cache values/{f=1}'
cmake -LAH # adding -H to show more help information about each option

常用选项

-S <path-to-source>          = Explicitly specify a source directory.CMakeLists.txt路径
-B <path-to-build>           = Explicitly specify a build directory.
-DCMAKE_BUILD_TYPE=Debug
-DCMAKE_INSTALL_PREFIX=directory --- Specify for directory the full path name of where you want thetools and libraries to be installed (default /usr/local)

-G <generator> 基于不同平台的makefile生成方式

  • -G "Unix Makefiles"
  • -G "MinGW"
  • 之类的

CMakeList.txt基本语法

# cmake required version
cmake_minimum_required(VERSION 3.0.0)

# more error message
SET( CMAKE_VERBOSE_MAKEFILE on )

#project name
PROJECT(ipcc_test)

# compile
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_C_COMPILER gcc)
set(CMAKE_CXX_COMPILER g++)


# flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O3  -pthread")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O3  -pthread -fopenmp")

#head file path
INCLUDE_DIRECTORIES(include)

#source directory
AUX_SOURCE_DIRECTORY(src DIR_SRCS) # 搜集所有在指定路径下的源文件的文件名,将输出结果列表储存在指定的变量DIR_SRCS中

# message
message(STATUS "PROJECT_SOURCE_DIR is ${PROJECT_SOURCE_DIR}")
message(STATUS "PROJECT_BINARY_DIR is ${PROJECT_BINARY_DIR}")
message(STATUS "CMAKE_CURRENT_SOURCE_DIR is ${CMAKE_CURRENT_SOURCE_DIR}")

#output path
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

#set environment variable
SET(TEST ${DIR_SRCS})  # 此处用于显示如何用环境变量对环境变量进行赋值


#add target/final executable file
ADD_EXECUTABLE(./bin/exe ${TEST})

# 指定最后生成类似.so的文件
add_library(${PLUGIN_NAME} SHARED ${CPP_SRCS})

# 继续构建的子目录
add_subdirectory(dir)

链接库

# add lib path to search lib file
link_directories(${CMAKE_SOURCE_DIR}/lib)

add_executable(foo ${FOO_SRCS})

#set extern libraries
SET(LIBRARIES LIBRARIESlibm.so)

#add link library
TARGET_LINK_LIBRARIES(../bin/bin ${LIBRARIES})
target_link_libraries(foo bar) # libbar.so is found in ${CMAKE_SOURCE_DIR}/lib

多级目录编译

CMakeLists.txt*.cpp一定会被变量包含AUX_SOURCE_DIRECTORY或者FILE,然后跨层传递add_subdirectory,变量组合SET,直至被添加到可执行文件ADD_EXECUTABLE或者add_library

上一层CMakeLists.txt
set(exampleDIR "xxx")

# pre-define
set(dir1_srcs)
set(dir2_srcs)
set(dir3_srcs)

# cmake in subdir (重要)
add_subdirectory(${exampleDIR}/subdir)

SET(CPP_SRCS ${dir1_srcs} ${dir2_srcs} ${dir3_srcs})
add_library(${PLUGIN_NAME} SHARED ${CPP_SRCS})
CMakeLists.txt in ${exampleDIR}/subdir
FILE(GLOB _dir1_srcs *.cpp)

LIST(APPEND dir1_srcs ${_dir1_srcs})

# pass to parent(the CMakeLists.txt using add_subdirectory)
SET(dir1_srcs ${dir1_srcs} PARENT_SCOPE)

实例

目录下所有源文件编译成单独的可执行文件

实现头文件、执行文件、源代码都分开存储。

file(GLOB files "*/*.cpp")
foreach (file ${files})
    message(STATUS "file is ${file}")
    string(REGEX REPLACE ".+/(.+)\\..*" "\\1" exe ${file})
    message(STATUS "file name is ${exe}")
    add_executable(${exe} ${file})
    TARGET_LINK_LIBRARIES(${exe} ${CONAN_LIBS})
endforeach ()
string(REGEX REPLACE <regular_expression>
    <replacement_expression> <output_variable>
    <input> [<input>...])

尽可能匹配 <regular_expression> 多次,并用 <replacement_expression> 替换输出中的匹配项。匹配之前将所有 <input> 参数连接在一起。

所述 <replacement_expression> 可以是指使用匹配的括号分隔子表达式 \1 , \2 ,..., \9 。请注意,CMake代码中需要两个反斜杠( \\1 )才能通过参数解析获得反斜杠。同理 \\.是匹配 .的意思。

# Find all main*.cpp files and store in list mains
file(GLOB_RECURSE mains RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/main*.cpp")

foreach(mainfile IN LISTS mains)
    # Get file name without directory
    get_filename_component(mainname ${mainfile} NAME_WE)
    add_executable(${mainname} ${mainfile})
endforeach()
file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/src/ *.c )

foreach( sourcefile IN LISTS APP_SOURCES )
    string( REPLACE ".c" "" program ${sourcefile} )
    add_executable( ${program} ${sourcefile} )
    #target_link_libraries( ${program} zmq )
endforeach( sourcefile )
将指定的文件编译成单独的可执行文件

example code

运行n次并求平均时间

example code

比较时间的Cmake优化小项目

https://github.com/Kirrito-k423/StencilAcc

需要进一步的研究学习

  • 学习Quest cmake 添加openmp的编译选项核compile option

参考文献

https://www.cnblogs.com/lyq105/archive/2010/12/03/1895067.html

https://blog.csdn.net/ET_Endeavoring/article/details/98989066

———————————————— 版权声明:本文为CSDN博主「商汤科技」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq295109601/article/details/118867192