From 1df4375e9d2b9f9f22e246c0454962597e97dc64 Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 1 Nov 2026 08:34:41 -0600 Subject: [PATCH 1/3] Add env flag to init The `--env VAR=VALUE` flag is stored in the prefix and set for the cmake configure, build and install of every package, but not when cget downloads the package. So a dead proxy such as `https_proxy=http://127.0.0.1:1` can be used to make sure the builds do not reach the network. Also, `to_define_dict` now splits on the first `=` only, so `-DVAR=a=b` keeps the whole value. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01Aqc8j4E36M4BkM4P1c6SVv --- cget/cli.py | 4 +++- cget/prefix.py | 14 +++++++++++++- cget/util.py | 11 ++++++++++- docs/src/commands.rst | 4 ++++ test/libsimpleenv/CMakeLists.txt | 18 ++++++++++++++++++ test/libsimpleenv/include/simple.h | 10 ++++++++++ test/libsimpleenv/test.cpp | 7 +++++++ test/test_cget.py | 16 ++++++++++++++++ 8 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 test/libsimpleenv/CMakeLists.txt create mode 100644 test/libsimpleenv/include/simple.h create mode 100644 test/libsimpleenv/test.cpp diff --git a/cget/cli.py b/cget/cli.py index 68c7e55..64d19df 100644 --- a/cget/cli.py +++ b/cget/cli.py @@ -75,9 +75,10 @@ def w(obj, prefix, verbose, build_path, *args, **kwargs): @click.option('--ldflags', required=False, help="Set additional linker flags") @click.option('--std', required=False, help="Set C++ standard if available") @click.option('-D', '--define', multiple=True, help="Extra configuration variables to pass to CMake") +@click.option('--env', multiple=True, help="Environment variables to set when building packages") @click.option('--shared', is_flag=True, help="Set toolchain to build shared libraries by default") @click.option('--static', is_flag=True, help="Set toolchain to build static libraries by default") -def init_command(prefix, toolchain, cc, cxx, cflags, cxxflags, ldflags, std, define, shared, static): +def init_command(prefix, toolchain, cc, cxx, cflags, cxxflags, ldflags, std, define, env, shared, static): """ Initialize install directory """ if shared and static: display.error("shared and static are not supported together") @@ -95,6 +96,7 @@ def init_command(prefix, toolchain, cc, cxx, cflags, cxxflags, ldflags, std, def ldflags=ldflags, std=std, defines=defines) + prefix.write_env(util.to_define_dict(env)) @cli.command(name='install') @use_prefix diff --git a/cget/prefix.py b/cget/prefix.py index e9a2695..9dbe431 100644 --- a/cget/prefix.py +++ b/cget/prefix.py @@ -118,10 +118,22 @@ def check(self, f, *args): def get_env(self): - return { + env = { 'LD_LIBRARY_PATH': self.get_path('lib'), 'PKG_CONFIG_PATH': self.pkg_config_path() } + env.update(self.read_env()) + return env + + def get_env_file(self): + return self.get_private_path('env') + + def read_env(self): + return util.to_define_dict(util.read_from(self.get_env_file())) + + def write_env(self, env): + util.delete_file(self.get_env_file()) + return util.mkfile(self.get_private_path(), 'env', ['{0}={1}'.format(key, value) for key, value in env.items()]) def write_cmake(self, always_write=False, **kwargs): return util.mkfile(self.get_private_path(), 'cget.cmake', self.generate_cmake_toolchain(**kwargs), always_write=always_write) diff --git a/cget/util.py b/cget/util.py index 84278b5..e18cd68 100644 --- a/cget/util.py +++ b/cget/util.py @@ -78,6 +78,12 @@ def write_to(file, lines): with open(file, 'w') as f: f.writelines(content) +def read_from(file): + if os.path.exists(file): + with open(file) as f: + for line in f.read().splitlines(): + yield line + def mkdir(p): if not os.path.exists(p): os.makedirs(p) return p @@ -118,6 +124,9 @@ def get_cache_file(key): else: return None +def delete_file(path): + if path is not None and os.path.exists(path): os.remove(adjust_path(path)) + def delete_dir(path): if path is not None and os.path.exists(path): shutil.rmtree(adjust_path(path)) @@ -361,7 +370,7 @@ def to_define_dict(xs): result = {} for x in xs: if '=' in x: - p = x.split('=') + p = x.split('=', 1) result[p[0]] = p[1] else: result[x] = '' diff --git a/docs/src/commands.rst b/docs/src/commands.rst index 9ce6a85..b6697a0 100644 --- a/docs/src/commands.rst +++ b/docs/src/commands.rst @@ -159,6 +159,10 @@ This will initialize the cmake toolchain. By default, the ``install`` command wi Extra configuration variables to pass to CMake. +.. option:: --env VAR=VALUE + + Environment variables to set when building packages. These are set for the cmake configure, build and install steps of every package installed in the prefix. They are not set when cget downloads the package. + .. option:: --shared Set toolchain to build shared libraries by default. diff --git a/test/libsimpleenv/CMakeLists.txt b/test/libsimpleenv/CMakeLists.txt new file mode 100644 index 0000000..c1283af --- /dev/null +++ b/test/libsimpleenv/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required (VERSION 2.8) + +if("$ENV{CGET_ENV_FLAG}" STREQUAL "On" AND "$ENV{CGET_ENV_VALUE}" STREQUAL "a=b") +install (FILES include/simple.h DESTINATION include) + +include(CTest) + +add_executable (simpletest test.cpp) +if(WIN32) + add_test(NAME simpletest WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH} COMMAND simpletest${CMAKE_EXECUTABLE_SUFFIX}) +else() + add_test(NAME simpletest COMMAND simpletest) +endif() + +include_directories(include) +else() + message(FATAL_ERROR "CGET_ENV_FLAG and CGET_ENV_VALUE not set") +endif() diff --git a/test/libsimpleenv/include/simple.h b/test/libsimpleenv/include/simple.h new file mode 100644 index 0000000..9b54f12 --- /dev/null +++ b/test/libsimpleenv/include/simple.h @@ -0,0 +1,10 @@ + +#ifndef GUARD_SIMPLE_H +#define GUARD_SIMPLE_H + +inline void simple() +{ +} + + +#endif diff --git a/test/libsimpleenv/test.cpp b/test/libsimpleenv/test.cpp new file mode 100644 index 0000000..fd6480d --- /dev/null +++ b/test/libsimpleenv/test.cpp @@ -0,0 +1,7 @@ + +#include + +int main() +{ + simple(); +} diff --git a/test/test_cget.py b/test/test_cget.py index fe483d2..402e720 100644 --- a/test/test_cget.py +++ b/test/test_cget.py @@ -905,6 +905,22 @@ def test_flags_fail_define(d): def test_flags_define(d): d.cmds([cget_cmd('install', '--verbose --test --define CGET_FLAG=On', get_exists_path('libsimpleflag'))]) +@appveyor_skip +def test_env_init(d): + d.cmds(install_cmds(init='--env CGET_ENV_FLAG=On --env CGET_ENV_VALUE=a=b', url=get_exists_path('libsimpleenv'))) + +@pytest.mark.xfail(strict=True) +def test_env_fail(d): + d.cmds([cget_cmd('install', '--verbose --test', get_path('libsimpleenv'))]) + +@pytest.mark.xfail(strict=True) +def test_env_init_reset(d): + d.cmds([ + cget_cmd('init', '--env CGET_ENV_FLAG=On --env CGET_ENV_VALUE=a=b'), + cget_cmd('init'), + cget_cmd('install', '--verbose --test', get_path('libsimpleenv')) + ]) + @appveyor_skip def test_flags_toolchain(d): d.cmds([ From 17854f7a8adffeb91dfe7c3b709208091177a642 Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 1 Nov 2026 08:54:32 -0600 Subject: [PATCH 2/3] Update docs --- docs/src/commands.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/commands.rst b/docs/src/commands.rst index b6697a0..21187ef 100644 --- a/docs/src/commands.rst +++ b/docs/src/commands.rst @@ -161,7 +161,7 @@ This will initialize the cmake toolchain. By default, the ``install`` command wi .. option:: --env VAR=VALUE - Environment variables to set when building packages. These are set for the cmake configure, build and install steps of every package installed in the prefix. They are not set when cget downloads the package. + Environment variables to set when building packages. These are set for the cmake configure, build and install steps of every package installed in the prefix. They are not set when cget runs. .. option:: --shared From 0772e60b51737a7d8821942219ebd0d525277abe Mon Sep 17 00:00:00 2001 From: Paul Date: Sun, 1 Nov 2026 20:53:34 -0600 Subject: [PATCH 3/3] Fix CI failure --- .github/workflows/tox.yml | 5 +++++ test/test_util.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 344bef8..218e74f 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -61,6 +61,11 @@ jobs: - name: Install build tools if: matrix.container run: | + # Debian 11 (bullseye) is end-of-life and its packages have moved + # from deb.debian.org/security.debian.org to archive.debian.org. + if grep -qs bullseye /etc/apt/sources.list; then + sed -i -E 's#https?://(deb|security)\.debian\.org/#http://archive.debian.org/#g' /etc/apt/sources.list + fi apt-get update apt-get install -y make gcc g++ pkg-config - name: Install dependencies diff --git a/test/test_util.py b/test/test_util.py index 3f0e63f..6fc3cbf 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -1119,7 +1119,7 @@ def test_with_cwd(self, tmp_path): class TestToDefineDictAdditional: def test_value_with_equals(self): result = util.to_define_dict(["KEY=val=ue"]) - assert result["KEY"] == "val" # split on first '=' + assert result["KEY"] == "val=ue" # split on first '=' only def test_single_entry(self): result = util.to_define_dict(["X=Y"])