警告
本文最后更新于 2024-01-25,文中内容可能已过时。
一、CMake:使用控制流
导言
在前面的示例中,我们已经使用过if-else-endif。CMake还提供了创建循环的语言工具:foreach-endforeach和while-endwhile。两者都可以与break结合使用,以便尽早从循环中跳出。而本篇也是为第一章的完结篇,算是正式的踏入了CMake学习的大门了。
二、项目结构
1
2
3
4
5
6
7
8
| .
├── cal_add.h
├── cal_subtract.cpp
├── cal_subtract.h
├── CMakeLists.txt
├── main.cpp
├── message.cpp
└── message.h
|
本项目结构回归到了简单的结构,目的主要是为了快速展示本篇的主旨,即如何使用控制流实现一些功能。
项目地址:
https://gitee.com/jiangli01/tutorials/tree/master/cmake-tutorial/chapter1/13
三、CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(control-flow LANGUAGES CXX)
set(CXX_STANDARD 11)
add_library(test_lib
STATIC
${CMAKE_SOURCE_DIR}/message.h
${CMAKE_SOURCE_DIR}/message.cpp
${CMAKE_SOURCE_DIR}/cal_add.h
${CMAKE_SOURCE_DIR}/cal_subtract.h
${CMAKE_SOURCE_DIR}/cal_subtract.cpp
)
# 使用-O3编译器优化级别编译库,对目标设置一个私有编译器选项
target_compile_options(test_lib PRIVATE -O3)
# 生成一个源文件列表,以较低的优化选项进行编译
list(APPEND sources_with_lower_optimization
cal_subtract.cpp
)
# 循环这些源文件,将它们的优化级别调到-O2。使用它们的源文件属性完成
message(STATUS "Setting source properties using IN LISTS syntax:")
foreach(_source IN LISTS sources_with_lower_optimization)
set_source_files_properties(${_source} PROPERTIES COMPILE_FLAGS -O2)
message(STATUS "Appending -O2 flag for ${_source}")
endforeach()
# 为了确保设置属性,再次循环并在打印每个源文件的COMPILE_FLAGS属性
message(STATUS "Querying sources properties using plain syntax:")
foreach(_source ${sources_with_lower_optimization})
get_source_file_property(_flags ${_source} COMPILE_FLAGS)
message(STATUS "Source ${_source} has the following extra COMPILE_FLAGS: ${_flags}")
endforeach()
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} test_lib)
set_source_files_properties(file PROPERTIES property value)
|
将属性设置为给定文件的传递值。与目标非常相似,文件在CMake中也有属性,允许对构建系统进行非常细粒度的控制。
Tip
1
| get_source_file_property(VAR file property)
|
检索给定文件所需属性的值,并将其存储在CMakeVAR
变量中。
注意:CMake
中,列表是用分号
分隔的字符串组。列表可以由list
或set
命令创建。例如,set(var a b c d e)
和list(APPEND a b c d e)
都创建了列表a;b;c;d;e
。
引用
1
2
3
| foreach(loop_var range total)
or
foreach(loop_var range start stop [step])
|
通过指定一个范围,可以对整数进行循环
✦
四、相关源码
cal_add.h
1
2
3
4
5
6
7
8
| #ifndef CALCULATE_ADD_HEADER
#define CALCULATE_ADD_HEADER
template <typename T, typename U>
auto Add(T t, U u) -> decltype(t + u){
return t + u;
}
#endif // ! CALCULATE_ADD_HEADER
|
cal_substruct.h
1
2
3
4
5
| #ifndef CALCULATE_SUBSTRACT_HEADER
#define CALCULATE_SUBSTRACT_HEADER
float Substract(float a, float b);
#endif // ! CALCULATE_SUBSTRACT_HEADER
|
cal_substruct.cpp
1
| float Substract(float a, float b) { return a - b; }
|
message.h
1
2
3
4
5
6
7
8
9
10
| #ifndef MESSAGE_HEADER_H_
#define MESSAGE_HEADER_H_
#include <string>
class Message {
public:
Message() {}
void Print(const std::string& message);
};
#endif // ! MESSAGE_HEADER_H_
|
message.cpp
1
2
3
4
5
6
| #include "message.h"
#include <iostream>
void Message::Print(const std::string& message) {
std::cout << message << std::endl;
}
|
main.cpp
1
2
3
4
5
6
7
8
9
10
11
| #include "message.h"
#include "cal_add.h"
#include "cal_subtract.h"
int main() {
int a = 1;
int b = 2;
auto c = Add(a , b);
Message message;
message.Print(std::to_string(c));
return 0;
}
|
五、编译结果
1
2
3
4
5
6
7
8
9
10
11
12
13
| -- The CXX compiler identification is GNU 9.4.0
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Setting source properties using IN LISTS syntax:
-- Appending -O2 flag for cal_add.cpp
-- Appending -O2 flag for cal_subtract.cpp
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jiangli/repo/tutorials/cmake-tutorial/chapter1/13/build
|
五、附录
foreach()
的四种使用方式:
foreach(loop_var arg1 arg2 ...)
: 其中提供循环变量和显式项列表。当为sources_with_lower_optimization
中的项打印编译器标志集时,使用此表单。注意,如果项目列表位于变量中,则必须显式展开它;也就是说,${sources_with_lower_optimization}
必须作为参数传递。- 通过指定一个范围,可以对整数进行循环,例如:
foreach(loop_var range total)
或foreach(loop_var range start stop [step])
。 - 对列表值变量的循环,例如:
foreach(loop_var IN LISTS [list1[...]])
。参数解释为列表,其内容就会自动展开。 - 对变量的循环,例如:
foreach(loop_var IN ITEMS [item1 [...]])
。参数的内容没有展开。