diff --git a/conan/tools/_compilers.py b/conan/tools/_compilers.py index b1eaf5ec587..05b4d10c399 100644 --- a/conan/tools/_compilers.py +++ b/conan/tools/_compilers.py @@ -39,3 +39,76 @@ def architecture_flag(settings): "e2k-v6": "-march=elbrus-v6", "e2k-v7": "-march=elbrus-v7"}.get(str(arch), "") return "" + + +def build_type_flags(settings): + """ + returns flags specific to the build type (Debug, Release, etc.) + (-s, -g, /Zi, etc.) + """ + compiler = settings.get_safe("compiler.base") or settings.get_safe("compiler") + + build_type = settings.get_safe("build_type") + vs_toolset = settings.get_safe("compiler.toolset") + if not compiler or not build_type: + return "" + + # https://github.com/Kitware/CMake/blob/d7af8a34b67026feaee558433db3a835d6007e06/ + # Modules/Platform/Windows-MSVC.cmake + if str(compiler) == 'Visual Studio': + if vs_toolset and "clang" in str(vs_toolset): + flags = {"Debug": ["-gline-tables-only", "-fno-inline", "-O0"], + "Release": ["-O2"], + "RelWithDebInfo": ["-gline-tables-only", "-O2", "-fno-inline"], + "MinSizeRel": [] + }.get(build_type, ["-O2", "-Ob2"]) + else: + flags = {"Debug": ["-Zi", "-Ob0", "-Od"], + "Release": ["-O2", "-Ob2"], + "RelWithDebInfo": ["-Zi", "-O2", "-Ob1"], + "MinSizeRel": ["-O1", "-Ob1"], + }.get(build_type, []) + return flags + else: + # https://github.com/Kitware/CMake/blob/f3bbb37b253a1f4a26809d6f132b3996aa2e16fc/ + # Modules/Compiler/GNU.cmake + # clang include the gnu (overriding some things, but not build type) and apple clang + # overrides clang but it doesn't touch clang either + if str(compiler) in ["clang", "gcc", "apple-clang", "qcc", "mcst-lcc"]: + # FIXME: It is not clear that the "-s" is something related with the build type + # cmake is not adjusting it + # -s: Remove all symbol table and relocation information from the executable. + flags = {"Debug": ["-g"], + "Release": ["-O3", "-s"] if str(compiler) == "gcc" else ["-O3"], + "RelWithDebInfo": ["-O2", "-g"], + "MinSizeRel": ["-Os"], + }.get(build_type, []) + return flags + elif str(compiler) == "sun-cc": + # https://github.com/Kitware/CMake/blob/f3bbb37b253a1f4a26809d6f132b3996aa2e16fc/ + # Modules/Compiler/SunPro-CXX.cmake + flags = {"Debug": ["-g"], + "Release": ["-xO3"], + "RelWithDebInfo": ["-xO2", "-g"], + "MinSizeRel": ["-xO2", "-xspace"], + }.get(build_type, []) + return flags + return "" + + +def use_win_mingw(conanfile): + if hasattr(conanfile, 'settings_build'): + os_build = conanfile.settings_build.get_safe('os') + else: + os_build = conanfile.settings.get_safe('os_build') + if os_build is None: # Assume is the same specified in host settings, not cross-building + os_build = conanfile.settings.get_safe("os") + + if os_build == "Windows": + compiler = conanfile.settings.get_safe("compiler") + sub = conanfile.settings.get_safe("os.subsystem") + if sub in ("cygwin", "msys2", "msys") or compiler == "qcc": + return False + else: + return True + return False diff --git a/conan/tools/cmake/utils.py b/conan/tools/cmake/utils.py index 7f572daf165..006d5187d10 100644 --- a/conan/tools/cmake/utils.py +++ b/conan/tools/cmake/utils.py @@ -1,7 +1,7 @@ import os +from conan.tools._compilers import use_win_mingw from conans.errors import ConanException -from conans.util.log import logger def is_multi_configuration(generator): @@ -33,21 +33,7 @@ def get_generator(conanfile): return base compiler_base = conanfile.settings.get_safe("compiler.base") - arch = conanfile.settings.get_safe("arch") - compiler_base_version = conanfile.settings.get_safe("compiler.base.version") - if hasattr(conanfile, 'settings_build'): - os_build = conanfile.settings_build.get_safe('os') - else: - os_build = conanfile.settings.get_safe('os_build') - if os_build is None: # Assume is the same specified in host settings, not cross-building - os_build = conanfile.settings.get_safe("os") - - if not compiler or not compiler_version or not arch: - if os_build == "Windows": - logger.warning("CMake generator could not be deduced from settings") - return None - return "Unix Makefiles" if compiler == "Visual Studio" or compiler_base == "Visual Studio": version = compiler_base_version or compiler_version @@ -63,8 +49,7 @@ def get_generator(conanfile): base = "Visual Studio %s" % _visuals return base - # The generator depends on the build machine, not the target - if os_build == "Windows" and compiler != "qcc": - return "MinGW Makefiles" # it is valid only under Windows + if use_win_mingw(conanfile): + return "MinGW Makefiles" return "Unix Makefiles" diff --git a/conan/tools/gnu/__init__.py b/conan/tools/gnu/__init__.py index 32860e46378..87688ef9e40 100644 --- a/conan/tools/gnu/__init__.py +++ b/conan/tools/gnu/__init__.py @@ -1 +1,5 @@ from .make import MakeToolchain +from conan.tools.gnu.autotoolstoolchain import AutotoolsToolchain +from conan.tools.gnu.autotoolsdeps import AutotoolsDeps +from conan.tools.gnu.autotools import Autotools +from conan.tools.gnu.autotoolsgen import AutotoolsGen diff --git a/conan/tools/gnu/autotools.py b/conan/tools/gnu/autotools.py new file mode 100644 index 00000000000..6c912487b43 --- /dev/null +++ b/conan/tools/gnu/autotools.py @@ -0,0 +1,61 @@ +import platform + +from conan.tools._compilers import use_win_mingw + + +class Autotools(object): + + def __init__(self, conanfile): + """ + FIXME: include_rpath_flags CONAN 2.0 to default True? Could break many packages in center + """ + self._conanfile = conanfile + self._win_bash = False + self._include_rpath_flags = False + self._os = conanfile.settings.get_safe("os") + self._os_version = conanfile.settings.get_safe("os.version") + self._os_sdk = conanfile.settings.get_safe("os.sdk") + self._os_subsystem = conanfile.settings.get_safe("os.subsystem") + self._arch = conanfile.settings.get_safe("arch") + self._build_type = conanfile.settings.get_safe("build_type") + self._compiler = conanfile.settings.get_safe("compiler") + self._compiler_version = conanfile.settings.get_safe("compiler.version") + + # Precalculate build, host, target triplets + # TODO self.build, self.host, self.target = self._get_host_build_target_flags() + + def configure(self): + """ + http://jingfenghanmax.blogspot.com.es/2010/09/configure-with-host-target-and-build.html + https://gcc.gnu.org/onlinedocs/gccint/Configure-Terms.html + """ + if not self._conanfile.should_configure: + return + configure_dir = "." + + # TODO: Management of build, host, target triplet + # TODO: Management of PKG_CONFIG_PATH + # TODO: Implement management of --prefix, bindir, sbindir, libexecdir, libdir, includedir + + cmd = "%s/configure" % configure_dir + self._conanfile.output.info("Calling:\n > %s" % cmd) + self._conanfile.run(cmd) + + def make(self): + """if not self._build_type: + raise ConanException("build_type setting should be defined.") + with environment_append(vars or self.vars): + str_args = args_to_string(args) + cpu_count_option = (("-j%s" % cpu_count(output=self._conanfile.output)) + if ("-j" not in str_args and "nmake" not in make_program.lower()) + else None) + self._conanfile.run("%s" % join_arguments([make_program, target, str_args, + cpu_count_option]), + win_bash=self._win_bash, subsystem=self.subsystem)""" + + make_program = self._conanfile.conf["tools.gnu"].make_program + if make_program is None: + make_program = "mingw32-make" if use_win_mingw(self._conanfile) else "make" + # Need to activate the buildenv if existing + command = make_program + self._conanfile.run(command) diff --git a/conan/tools/gnu/autotoolsdeps.py b/conan/tools/gnu/autotoolsdeps.py new file mode 100644 index 00000000000..74139dcffb6 --- /dev/null +++ b/conan/tools/gnu/autotoolsdeps.py @@ -0,0 +1,106 @@ +from conan.tools.env import Environment +from conans.model.build_info import DepCppInfo + + +class AutotoolsDeps: + def __init__(self, conanfile): + # Set the generic objects before mapping to env vars to let the user + # alter some value + self._conanfile = conanfile + + self.libs = [] + self.system_libs = [] + self.include_paths = [] + self.lib_paths = [] + self.defines = [] + self.cflags = [] + self.cxxflags = [] + self.sharedlinkflags = [] + self.exelinkflags = [] + self.frameworks = [] + self.framework_paths = [] + self.sysroot = None + + def merge_lists(seq1, seq2): + return [s for s in seq1 if s not in seq2] + seq2 + + def merge(dep): + dep_cpp_info = DepCppInfo(dep.cpp_info) # To deal with components + self.system_libs = merge_lists(self.system_libs, dep_cpp_info.system_libs) + self.include_paths = merge_lists(self.include_paths, dep_cpp_info.include_paths) + self.lib_paths = merge_lists(self.lib_paths, dep_cpp_info.lib_paths) + self.framework_paths = merge_lists(self.framework_paths, dep_cpp_info.framework_paths) + self.libs = merge_lists(self.libs, dep_cpp_info.libs) + self.frameworks = merge_lists(self.frameworks, dep_cpp_info.frameworks) + + # Note these are in reverse order + self.defines = merge_lists(dep_cpp_info.defines, self.defines) + self.cxxflags = merge_lists(dep_cpp_info.cxxflags, self.cxxflags) + self.cflags = merge_lists(dep_cpp_info.cflags, self.cflags) + self.sharedlinkflags = merge_lists(dep_cpp_info.sharedlinkflags, self.sharedlinkflags) + self.exelinkflags = merge_lists(dep_cpp_info.exelinkflags, self.exelinkflags) + + if not self.sysroot: + self.sysroot = dep_cpp_info.sysroot + + def _apply_transitive_runenv(next_requires): + # TODO: This visitor is same as VirtualEnv runenv_info one, extract + all_requires = [] + while next_requires: + new_requires = [] + for require in next_requires: + # The explicit has more priority + merge(require) + all_requires.append(require) + + for transitive in require.dependencies.requires: + # Avoid duplication/repetitions + if transitive not in new_requires and transitive not in all_requires: + new_requires.append(transitive) + next_requires = new_requires + + _apply_transitive_runenv(self._conanfile.dependencies.requires) + + def environment(self): + # cpp_flags + cpp_flags = [] + include_paths = ['-I"%s"' % p for p in self.include_paths] + cpp_flags.extend(include_paths) + cpp_flags.extend(["-D%s" % define for define in self.defines]) + + # Libs + libs = ["-l%s" % library for library in self.libs] + + # Ldflags + # TODO: Discuss, should the helper filter frameworks based on compiler? + frameworks = ["-framework %s" % framework for framework in self.frameworks] + frameworks_paths = ["-F %s" % framework_path for framework_path in self.framework_paths] + ldflags = self.sharedlinkflags + ldflags.extend(self.exelinkflags) + ldflags.extend(frameworks) + ldflags.extend(frameworks_paths) + lib_paths = ['-L"%s"' % p for p in self.lib_paths] + ldflags.extend(lib_paths) + + # cflags + cflags = self.cflags + cxxflags = self.cxxflags + + if self.sysroot: + srf = '--sysroot={}'.format(self.sysroot) + cflags.append(srf) + cxxflags.append(srf) + ldflags.append(srf) + + env = Environment() + env.append("CPPFLAGS", cpp_flags) + env.append("LIBS", libs) + env.append("LDFLAGS", ldflags) + env.append("CXXFLAGS", cxxflags) + env.append("CFLAGS", cflags) + return env + + def generate(self): + env = self.environment() + env.save_sh("conanautotoolsdeps.sh") + env.save_bat("conanautotoolsdeps.bat") diff --git a/conan/tools/gnu/autotoolsgen.py b/conan/tools/gnu/autotoolsgen.py new file mode 100644 index 00000000000..ac0b523fefc --- /dev/null +++ b/conan/tools/gnu/autotoolsgen.py @@ -0,0 +1,35 @@ +import platform + +from conan.tools.env import VirtualEnv +from conan.tools.gnu import AutotoolsToolchain, AutotoolsDeps + + +class AutotoolsGen: + def __init__(self, conanfile): + self.toolchain = AutotoolsToolchain(conanfile) + self.deps = AutotoolsDeps(conanfile) + self.env = VirtualEnv(conanfile) + + def build_environment(self): + envtoolchain = self.toolchain.environment() + envdeps = self.deps.environment() + build_env = self.env.build_environment() + build_env.compose(envtoolchain) + build_env.compose(envdeps) + return build_env + + def run_environment(self): + run_env = self.env.run_environment() + return run_env + + def generate(self): + build_env = self.build_environment() + run_env = self.run_environment() + # FIXME: Use settings, not platform Not always defined :( + # os_ = self._conanfile.settings_build.get_safe("os") + if platform.system() == "Windows": + build_env.save_bat("conanbuildenv.bat") + run_env.save_bat("conanrunenv.bat") + else: + build_env.save_sh("conanbuildenv.sh") + run_env.save_sh("conanrunenv.sh") diff --git a/conan/tools/gnu/autotoolstoolchain.py b/conan/tools/gnu/autotoolstoolchain.py new file mode 100644 index 00000000000..c9358d85f70 --- /dev/null +++ b/conan/tools/gnu/autotoolstoolchain.py @@ -0,0 +1,111 @@ +from conan.tools._compilers import architecture_flag, build_type_flags +from conan.tools.env import Environment +# FIXME: need to refactor this import and bring to conan.tools +from conans.client.build.cppstd_flags import cppstd_flag_new + + +class AutotoolsToolchain: + def __init__(self, conanfile): + self._conanfile = conanfile + build_type = self._conanfile.settings.get_safe("build_type") + + # TODO: compiler.runtime for Visual studio? + # defines + self.ndebug = None + if build_type in ['Release', 'RelWithDebInfo', 'MinSizeRel']: + self.ndebug = "NDEBUG" + self.gcc_cxx11_abi = self._cxx11_abi_define() + self.defines = [] + + # cxxflags, cflags + self.cxxflags = [] + self.cflags = [] + self.ldflags = [] + self.libcxx = self._libcxx() + self.fpic = self._conanfile.options.get_safe("fPIC") + + # FIXME: This needs to be imported here into conan.tools + self.cppstd = cppstd_flag_new(self._conanfile.settings) + self.arch_flag = architecture_flag(self._conanfile.settings) + # TODO: This is also covering compilers like Visual Studio, necessary to test it (&remove?) + self.build_type_flags = build_type_flags(self._conanfile.settings) + + def _rpaths_link(self): + # TODO: Not implemented yet + pass + + # TODO: Apple: tools.apple_deployment_target_flag, + # TODO: tools.XCRun(self._conanfile.settings).sdk_path + # TODO: "-arch", tools.to_apple_arch(self._arch) + + def _cxx11_abi_define(self): + # https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html + # The default is libstdc++11, only specify the contrary '_GLIBCXX_USE_CXX11_ABI=0' + settings = self._conanfile.settings + libcxx = settings.get_safe("compiler.libcxx") + if not libcxx: + return + + compiler = settings.get_safe("compiler.base") or settings.get_safe("compiler") + if compiler == "gcc": + if libcxx == 'libstdc++': + return '_GLIBCXX_USE_CXX11_ABI=0' + + def _libcxx(self): + settings = self._conanfile.settings + libcxx = settings.get_safe("compiler.libcxx") + if not libcxx: + return + + compiler = settings.get_safe("compiler.base") or settings.get_safe("compiler") + + if compiler in ['clang', 'apple-clang']: + if libcxx in ['libstdc++', 'libstdc++11']: + return '-stdlib=libstdc++' + elif libcxx == 'libc++': + return '-stdlib=libc++' + elif compiler == 'sun-cc': + return ({"libCstd": "-library=Cstd", + "libstdcxx": "-library=stdcxx4", + "libstlport": "-library=stlport4", + "libstdc++": "-library=stdcpp"}.get(libcxx)) + elif compiler == "qcc": + return "-Y _%s" % str(libcxx) + + def environment(self): + env = Environment() + # defines + if self.ndebug: + self.defines.append(self.ndebug) + if self.gcc_cxx11_abi: + self.defines.append(self.gcc_cxx11_abi) + + if self.libcxx: + self.cxxflags.append(self.libcxx) + + if self.cppstd: + self.cxxflags.append(self.cppstd) + + if self.arch_flag: + self.cxxflags.append(self.arch_flag) + self.cflags.append(self.arch_flag) + self.ldflags.append(self.arch_flag) + + if self.build_type_flags: + self.cxxflags.extend(self.build_type_flags) + self.cflags.extend(self.build_type_flags) + + if self.fpic: + self.cxxflags.append("-fPIC") + self.cflags.append("-fPIC") + + env.append("CPPFLAGS", ["-D{}".format(d) for d in self.defines]) + env.append("CXXFLAGS", self.cxxflags) + env.append("CFLAGS", self.cflags) + env.append("LDFLAGS", self.ldflags) + return env + + def generate(self): + env = self.environment() + env.save_sh("conanautotoolstoolchain.sh") + env.save_bat("conanautotoolstoolchain.bat") diff --git a/conans/client/envvars/environment.py b/conans/client/envvars/environment.py index 161a4c2aba7..9ce9c047264 100644 --- a/conans/client/envvars/environment.py +++ b/conans/client/envvars/environment.py @@ -177,7 +177,7 @@ def _files(env_vars, vars_with_spaces, flavor, activate_tpl, deactivate_tpl, ven activate_content = activate_tpl.render(environment_file=env_filepath, modified_vars=modified_vars, new_vars=new_vars, venv_name=venv_name) - deactivate_content = deactivate_tpl.render(modified_vars=modified_vars, new_vars=new_vars, + deactivate_content = deactivate_tpl.render(modified_vars=modified_vars, new_vars=new_vars, venv_name=venv_name) environment_lines = ["{}={}".format(name, value) for name, value, _ in ret] diff --git a/conans/client/generators/__init__.py b/conans/client/generators/__init__.py index bb5eb3990e9..b80ce5f82d6 100644 --- a/conans/client/generators/__init__.py +++ b/conans/client/generators/__init__.py @@ -67,7 +67,7 @@ def __init__(self): "markdown": MarkdownGenerator} self._new_generators = ["CMakeToolchain", "CMakeDeps", "MakeToolchain", "MSBuildToolchain", "MesonToolchain", "MSBuildDeps", "QbsToolchain", "msbuild", - "VirtualEnv"] + "VirtualEnv", "AutotoolsDeps", "AutotoolsToolchain", "AutotoolsGen"] def add(self, name, generator_class, custom=False): if name not in self._generators or custom: @@ -96,6 +96,15 @@ def _new_generator(self, generator_name, output): elif generator_name == "MakeToolchain": from conan.tools.gnu import MakeToolchain return MakeToolchain + elif generator_name == "AutotoolsDeps": + from conan.tools.gnu import AutotoolsDeps + return AutotoolsDeps + elif generator_name == "AutotoolsToolchain": + from conan.tools.gnu import AutotoolsToolchain + return AutotoolsToolchain + elif generator_name == "AutotoolsGen": + from conan.tools.gnu import AutotoolsGen + return AutotoolsGen elif generator_name == "MSBuildToolchain": from conan.tools.microsoft import MSBuildToolchain return MSBuildToolchain diff --git a/conans/test/assets/sources.py b/conans/test/assets/sources.py index bd9934897b1..052e96b904f 100644 --- a/conans/test/assets/sources.py +++ b/conans/test/assets/sources.py @@ -35,6 +35,11 @@ std::cout << " {{ msg or name }} __x86_64__ defined\n"; #endif + // Libstdc++ + #if defined _GLIBCXX_USE_CXX11_ABI + std::cout << " {{ msg or name }} _GLIBCXX_USE_CXX11_ABI "<< _GLIBCXX_USE_CXX11_ABI << "\n"; + #endif + // COMPILER VERSIONS #if _MSC_VER std::cout << " {{ msg or name }} _MSC_VER" << _MSC_VER<< "\n"; diff --git a/conans/test/functional/toolchains/gnu/__init__.py b/conans/test/functional/toolchains/gnu/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/conans/test/functional/toolchains/gnu/test_autotools.py b/conans/test/functional/toolchains/gnu/test_autotools.py new file mode 100644 index 00000000000..59f7afeb06d --- /dev/null +++ b/conans/test/functional/toolchains/gnu/test_autotools.py @@ -0,0 +1,167 @@ +import os +import platform +import textwrap +import time + +import pytest + +from conan.tools.env.environment import environment_wrap_command +from conans.test.assets.autotools import gen_makefile_am, gen_configure_ac, gen_makefile +from conans.test.assets.sources import gen_function_cpp +from conans.test.functional.utils import check_exe_run +from conans.test.utils.tools import TestClient +from conans.util.files import touch + + +@pytest.mark.skipif(platform.system() != "Linux", reason="Requires Autotools") +@pytest.mark.tool_autotools() +def test_autotools(): + client = TestClient(path_with_spaces=False) + client.run("new hello/0.1 --template=v2_cmake") + client.run("create .") + + main = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) + makefile_am = gen_makefile_am(main="main", main_srcs="main.cpp") + configure_ac = gen_configure_ac() + + conanfile = textwrap.dedent(""" + from conans import ConanFile + from conan.tools.gnu import Autotools + + class TestConan(ConanFile): + requires = "hello/0.1" + settings = "os", "compiler", "arch", "build_type" + exports_sources = "configure.ac", "Makefile.am", "main.cpp" + generators = "AutotoolsGen" + + def build(self): + self.run("aclocal") + self.run("autoconf") + self.run("automake --add-missing --foreign") + autotools = Autotools(self) + autotools.configure() + autotools.make() + """) + + client.save({"conanfile.py": conanfile, + "configure.ac": configure_ac, + "Makefile.am": makefile_am, + "main.cpp": main}, clean_first=True) + client.run("install .") + client.run("build .") + client.run_command("./main") + check_exe_run(client.out, "main", "gcc", None, "Release", "x86_64", None, cxx11_abi=0) + assert "hello/0.1: Hello World Release!" in client.out + + +def build_windows_subsystem(profile, make_program): + """ The AutotoolsDeps can be used also in pure Makefiles, if the makefiles follow + the Autotools conventions + """ + # FIXME: cygwin in CI (my local machine works) seems broken for path with spaces + client = TestClient(path_with_spaces=False) + client.run("new hello/0.1 --template=v2_cmake") + # TODO: Test Windows subsystems in CMake, at least msys is broken + os.rename(os.path.join(client.current_folder, "test_package"), + os.path.join(client.current_folder, "test_package2")) + client.save({"profile": profile}) + client.run("create . --profile=profile") + + main = gen_function_cpp(name="main", includes=["hello"], calls=["hello"]) + makefile = gen_makefile(apps=["app"]) + + conanfile = textwrap.dedent(""" + from conans import ConanFile + from conan.tools.gnu import AutotoolsToolchain, Autotools, AutotoolsDeps + + class TestConan(ConanFile): + requires = "hello/0.1" + settings = "os", "compiler", "arch", "build_type" + exports_sources = "Makefile" + generators = "AutotoolsGen" + + def build(self): + autotools = Autotools(self) + autotools.make() + """) + client.save({"app.cpp": main, + "Makefile": makefile, + "conanfile.py": conanfile, + "profile": profile}, clean_first=True) + + client.run("install . --profile=profile") + cmd = environment_wrap_command("conanbuildenv", make_program, cwd=client.current_folder) + client.run_command(cmd) + client.run_command("app") + # TODO: fill compiler version when ready + check_exe_run(client.out, "main", "gcc", None, "Release", "x86_64", None) + assert "hello/0.1: Hello World Release!" in client.out + + client.save({"app.cpp": gen_function_cpp(name="main", msg="main2", + includes=["hello"], calls=["hello"])}) + # Make sure it is newer + t = time.time() + 1 + touch(os.path.join(client.current_folder, "app.cpp"), (t, t)) + + client.run("build .") + client.run_command("app") + # TODO: fill compiler version when ready + check_exe_run(client.out, "main2", "gcc", None, "Release", "x86_64", None, cxx11_abi=0) + assert "hello/0.1: Hello World Release!" in client.out + return client.out + + +@pytest.mark.tool_cygwin +@pytest.mark.skipif(platform.system() != "Windows", reason="Needs windows") +def test_autotoolsdeps_cygwin(): + gcc = textwrap.dedent(""" + [settings] + os=Windows + os.subsystem=cygwin + compiler=gcc + compiler.version=4.9 + compiler.libcxx=libstdc++ + arch=x86_64 + build_type=Release + """) + out = build_windows_subsystem(gcc, make_program="make") + assert "__MSYS__" not in out + assert "MINGW" not in out + assert "main2 __CYGWIN__1" in out + + +@pytest.mark.tool_mingw64 +@pytest.mark.skipif(platform.system() != "Windows", reason="Needs windows") +def test_autotoolsdeps_mingw_msys(): + gcc = textwrap.dedent(""" + [settings] + os=Windows + compiler=gcc + compiler.version=4.9 + compiler.libcxx=libstdc++ + arch=x86_64 + build_type=Release + """) + out = build_windows_subsystem(gcc, make_program="mingw32-make") + assert "__MSYS__" not in out + assert "main2 __MINGW64__1" in out + + +@pytest.mark.tool_msys2 +@pytest.mark.skipif(platform.system() != "Windows", reason="Needs windows") +def test_autotoolsdeps_msys(): + gcc = textwrap.dedent(""" + [settings] + os=Windows + os.subsystem=msys2 + compiler=gcc + compiler.version=4.9 + compiler.libcxx=libstdc++ + arch=x86_64 + build_type=Release + """) + out = build_windows_subsystem(gcc, make_program="make") + # Msys2 is a rewrite of Msys, using Cygwin + assert "MINGW" not in out + assert "main2 __MSYS__1" in out + assert "main2 __CYGWIN__1" in out diff --git a/conans/test/functional/toolchains/test_make.py b/conans/test/functional/toolchains/gnu/test_make.py similarity index 100% rename from conans/test/functional/toolchains/test_make.py rename to conans/test/functional/toolchains/gnu/test_make.py diff --git a/conans/test/functional/utils.py b/conans/test/functional/utils.py index 29fcc98f8b1..a9180eb8403 100644 --- a/conans/test/functional/utils.py +++ b/conans/test/functional/utils.py @@ -23,7 +23,8 @@ def check_vs_runtime(exe, client, vs_version, build_type, static, architecture=" raise NotImplementedError() -def check_exe_run(output, names, compiler, version, build_type, arch, cppstd, definitions=None): +def check_exe_run(output, names, compiler, version, build_type, arch, cppstd, definitions=None, + cxx11_abi=None): output = str(output) names = names if isinstance(names, list) else [names] @@ -41,6 +42,8 @@ def check_exe_run(output, names, compiler, version, build_type, arch, cppstd, de assert "{} _MSVC_LANG20{}".format(name, cppstd) in output elif compiler == "gcc": + assert "{} __GNUC__".format(name) in output + if arch == "x86": assert "{} __i386__ defined".format(name) in output elif arch == "x86_64": @@ -59,6 +62,9 @@ def check_exe_run(output, names, compiler, version, build_type, arch, cppstd, de "17": "201703"}[cppstd] assert "{} __cplusplus{}".format(name, cppstd_value) in output + if cxx11_abi is not None: + assert "{} _GLIBCXX_USE_CXX11_ABI {}".format(name, cxx11_abi) in output + if definitions: for k, v in definitions.items(): assert "{}: {}".format(k, v) in output