我更喜欢把CMake中的“配置文件”称为“模板文件”。
Hello模板文件
如何写一个模板文件,并使用呢?
- 一般将模板文件命名为
<文件名>.<后缀名>.in
- 在模板文件中,使用
@<cmake-var-name>@
方式即可引用一个CMake变量,如@Tutorial_VERSION_MAJOR@
- 在CMake文件中,使用
configure_file
命令,即可把CMake变量传入模板文件,生成结果文件configure_file(TutorialConfig.h.in #输入文件(即模板文件)
TutorialConfig.h #输出文件
@ONLY #替换配置文件中的@变量,这个可以省略不写
)
配置文件的妙用
毋庸置疑,CMake之C++是非常成熟的。但在构建某些C#工程而言,会显得非常吃力。此时“模板文件”就能帮助我们构建一个非常复杂的工程。
使用步骤:
- 使用Visual Studio创建好你中意的C#工程
- 然后将
<文件名>.csproj
进行修改- 将需要CMake传入的变量改成
@<cmake-var-name>@
- 将文件名改成
<文件名>.csproj.in
- 将需要CMake传入的变量改成
- 使用
configure_file
将模板文件编译成<文件名>.csproj
- 有多种方式
- 将项目加入工程中,可以使用命令
include_external_msproject(目标名, <文件名>.csproj)
引入外部的VS工程 - 可以使用
dotnet.exe
,直接编译、运行这个工程
- 将项目加入工程中,可以使用命令
详细的例子可参考《CMake SWIG C#》的应用文章。
配置文件会用到的相关写法
拼接字符串
参考文章:configure_file list of files -> #includes cmake
例一:获取源代码列表,并拼接成字符串
- CMakeLists.txt ``` cmake_minimum_required(VERSION 3.8) project(swigdotnettest)
获得源代码列表,并拼接成字符串,模板文件中要使用
set(source_files_string) file(GLOB_RECURSE SRC_FILES ${CMAKE_CURRENT_LIST_DIR}/*.cs) foreach(item ${SRC_FILES})
# <Compile Include="exe_test.cs" />
set(source_files_string
"${source_files_string}<Compile Include=\"${item}\" />
"
)
endforeach()
获得依赖库
set(references_string “”) join_references_string(references_string ${Project_OUTPUT_DIR}/smartgis_core_csharp.dll ${Project_OUTPUT_DIR}/glal_core_wrapper_dotnet.dll ${Project_OUTPUT_DIR}/glal_util_wrapper_dotnet.dll )
生成测试工程
configure_file(dotnet_xunit_template.csproj.in ${PROJECT_NAME}.csproj @ONLY)
加入
include_external_msproject( ${PROJECT_NAME} ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.csproj )
2. dotnet_xunit_template.csproj.in
<IsPackable>false</IsPackable>
<Configuration>Release</Configuration>
<Platform>@platform_type@</Platform>
<OutputPath>@Project_OUTPUT_DIR@</OutputPath>
<!--输出目录去掉版本目录。没有这个标签,输出目录是OutputPath\net5 -->
<AppendTargetFrameworkToOutputPath>output</AppendTargetFrameworkToOutputPath>
3. join_references_string宏
拼接csproj中依赖库的字符串
references_string 返回值(csproj中依赖库的字符串)
其他参数 收集在dependlibs_path中
macro(join_references_string references_string) set(dependlibs_path “${ARGN}”) #依赖库的全路径
# 处理一个依赖库
foreach(dependlib_path ${dependlibs_path})
#没有后缀名的文件名称
get_filename_component(dependlib_name ${dependlib_path} NAME_WLE)
# <Reference Include="simple_wrapper_dotnet">
# <HintPath>$(OutputPath)\simple_wrapper_dotnet.dll</HintPath>
# </Reference>
set(item_string
"
<Reference Include=\"${dependlib_name}\">
<HintPath>${dependlib_path}</HintPath>
</Reference>
"
)
set(${references_string}
"${${references_string}}${item_string}"
)
endforeach()
endmacro() ```