[TOC]
经常会看到的:
#CMake变量使用 ${ }取值
#但是在IF控制语句中是直接使用变量名。
文件内容
cmake_minimum_required(VERSION 3.2)
# 规定cmake软件的版本
#定义一个可在CMake脚本其他位置调用的函数
function(COMPILE_X86_TESTS name address_size has_avx has_avx512)
······
endfunction()
#到endfunction()为止结束,····为函数体内容
function内部
function(COMPILE_X86_TESTS name address_size has_avx has_avx512)
set(X86_TEST_FLAGS
-I${CMAKE_SOURCE_DIR}
-DADDRESS_SIZE_BITS=${address_size}
-DHAS_FEATURE_AVX=${has_avx}
-DHAS_FEATURE_AVX512=${has_avx512}
-DGTEST_HAS_RTTI=0
-DGTEST_HAS_TR1_TUPLE=0
)
add_executable(lift-${name}-tests
EXCLUDE_FROM_ALL
Lift.cpp
Tests.S
)
target_compile_options(lift-${name}-tests
PRIVATE ${X86_TEST_FLAGS} -DIN_TEST_GENERATOR
)
file(GLOB X86_TEST_FILES
"${CMAKE_CURRENT_LIST_DIR}/*/*.S"
)
set_target_properties(lift-${name}-tests PROPERTIES OBJECT_DEPENDS "${X86_TEST_FILES}")
target_link_libraries(lift-${name}-tests PRIVATE remill GTest::gtest)
target_compile_definitions(lift-${name}-tests PUBLIC ${PROJECT_DEFINITIONS})
add_custom_command(
OUTPUT tests_${name}.bc
COMMAND lift-${name}-tests --arch ${name} --bc_out tests_${name}.bc
DEPENDS semantics
)
add_custom_command(
OUTPUT tests_${name}.S
COMMAND ${CMAKE_BC_COMPILER} -Wno-override-module -S -O0 -g0 -c tests_${name}.bc -o tests_${name}.S
DEPENDS tests_${name}.bc
)
add_executable(run-${name}-tests EXCLUDE_FROM_ALL Run.cpp Tests.S tests_${name}.S)
set_target_properties(run-${name}-tests PROPERTIES OBJECT_DEPENDS "${X86_TEST_FILES}")
target_link_libraries(run-${name}-tests PUBLIC remill GTest::gtest)
target_compile_definitions(run-${name}-tests PUBLIC ${PROJECT_DEFINITIONS})
target_compile_options(run-${name}-tests
PRIVATE ${X86_TEST_FLAGS}
)
message(STATUS "Adding test: ${name} as run-${name}-tests")
add_test(NAME "${name}" COMMAND "run-${name}-tests")
add_dependencies(test_dependencies "run-${name}-tests")
endfunction()
逐条解释
#SET命令用于赋值
#CMake变量使用 ${ }取值
set(X86_TEST_FLAGS
-I${CMAKE_SOURCE_DIR}
-DADDRESS_SIZE_BITS=${address_size}
-DHAS_FEATURE_AVX=${has_avx}
-DHAS_FEATURE_AVX512=${has_avx512}
-DGTEST_HAS_RTTI=0
-DGTEST_HAS_TR1_TUPLE=0
)
#生成可执行文件
#生成 lift.cpp和Tests.s的可执行文件
#格式:add_executable(${TARGET_NAME} ${SOURCES})
# ${TARGET_NAME}代表你设置的项目名称变量;
# ${SOURCES}代表你的源文件变量
add_executable(lift-${name}-tests
EXCLUDE_FROM_ALL
Lift.cpp
Tests.S
)
#在编译给定目标文件时,指定要用到的编译选项。target目标文件必须已经存在(由命令add_executable()或add_library()创建)且不能被IMPORTED修饰。
# 格式:target_compile_options(<target> [BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
target_compile_options(lift-${name}-tests
PRIVATE ${X86_TEST_FLAGS} -DIN_TEST_GENERATOR
)
# 文件写入与追加
# 格式:file(WRITE <filename> <content>...)
# 例子:file(WRITE test.txt "this is a test to wirte\n")
# 此处大概是指把 "${CMAKE_CURRENT_LIST_DIR}/*/*.S" GLOB(一种操作) 到 X86_TEST_FILES文件里。
file(GLOB X86_TEST_FILES
"${CMAKE_CURRENT_LIST_DIR}/*/*.S"
)
# 设置输出的名称,设置动态库的版本和API版本
# 格式 set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "/SUBSYSTEM:WINDOWS")
set_target_properties(lift-${name}-tests PROPERTIES OBJECT_DEPENDS "${X86_TEST_FILES}")
# 格式: TARGET_LINK_LIBRARIES(target lib1 lib2 …)
# 为target添加需要链接的共享库
target_link_libraries(lift-${name}-tests PRIVATE remill GTest::gtest)
# 为目标增加编译定义
# 格式 target_compile_definitions(<target>
#<INTERFACE|PUBLIC|PRIVATE> [items1...]
#[<INTERFACE|PUBLIC|PRIVATE> [items2...] ...]
# )
#指定编译给定 <target> 时要使用的编译定义。命名的 <target> 必须由诸如 add_executable() 或 add_library() 之类的命令创建,并且不能是导入的目标。
target_compile_definitions(lift-${sname}-tests PUBLIC ${PROJECT_DEFINITIONS})
# 增加一个没有输出的目标,使得它总是被构建。
#在很多时候,需要在cmake中创建一些目标,如clean、copy等等,这就需要通过add_custom_target来指定。同时,add_custom_command可以用来完成对add_custom_target生成的target的补充。
add_custom_command(
OUTPUT tests_${name}.bc
COMMAND lift-${name}-tests --arch ${name} --bc_out tests_${name}.bc
DEPENDS semantics
)
add_custom_command(
OUTPUT tests_${name}.S
COMMAND ${CMAKE_BC_COMPILER} -Wno-override-module -S -O0 -g0 -c tests_${name}.bc -o tests_${name}.S
DEPENDS tests_${name}.bc
)
# 之前有过解释,还不清楚为什么要重新写一遍
add_executable(run-${name}-tests EXCLUDE_FROM_ALL Run.cpp Tests.S tests_${name}.S)
set_target_properties(run-${name}-tests PROPERTIES OBJECT_DEPENDS "${X86_TEST_FILES}")
target_link_libraries(run-${name}-tests PUBLIC remill GTest::gtest)
target_compile_definitions(run-${name}-tests PUBLIC ${PROJECT_DEFINITIONS})
target_compile_options(run-${name}-tests
PRIVATE ${X86_TEST_FLAGS}
)
#为用户显示一条消息
#格式 message( [STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] "message to display" ...)
# STATUS = 非重要消息
message(STATUS "Adding test: ${name} as run-${name}-tests")
#向要由ctest运行的项目添加测试
#格式 add_test(NAME <name> COMMAND <command> [<arg>...]
# [CONFIGURATIONS <config>...]
# [WORKING_DIRECTORY <dir>]
# [COMMAND_EXPAND_LISTS])
#添加名为< name >的测试。测试名称可以包含任意字符,如果需要,可以用引号参数或括号参数表示
#COMMAND:指定测试命令行。如果< command >指定了一个可执行目标(由add_executable()创建),它将自动被构建时创建的可执行文件的位置所取代。
add_test(NAME "${name}" COMMAND "run-${name}-tests")
#在顶层目标之间添加依赖关系
# 使顶层< target >依赖于其他顶层目标,以确保它们在< target >之前构建。顶层目标是由add_executable()、add_library()或add_custom_target()命令之一创建的目标(但不是由CMake生成的类似于install的目标)。
add_dependencies(test_dependencies "run-${name}-tests")
function外部
# 如果我们在cmake某个程序的时候,经常会提示找不到某个所依赖的库,那么这是时候我们就需要检查我们引入依赖库的路径对不对了, Cmake中一个自动寻找函数find_package()可以帮我们实现这个功能。
#REQUIRED可选字段。表示一定要找到包,找不到的话就立即停掉整个cmake。而如果不指定REQUIRED则cmake会继续执行。
find_package(GTest CONFIG REQUIRED)
# 开启项目的测试功能
enable_testing()
# 如果不是苹果系统
if (NOT APPLE)
COMPILE_X86_TESTS(x86 32 0 0)
COMPILE_X86_TESTS(x86_avx 32 1 0)
endif()
# 不太清楚,但是是function的参数
COMPILE_X86_TESTS(amd64 64 0 0)
COMPILE_X86_TESTS(amd64_avx 64 1 0)