mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-14 02:08:27 +08:00
Merge topic 'update-kwsys'
77ea15b797
Tests: Add case covering `cmake -E env` with empty environment variable209dfc51d3
Merge branch 'upstream-KWSys' into update-kwsys92a7104600
KWSys 2025-10-08 (3bae03fe) Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !11288
This commit is contained in:
@@ -209,7 +209,6 @@ endif()
|
|||||||
|
|
||||||
# Include helper macros.
|
# Include helper macros.
|
||||||
include(${CMAKE_CURRENT_SOURCE_DIR}/kwsysPlatformTests.cmake)
|
include(${CMAKE_CURRENT_SOURCE_DIR}/kwsysPlatformTests.cmake)
|
||||||
include(CheckTypeSize)
|
|
||||||
|
|
||||||
# Do full dependency headers.
|
# Do full dependency headers.
|
||||||
include_regular_expression("^.*$")
|
include_regular_expression("^.*$")
|
||||||
|
@@ -675,15 +675,21 @@ char const* SystemTools::GetEnv(std::string const& key)
|
|||||||
bool SystemTools::GetEnv(char const* key, std::string& result)
|
bool SystemTools::GetEnv(char const* key, std::string& result)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
auto wide_key = Encoding::ToWide(key);
|
std::wstring const wKey = Encoding::ToWide(key);
|
||||||
auto result_size = GetEnvironmentVariableW(wide_key.data(), nullptr, 0);
|
std::vector<wchar_t> heapBuf;
|
||||||
if (result_size <= 0) {
|
wchar_t stackBuf[256];
|
||||||
|
DWORD bufSz = static_cast<DWORD>(sizeof(stackBuf) / sizeof(stackBuf[0]));
|
||||||
|
wchar_t* buf = stackBuf;
|
||||||
|
DWORD r;
|
||||||
|
while ((r = GetEnvironmentVariableW(wKey.c_str(), buf, bufSz)) >= bufSz) {
|
||||||
|
heapBuf.resize(r);
|
||||||
|
bufSz = r;
|
||||||
|
buf = &heapBuf[0];
|
||||||
|
}
|
||||||
|
if (r == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::wstring wide_result;
|
result = Encoding::ToNarrow(buf);
|
||||||
wide_result.resize(result_size - 1);
|
|
||||||
GetEnvironmentVariableW(wide_key.data(), &wide_result[0], result_size);
|
|
||||||
result = Encoding::ToNarrow(wide_result);
|
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
char const* v = getenv(key);
|
char const* v = getenv(key);
|
||||||
@@ -703,12 +709,12 @@ bool SystemTools::GetEnv(std::string const& key, std::string& result)
|
|||||||
bool SystemTools::HasEnv(char const* key)
|
bool SystemTools::HasEnv(char const* key)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
std::wstring const wkey = Encoding::ToWide(key);
|
std::wstring const wKey = Encoding::ToWide(key);
|
||||||
wchar_t const* v = _wgetenv(wkey.c_str());
|
DWORD r = GetEnvironmentVariableW(wKey.c_str(), nullptr, 0);
|
||||||
|
return !(r == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND);
|
||||||
#else
|
#else
|
||||||
char const* v = getenv(key);
|
return getenv(key) != nullptr;
|
||||||
#endif
|
#endif
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SystemTools::HasEnv(std::string const& key)
|
bool SystemTools::HasEnv(std::string const& key)
|
||||||
@@ -732,8 +738,8 @@ static int kwsysUnPutEnv(std::string const& env)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(__CYGWIN__) || defined(__GLIBC__)
|
#elif defined(__CYGWIN__) || defined(__GLIBC__)
|
||||||
/* putenv("A") removes A from the environment. It must not put the
|
// putenv("A") removes A from the environment with the GNU runtime.
|
||||||
memory in the environment because it does not have any "=" syntax. */
|
// It cannot put the memory in the environment since there is no "=" syntax.
|
||||||
|
|
||||||
static int kwsysUnPutEnv(std::string const& env)
|
static int kwsysUnPutEnv(std::string const& env)
|
||||||
{
|
{
|
||||||
@@ -750,12 +756,7 @@ static int kwsysUnPutEnv(std::string const& env)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
/* putenv("A=") places "A=" in the environment, which is as close to
|
// putenv("A=") removes A from the environment with the MSVC runtime.
|
||||||
removal as we can get with the putenv API. We have to leak the
|
|
||||||
most recent value placed in the environment for each variable name
|
|
||||||
on program exit in case exit routines access it. */
|
|
||||||
|
|
||||||
static kwsysEnvSet kwsysUnPutEnvSet;
|
|
||||||
|
|
||||||
static int kwsysUnPutEnv(std::string const& env)
|
static int kwsysUnPutEnv(std::string const& env)
|
||||||
{
|
{
|
||||||
@@ -763,13 +764,7 @@ static int kwsysUnPutEnv(std::string const& env)
|
|||||||
size_t const pos = wEnv.find('=');
|
size_t const pos = wEnv.find('=');
|
||||||
size_t const len = pos == std::string::npos ? wEnv.size() : pos;
|
size_t const len = pos == std::string::npos ? wEnv.size() : pos;
|
||||||
wEnv.resize(len + 1, L'=');
|
wEnv.resize(len + 1, L'=');
|
||||||
wchar_t* newEnv = _wcsdup(wEnv.c_str());
|
return _wputenv(wEnv.c_str());
|
||||||
if (!newEnv) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
kwsysEnvSet::Free oldEnv(kwsysUnPutEnvSet.Release(newEnv));
|
|
||||||
kwsysUnPutEnvSet.insert(newEnv);
|
|
||||||
return _wputenv(newEnv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@@ -846,7 +841,7 @@ public:
|
|||||||
bool Put(char const* env)
|
bool Put(char const* env)
|
||||||
{
|
{
|
||||||
# if defined(_WIN32)
|
# if defined(_WIN32)
|
||||||
std::wstring const wEnv = Encoding::ToWide(env);
|
std::wstring wEnv = Encoding::ToWide(env);
|
||||||
wchar_t* newEnv = _wcsdup(wEnv.c_str());
|
wchar_t* newEnv = _wcsdup(wEnv.c_str());
|
||||||
# else
|
# else
|
||||||
char* newEnv = strdup(env);
|
char* newEnv = strdup(env);
|
||||||
@@ -854,7 +849,21 @@ public:
|
|||||||
Free oldEnv(this->Release(newEnv));
|
Free oldEnv(this->Release(newEnv));
|
||||||
this->insert(newEnv);
|
this->insert(newEnv);
|
||||||
# if defined(_WIN32)
|
# if defined(_WIN32)
|
||||||
return _wputenv(newEnv) == 0;
|
// `_wputenv` updates both the C runtime library's `_wenviron` array
|
||||||
|
// and the process's environment block.
|
||||||
|
if (_wputenv(newEnv) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// There seems to be no way to add an empty variable to `_wenviron`
|
||||||
|
// through the C runtime library: `_wputenv("A=")` removes "A".
|
||||||
|
// Add it directly to the process's environment block.
|
||||||
|
// This is used by child processes, and by our `GetEnv`.
|
||||||
|
std::string::size_type const eqPos = wEnv.find(L'=');
|
||||||
|
if (eqPos != std::string::npos && (eqPos + 1) == wEnv.size()) {
|
||||||
|
wEnv.resize(eqPos);
|
||||||
|
return SetEnvironmentVariableW(wEnv.c_str(), L"");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
# else
|
# else
|
||||||
return putenv(newEnv) == 0;
|
return putenv(newEnv) == 0;
|
||||||
# endif
|
# endif
|
||||||
|
@@ -696,6 +696,12 @@ static bool CheckPutEnv(std::string const& env, char const* name,
|
|||||||
<< value << "\"!" << std::endl;
|
<< value << "\"!" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool bv = kwsys::SystemTools::HasEnv(name);
|
||||||
|
if (!bv) {
|
||||||
|
std::cerr << "HasEnv(\"" << name << "\") returned \"" << bv
|
||||||
|
<< "\", not \"true\"!" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -711,6 +717,12 @@ static bool CheckUnPutEnv(char const* env, char const* name)
|
|||||||
<< "\", not (null)!" << std::endl;
|
<< "\", not (null)!" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool bv = kwsys::SystemTools::HasEnv(name);
|
||||||
|
if (bv) {
|
||||||
|
std::cerr << "HasEnv(\"" << name << "\") returned \"" << bv
|
||||||
|
<< "\", not \"false\"!" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -721,6 +733,7 @@ static bool CheckEnvironmentOperations()
|
|||||||
res &= CheckPutEnv("B=C", "B", "C");
|
res &= CheckPutEnv("B=C", "B", "C");
|
||||||
res &= CheckPutEnv("C=D", "C", "D");
|
res &= CheckPutEnv("C=D", "C", "D");
|
||||||
res &= CheckPutEnv("D=E", "D", "E");
|
res &= CheckPutEnv("D=E", "D", "E");
|
||||||
|
res &= CheckPutEnv("F=", "F", "");
|
||||||
res &= CheckUnPutEnv("A", "A");
|
res &= CheckUnPutEnv("A", "A");
|
||||||
res &= CheckUnPutEnv("B=", "B");
|
res &= CheckUnPutEnv("B=", "B");
|
||||||
res &= CheckUnPutEnv("C=D", "C");
|
res &= CheckUnPutEnv("C=D", "C");
|
||||||
|
1
Tests/RunCMake/CommandLine/E_env-empty-stdout.txt
Normal file
1
Tests/RunCMake/CommandLine/E_env-empty-stdout.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
^-- TEST_ENV is correctly set in environment: ''$
|
5
Tests/RunCMake/CommandLine/E_env-empty.cmake
Normal file
5
Tests/RunCMake/CommandLine/E_env-empty.cmake
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
if(DEFINED ENV{TEST_ENV})
|
||||||
|
message(STATUS "TEST_ENV is correctly set in environment: '$ENV{TEST_ENV}'")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "TEST_ENV is incorrectly not set in environment")
|
||||||
|
endif()
|
@@ -820,6 +820,7 @@ run_cmake_command(E_env-no-command0 ${CMAKE_COMMAND} -E env)
|
|||||||
run_cmake_command(E_env-no-command1 ${CMAKE_COMMAND} -E env TEST_ENV=1)
|
run_cmake_command(E_env-no-command1 ${CMAKE_COMMAND} -E env TEST_ENV=1)
|
||||||
run_cmake_command(E_env-bad-arg1 ${CMAKE_COMMAND} -E env -bad-arg1)
|
run_cmake_command(E_env-bad-arg1 ${CMAKE_COMMAND} -E env -bad-arg1)
|
||||||
run_cmake_command(E_env-set ${CMAKE_COMMAND} -E env TEST_ENV=1 ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-set.cmake)
|
run_cmake_command(E_env-set ${CMAKE_COMMAND} -E env TEST_ENV=1 ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-set.cmake)
|
||||||
|
run_cmake_command(E_env-empty ${CMAKE_COMMAND} -E env TEST_ENV= ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-empty.cmake)
|
||||||
run_cmake_command(E_env-unset ${CMAKE_COMMAND} -E env TEST_ENV=1 ${CMAKE_COMMAND} -E env --unset=TEST_ENV ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-unset.cmake)
|
run_cmake_command(E_env-unset ${CMAKE_COMMAND} -E env TEST_ENV=1 ${CMAKE_COMMAND} -E env --unset=TEST_ENV ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-unset.cmake)
|
||||||
run_cmake_command(E_env-stdin ${CMAKE_COMMAND} -DPRINT_STDIN_EXE=${PRINT_STDIN_EXE} -P ${RunCMake_SOURCE_DIR}/E_env-stdin.cmake)
|
run_cmake_command(E_env-stdin ${CMAKE_COMMAND} -DPRINT_STDIN_EXE=${PRINT_STDIN_EXE} -P ${RunCMake_SOURCE_DIR}/E_env-stdin.cmake)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user