运行cmake命令时如何加载环境文件(.env) ?



是否有任何选项可以允许我从dotenv文件加载键=值对?我知道我可以做-E env key=value,但是我有很多值,我想从dotenv文件加载它们,因为其他工具可以从它加载环境变量。我不想做bash技巧,因为我希望它尽可能简单和跨平台。

没有内置对dotenv文件的支持,但这里有一个纯CMake的完整实现。对于CMakeLists.txt,这里有一个例子:

cmake_minimum_required(VERSION 3.21)
project(env-test NONE)
add_custom_target(
example
COMMAND 
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/env.cmake 
${CMAKE_CURRENT_SOURCE_DIR}/.env  # dotenv
env  # command
)

以下是.env文件的内容:

foo=bar
bears=beets
battlestar=galactica

下面是这个工作的演示:

$ cmake -G Ninja -S . -B build
$ cmake --build build --target example
...
foo=bar
bears=beets
battlestar=galactica

,这是(复杂的)env.cmake脚本,实现这一点:

cmake_minimum_required(VERSION 3.21)
if (CMAKE_ARGC LESS 5)
message(FATAL_ERROR "Usage: cmake -P env.cmake <dotenv> [command...]")
endif ()
set(dotenv "${CMAKE_ARGV3}")
if (NOT EXISTS "${dotenv}")
message(FATAL_ERROR "Dot-env file not found: ${dotenv}")
endif ()
set(command "")
math(EXPR argc "${CMAKE_ARGC} - 1")
foreach (i RANGE 4 ${argc})
list(APPEND command "${CMAKE_ARGV${i}}")
endforeach ()
file(STRINGS "${dotenv}" entries)
foreach (entry IN LISTS entries)
if (entry MATCHES "^([^=]+)=(.*)$")
set(ENV{${CMAKE_MATCH_1}} "${CMAKE_MATCH_2}")
else ()
message(FATAL_ERROR "Malformed dotenv entry:n${entry}")
endif ()
endforeach ()
execute_process(COMMAND ${command} COMMAND_ERROR_IS_FATAL ANY)