配置
如果有多个配置选项,通过编译器标志传递它们会变得非常繁琐。它还会使配置设置难以检查。为了简化操作,Meson 支持生成配置文件。此功能类似于 CMake 等其他构建系统中找到的功能。
假设我们有以下 Meson 代码片段
conf_data = configuration_data()
conf_data.set('version', '1.2.3')
configure_file(input : 'config.h.in',
output : 'config.h',
configuration : conf_data)
并且 config.h.in
的内容为
#define VERSION_STR "@version@"
然后 Meson 会在相应的构建目录中创建一个名为 config.h
的文件,其内容如下。
#define VERSION_STR "1.2.3"
更具体地说,Meson 会找到所有类型为 @varname@
的字符串,并将其替换为 conf_data
中设置的相应值。您可以根据需要多次使用单个 configuration_data
对象,但在传递给 configure_file
函数后它会变得不可变。也就是说,在它被用来生成输出后,set
函数将不可用,尝试调用它会导致错误。不可变 configuration_data
的副本仍然是不可变的。
对于更复杂的配置文件生成,Meson 提供了第二种形式。要使用它,请在您的配置文件中添加一行如下所示的代码。
#mesondefine TOKEN
发生的替换取决于 TOKEN 的值和类型
#define TOKEN // If TOKEN is set to boolean true.
#undef TOKEN // If TOKEN is set to boolean false.
#define TOKEN 4 // If TOKEN is set to an integer or string value.
/* undef TOKEN */ // If TOKEN has not been set to any value.
请注意,如果您要定义一个 C 字符串,则需要自己进行引号,例如
conf_data.set('TOKEN', '"value"')
由于这是一种非常常见的操作,Meson 提供了一种便捷方法
plain_var = 'value'
conf_data.set_quoted('TOKEN', plain_var) # becomes #define TOKEN "value"
通常,您在 Meson 中有一个布尔值,但需要将 C/C++ 令牌定义为 0 或 1。Meson 为这种情况提供了一个便捷函数。
conf_data.set10(token, boolean_value)
# The line above is equivalent to this:
if boolean_value
conf_data.set(token, 1)
else
conf_data.set(token, 0)
endif
在没有输入文件的情况下进行配置
如果未定义输入文件,则 Meson 将生成一个包含配置数据对象中所有条目的头文件。替换与生成 #mesondefine
条目时相同
conf_data.set('FOO', '"string"') => #define FOO "string"
conf_data.set('FOO', 'a_token') => #define FOO a_token
conf_data.set('FOO', true) => #define FOO
conf_data.set('FOO', false) => #undef FOO
conf_data.set('FOO', 1) => #define FOO 1
conf_data.set('FOO', 0) => #define FOO 0
在这种模式下,您还可以指定一个注释,该注释将放置在值之前,以便生成的代码具有自记录功能。
conf_data.set('BAR', true, description : 'Set BAR if it is available')
将生成
/* Set BAR if it is available */
#define BAR
处理文件编码
默认的 Meson 文件编码用于配置文件为 utf-8。如果您需要配置一个未以 utf-8 编码的文件,encoding
关键字将允许您指定要使用的文件编码。但是,强烈建议您尽可能将非 utf-8 文件转换为 utf-8。支持的文件编码是 python3 的编码,请参阅 标准编码。
使用字典
自 0.49.0 起 configuration_data()
接受一个可选的字典作为第一个参数。如果提供,每个键值对将被添加到 configuration_data
中,就像对它们中的每一个调用了 set()
方法一样。 configure_file()
的 configuration
关键字也接受字典而不是 configuration_data 对象。
示例
cdata = configuration_data({
'STRING' : '"foo"',
'INT' : 42,
'DEFINED' : true,
'UNDEFINED' : false,
})
configure_file(output : 'config1.h',
configuration : cdata,
)
configure_file(output : 'config2.h',
configuration : {
'STRING' : '"foo"',
'INT' : 42,
'DEFINED' : true,
'UNDEFINED' : false,
}
)
完整的示例
生成和使用配置文件需要以下步骤
- 生成文件
- 为包含该文件的目录创建一个包含目录对象
- 在目标中使用它
我们将使用在顶层目录中生成头文件的传统方法。通用名称为 config.h
,但我们将使用一个唯一的名称。这避免了在构建具有多个子项目的项目时意外包含错误的头文件的问题。
在顶层我们生成文件
conf_data = configuration_data()
# Set data
configure_file(input : 'projconfig.h.in',
output : 'projconfig.h',
configuration : conf_data)
之后立即我们生成包含对象。
configuration_inc = include_directories('.')
最后,我们在任何子目录中的目标中指定这一点。
executable(..., include_directories : configuration_inc)
现在,此目标中的任何源文件都可以像这样包含配置头文件
#include<projconfig.h>
搜索结果为