cmEnvironment: Introduce class for a set of environment variables

This commit is contained in:
Daniel Pfeifer
2026-03-08 21:45:14 +01:00
parent bf071f85fe
commit a5d0e0fb69
4 changed files with 124 additions and 0 deletions

View File

@@ -191,6 +191,8 @@ add_library(
cmDyndepCollation.h
cmELF.h
cmELF.cxx
cmEnvironment.cxx
cmEnvironment.h
cmEvaluatedTargetProperty.cxx
cmEvaluatedTargetProperty.h
cmExprParserHelper.cxx

66
Source/cmEnvironment.cxx Normal file
View File

@@ -0,0 +1,66 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmEnvironment.h"
#include <utility>
#include <cm/string_view>
#include <cm/vector>
#include <cmext/algorithm>
#if defined(_WIN32)
# include "cmsys/String.h"
#endif
bool cmEnvironment::EnvNameLess::operator()(std::string const& lhs,
std::string const& rhs) const
{
#if defined(_WIN32)
// Environment variable names are case-insensitive on Windows
return cmsysString_strcasecmp(lhs.c_str(), rhs.c_str()) < 0;
#else
return lhs < rhs;
#endif
}
cmEnvironment::cmEnvironment(std::vector<std::string> const& env)
{
for (std::string const& var : env) {
this->PutEnv(var);
}
}
void cmEnvironment::PutEnv(std::string const& env)
{
auto const pos = env.find('=');
if (pos != std::string::npos) {
this->Map[env.substr(0, pos)] = env.substr(pos + 1);
} else {
this->Map[env] = cm::nullopt;
}
}
void cmEnvironment::UnPutEnv(std::string const& env)
{
this->Map[env] = cm::nullopt;
}
void cmEnvironment::Update(cmEnvironment&& other)
{
for (auto& kv : other.Map) {
this->Map[kv.first] = std::move(kv.second);
}
other.Map.clear();
}
std::vector<std::string> cmEnvironment::GetVariables() const
{
auto result = std::vector<std::string>{};
result.reserve(this->Map.size());
for (auto const& elem : this->Map) {
if (elem.second) {
result.push_back(elem.first + '=' + *elem.second);
}
}
return result;
}

55
Source/cmEnvironment.h Normal file
View File

@@ -0,0 +1,55 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#pragma once
#include "cmConfigure.h" // IWYU pragma: keep
#include <map>
#include <string>
#include <vector>
#include <cm/optional>
/**
* Helper class to represent an environment.
*/
class cmEnvironment
{
public:
/** Initialize from `NAME=VALUE` strings. */
cmEnvironment(std::vector<std::string> const& env = {});
/**
* Add a single variable (or remove if no = sign) to the current
* environment.
*/
void PutEnv(std::string const& env);
/** Remove a single variable from the current environment. */
void UnPutEnv(std::string const& env);
/**
* Move the environment entries from `other` into this one, overwriting
* existing variables when a key is already present. */
void Update(cmEnvironment&& other);
/** Modify the value of a variable in-place using a transform function. */
template <typename F>
void Modify(std::string const& name, F&& transform)
{
cm::optional<std::string>& val = this->Map[name];
if (!val.has_value()) {
val = std::string{};
}
transform(*val);
}
std::vector<std::string> GetVariables() const;
protected:
struct EnvNameLess
{
bool operator()(std::string const& lhs, std::string const& rhs) const;
};
std::map<std::string, cm::optional<std::string>, EnvNameLess> Map;
};

View File

@@ -340,6 +340,7 @@ CMAKE_CXX_SOURCES="\
cmELF \
cmEnableLanguageCommand \
cmEnableTestingCommand \
cmEnvironment \
cmEvaluatedTargetProperty \
cmExecProgramCommand \
cmExecuteProcessCommand \