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/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..21187ef 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 runs. + .. 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([ 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"])