From 2da6846cf942c9802edfd241aa764e1b8324bf09 Mon Sep 17 00:00:00 2001 From: James Date: Tue, 26 Feb 2019 15:50:12 +0100 Subject: [PATCH] fixing virtualbuildenv (#4583) * fixing virtualbuildenv * fixing broken tests * test --- conans/client/generators/virtualbuildenv.py | 5 +- conans/client/generators/virtualenv.py | 2 +- .../generators/cmake_generator_test.py | 5 +- .../integration/build_environment_test.py | 40 ++++- .../unittests/client/build/cmake_flags.py | 34 ---- .../client/build/visual_environment.py | 157 ------------------ 6 files changed, 45 insertions(+), 198 deletions(-) delete mode 100644 conans/test/unittests/client/build/cmake_flags.py delete mode 100644 conans/test/unittests/client/build/visual_environment.py diff --git a/conans/client/generators/virtualbuildenv.py b/conans/client/generators/virtualbuildenv.py index ce192b15afc..fb408863e22 100644 --- a/conans/client/generators/virtualbuildenv.py +++ b/conans/client/generators/virtualbuildenv.py @@ -12,7 +12,10 @@ def __init__(self, conanfile): compiler = conanfile.settings.get_safe("compiler") if compiler == "Visual Studio": self.env = VisualStudioBuildEnvironment(conanfile).vars_dict - self.env.update(vcvars_dict(conanfile.settings, output=conanfile.output)) + settings_vars = vcvars_dict(conanfile.settings, output=conanfile.output) + for env_var in self.env: + self.env[env_var].extend(settings_vars.pop(env_var, [])) + self.env.update(settings_vars) else: self.env = AutoToolsBuildEnvironment(conanfile).vars_dict diff --git a/conans/client/generators/virtualenv.py b/conans/client/generators/virtualenv.py index c8f76b43d52..c81e164e3e2 100644 --- a/conans/client/generators/virtualenv.py +++ b/conans/client/generators/virtualenv.py @@ -6,7 +6,7 @@ class VirtualEnvGenerator(Generator): - append_with_spaces = ["CPPFLAGS", "CFLAGS", "CXXFLAGS", "LIBS", "LDFLAGS", "CL"] + append_with_spaces = ["CPPFLAGS", "CFLAGS", "CXXFLAGS", "LIBS", "LDFLAGS", "CL", "_LINK_"] def __init__(self, conanfile): self.conanfile = conanfile diff --git a/conans/test/functional/generators/cmake_generator_test.py b/conans/test/functional/generators/cmake_generator_test.py index 091b185123c..5a662d2935d 100644 --- a/conans/test/functional/generators/cmake_generator_test.py +++ b/conans/test/functional/generators/cmake_generator_test.py @@ -1,7 +1,5 @@ -import unittest import os - -from nose.plugins.attrib import attr +import unittest from conans import tools from conans.test.utils.tools import TestClient @@ -40,6 +38,7 @@ def build(self): os_build={os_build} """ + class CMakeGeneratorTest(unittest.TestCase): def _check_build_generator(self, os_build, generator): diff --git a/conans/test/integration/build_environment_test.py b/conans/test/integration/build_environment_test.py index 13882267210..d969d121462 100644 --- a/conans/test/integration/build_environment_test.py +++ b/conans/test/integration/build_environment_test.py @@ -1,8 +1,11 @@ import platform import unittest +from textwrap import dedent from conans.paths import CONANFILE from conans.test.utils.tools import TestClient +from conans.test.utils.cpp_test_files import cpp_hello_conan_files + mylibh = ''' double mean(double a, double b); @@ -59,9 +62,8 @@ def package_info(self): class BuildEnvironmenTest(unittest.TestCase): + @unittest.skipUnless(platform.system() == "Linux", "Requires Linux") def use_build_virtualenv_test(self): - if platform.system() != "Linux": - return client = TestClient(path_with_spaces=False) client.save({CONANFILE: conanfile, "mean.cpp": mylib, "mean.h": mylibh}) client.run("export . lasote/stable") @@ -108,3 +110,37 @@ def build(self): client.run("install . --build missing") client.run("build .") self.assertIn("15", client.user_io.out) + + @unittest.skipUnless(platform.system() == "Windows", "Requires windows") + def use_build_virtualenv_windows_test(self): + files = cpp_hello_conan_files("hello", "0.1", use_cmake=False, with_exe=False) + client = TestClient(path_with_spaces=False) + client.save(files) + client.run("create . user/testing") + files = cpp_hello_conan_files("hello2", "0.1", deps=["hello/0.1@user/testing"], + use_cmake=False, with_exe=False) + client.save(files, clean_first=True) + client.run("create . user/testing") + + reuse_conanfile = dedent(''' + from conans import ConanFile + + class ConanReuseLib(ConanFile): + requires = "hello2/0.1@user/testing" + generators = "virtualbuildenv" + settings = "os", "compiler", "build_type", "arch" + + def build(self): + self.run('activate_build.bat && cl /c /EHsc hello.cpp') + self.run('activate_build.bat && lib hello.obj -OUT:helloapp.lib') + self.run('activate_build.bat && cl /EHsc main.cpp helloapp.lib') + ''') + + reuse = cpp_hello_conan_files("app", "0.1", deps=["hello2/0.1@user/testing"], + use_cmake=False) + reuse["conanfile.py"] = reuse_conanfile + client.save(reuse, clean_first=True) + client.run("install .") + client.run("build .") + client.runner("main.exe", cwd=client.current_folder) + self.assertIn("Hello app;Hello hello2;Hello hello", ";".join(str(client.out).splitlines())) diff --git a/conans/test/unittests/client/build/cmake_flags.py b/conans/test/unittests/client/build/cmake_flags.py deleted file mode 100644 index d6ea74607b5..00000000000 --- a/conans/test/unittests/client/build/cmake_flags.py +++ /dev/null @@ -1,34 +0,0 @@ -import unittest - -from conans import CMake -from conans.client.build.cmake_flags import get_generator -from conans.test.utils.conanfile import MockSettings, ConanFileMock - - -class CMakeGeneratorTest(unittest.TestCase): - - def test_cmake_default_generator_linux(self): - settings = MockSettings({"os_build": "Linux"}) - generator = get_generator(settings) - self.assertEquals("Unix Makefiles", generator) - self._test_default_generator_cmake(settings, "Unix Makefiles") - - def test_cmake_default_generator_osx(self): - settings = MockSettings({"os_build": "Macos"}) - generator = get_generator(settings) - self.assertEquals("Unix Makefiles", generator) - self._test_default_generator_cmake(settings, "Unix Makefiles") - - def test_default_generator_windows(self): - settings = MockSettings({"os_build": "Windows"}) - generator = get_generator(settings) - self.assertEquals("MinGW Makefiles", generator) - self._test_default_generator_cmake(settings, "MinGW Makefiles") - - def _test_default_generator_cmake(self, settings, generator): - conanfile = ConanFileMock() - conanfile.settings = settings - cmake = CMake(conanfile) - self.assertEquals(generator, cmake.generator) - self.assertIn('-G "{}"'.format(generator), cmake.command_line) - diff --git a/conans/test/unittests/client/build/visual_environment.py b/conans/test/unittests/client/build/visual_environment.py deleted file mode 100644 index ce14435df65..00000000000 --- a/conans/test/unittests/client/build/visual_environment.py +++ /dev/null @@ -1,157 +0,0 @@ -import copy -import os - -from conans.client.build.compiler_flags import build_type_define, build_type_flags, format_defines, \ - include_path_option, parallel_compiler_cl_flag, visual_runtime -from conans.client.build.cppstd_flags import cppstd_flag - - -class VisualStudioBuildEnvironment(object): - """ - - LIB: library paths with semicolon separator - - CL: /I (include paths) - - _LINK_: linker options and libraries - - https://msdn.microsoft.com/en-us/library/19z1t1wy.aspx - https://msdn.microsoft.com/en-us/library/fwkeyyhe.aspx - https://msdn.microsoft.com/en-us/library/9s7c9wdw.aspx - https://msdn.microsoft.com/en-us/library/6y6t9esh.aspx - - """ - def __init__(self, conanfile, with_build_type_flags=True): - """ - :param conanfile: ConanFile instance - :param quote_paths: The path directories will be quoted. If you are using the vars together with - environment_append keep it to True, for virtualbuildenv quote_paths=False is required. - """ - self._with_build_type_flags = with_build_type_flags - - self._conanfile = conanfile - self._settings = conanfile.settings - self._deps_cpp_info = conanfile.deps_cpp_info - self._runtime = self._settings.get_safe("compiler.runtime") - - self.include_paths = conanfile.deps_cpp_info.include_paths - self.lib_paths = conanfile.deps_cpp_info.lib_paths - self.defines = copy.copy(conanfile.deps_cpp_info.defines) - self.flags = self._configure_flags() - self.cxx_flags = copy.copy(self._deps_cpp_info.cppflags) - self.link_flags = self._configure_link_flags() - self.libs = conanfile.deps_cpp_info.libs - self.std = self._std_cpp() - self.parallel = False - - def _configure_link_flags(self): - ret = copy.copy(self._deps_cpp_info.exelinkflags) - ret.extend(self._deps_cpp_info.sharedlinkflags) - return ret - - def _configure_flags(self): - ret = copy.copy(self._deps_cpp_info.cflags) - ret.extend(vs_build_type_flags(self._settings, with_flags=self._with_build_type_flags)) - return ret - - def _get_cl_list(self, quotes=True): - # FIXME: It should be managed with the compiler_flags module - # But need further investigation about the quotes and so on, so better to not break anything - if quotes: - ret = ['%s"%s"' % (include_path_option, lib) for lib in self.include_paths] - else: - ret = ['%s%s' % (include_path_option, lib) for lib in self.include_paths] - - runtime = visual_runtime(self._runtime) - if runtime: - ret.append(runtime) - - ret.extend(format_defines(self.defines)) - ret.extend(self.flags) - ret.extend(self.cxx_flags) - - if self.parallel: # Build source in parallel - ret.append(parallel_compiler_cl_flag(output=self._conanfile.output)) - - if self.std: - ret.append(self.std) - - return ret - - def _get_link_list(self): - def format_lib(lib): - return lib if lib.endswith('.lib') else '%s.lib' % lib - - ret = [flag for flag in self.link_flags] # copy - ret.extend([format_lib(lib) for lib in self.libs]) - - return ret - - @property - def vars(self): - """Used in conanfile with environment_append""" - flags = self._get_cl_list() - link_flags = self._get_link_list() - - cl_args = " ".join(flags) + _environ_value_prefix("CL") - link_args = " ".join(link_flags) - lib_paths = ";".join(['%s' % lib for lib in self.lib_paths]) + _environ_value_prefix("LIB", ";") - return {"CL": cl_args, - "LIB": lib_paths, - "_LINK_": link_args} - - @property - def vars_dict(self): - """Used in virtualbuildenvironment""" - # Here we do not quote the include paths, it's going to be used by virtual environment - cl = self._get_cl_list(quotes=False) - link = self._get_link_list() - - lib = [lib for lib in self.lib_paths] # copy - - if os.environ.get("CL", None): - cl.append(os.environ.get("CL")) - - if os.environ.get("LIB", None): - lib.append(os.environ.get("LIB")) - - if os.environ.get("_LINK_", None): - link.append(os.environ.get("_LINK_")) - - ret = {"CL": cl, - "LIB": lib, - "_LINK_": link} - return ret - - def _std_cpp(self): - return vs_std_cpp(self._settings) - - -def vs_build_type_flags(settings, with_flags=True): - build_type = settings.get_safe("build_type") - ret = [] - btd = build_type_define(build_type=build_type) - if btd: - ret.extend(format_defines([btd])) - if with_flags: - # When using to build a vs project we don't want to adjust these flags - btfs = build_type_flags("Visual Studio", build_type=build_type, - vs_toolset=settings.get_safe("compiler.toolset")) - if btfs: - ret.extend(btfs) - - return ret - - -def vs_std_cpp(settings): - if settings.get_safe("compiler") == "Visual Studio" and \ - settings.get_safe("cppstd"): - flag = cppstd_flag(settings.get_safe("compiler"), - settings.get_safe("compiler.version"), - settings.get_safe("cppstd")) - return flag - return None - - -def _environ_value_prefix(var_name, prefix=" "): - if os.environ.get(var_name, ""): - return "%s%s" % (prefix, os.environ.get(var_name, "")) - else: - return ""