From 0a6f82819078713695e46479e2c64ecdd882f561 Mon Sep 17 00:00:00 2001 From: memsharded Date: Thu, 10 Dec 2020 23:29:35 +0100 Subject: [PATCH 01/22] working in msvc new settings --- conan/tools/cmake/cmake.py | 52 +++++++++++++- conans/client/build/cmake_flags.py | 2 - conans/client/conf/__init__.py | 10 +++ .../test/integration/toolchains/test_cmake.py | 69 +++++++++++++++++++ 4 files changed, 129 insertions(+), 4 deletions(-) diff --git a/conan/tools/cmake/cmake.py b/conan/tools/cmake/cmake.py index ebb9e477964..4aa36955e41 100644 --- a/conan/tools/cmake/cmake.py +++ b/conan/tools/cmake/cmake.py @@ -3,14 +3,62 @@ from conans.client import tools from conans.client.build import join_arguments -from conans.client.build.cmake_flags import is_multi_configuration, get_generator +from conans.client.build.cmake_flags import is_multi_configuration from conan.tools.cmake.base import CMakeToolchainBase from conans.client.tools.files import chdir -from conans.client.tools.oss import cpu_count, args_to_string +from conans.client.tools.oss import cpu_count, args_to_string, get_cross_building_settings from conans.errors import ConanException from conans.model.version import Version from conans.util.conan_v2_mode import conan_v2_behavior from conans.util.files import mkdir +from conans.util.log import logger + + +def get_generator(conanfile): + # Returns the name of the generator to be used by CMake + # TODO: Provide a way to configure the generator from config + if "CONAN_CMAKE_GENERATOR" in os.environ: + return os.environ["CONAN_CMAKE_GENERATOR"] + + compiler = conanfile.settings.get_safe("compiler") + if compiler == "msvc": + toolset = conanfile.settings.get_safe("compiler.toolset") + _visuals = {'140': '14 2015', + '141': '15 2017', + '142': '16 2019'}[toolset] + base = "Visual Studio %s" % _visuals + return base + + compiler_base = conanfile.settings.get_safe("compiler.base") + arch = conanfile.settings.get_safe("arch") + compiler_version = conanfile.settings.get_safe("compiler.version") + compiler_base_version = conanfile.settings.get_safe("compiler.base.version") + os_build, _, _, _ = get_cross_building_settings(conanfile) + + 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 + _visuals = {'8': '8 2005', + '9': '9 2008', + '10': '10 2010', + '11': '11 2012', + '12': '12 2013', + '14': '14 2015', + '15': '15 2017', + '16': '16 2019'}.get(version, "UnknownVersion %s" % version) + 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 + + return "Unix Makefiles" def _validate_recipe(conanfile): diff --git a/conans/client/build/cmake_flags.py b/conans/client/build/cmake_flags.py index 6e99c7d2325..9ee264da0d4 100644 --- a/conans/client/build/cmake_flags.py +++ b/conans/client/build/cmake_flags.py @@ -37,8 +37,6 @@ def get_toolset(settings, generator): def get_generator(conanfile): # Returns the name of the generator to be used by CMake - if "CONAN_CMAKE_GENERATOR" in os.environ: - return os.environ["CONAN_CMAKE_GENERATOR"] compiler = conanfile.settings.get_safe("compiler") compiler_base = conanfile.settings.get_safe("compiler.base") diff --git a/conans/client/conf/__init__.py b/conans/client/conf/__init__.py index eaf399c2cf8..c760303de1f 100644 --- a/conans/client/conf/__init__.py +++ b/conans/client/conf/__init__.py @@ -71,6 +71,16 @@ threads: [None, posix, win32] # Windows MinGW exception: [None, dwarf2, sjlj, seh] # Windows MinGW cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20] + msvc: + runtime: [static, dynamic] + toolset: + 140: + 141: + version: [None, "1910", "1911", "1912", "1913", "1914", "1915", "1916"] + 142: + version: [None, "1920", "1921", "1922", "1923", "1924", "1925", "1926", + "1927", "1928"] + cppstd: [None, 14, 17, 20] Visual Studio: &visual_studio runtime: [MD, MT, MTd, MDd] version: ["8", "9", "10", "11", "12", "14", "15", "16"] diff --git a/conans/test/integration/toolchains/test_cmake.py b/conans/test/integration/toolchains/test_cmake.py index 2a580624800..736b77835fe 100644 --- a/conans/test/integration/toolchains/test_cmake.py +++ b/conans/test/integration/toolchains/test_cmake.py @@ -238,6 +238,75 @@ def _verify_out(marker=">>"): self._incremental_build(build_type=opposite_build_type) self._run_app(opposite_build_type, bin_folder=True, msg="AppImproved") + @parameterized.expand([("Debug", "static", "141", "14", "x86", True), + ("Release", "dynamic", "141", "17", "x86_64", False)]) + def test_toolchain_win_msvc(self, build_type, runtime, toolset, cppstd, arch, shared): + settings = {"compiler": "msvc", + "compiler.toolset": toolset, + "compiler.runtime": runtime, + "compiler.cppstd": cppstd, + "arch": arch, + "build_type": build_type, + } + options = {"shared": shared} + install_out = self._run_build(settings, options) + self.assertIn("WARN: Toolchain: Ignoring fPIC option defined for Windows", install_out) + + # FIXME: Hardcoded VS version and partial toolset check + self.assertIn('CMake command: cmake -G "Visual Studio 15 2017" ' + '-DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake"', self.client.out) + self.assertIn("Microsoft Visual Studio/2017", self.client.out) + + runtime = "MT" if runtime == "static" else "MD" + generator_platform = "x64" if arch == "x86_64" else "Win32" + arch = "x64" if arch == "x86_64" else "X86" + shared_str = "ON" if shared else "OFF" + vals = {"CMAKE_GENERATOR_PLATFORM": generator_platform, + "CMAKE_BUILD_TYPE": "", + "CMAKE_CXX_FLAGS": "/MP1 /DWIN32 /D_WINDOWS /W3 /GR /EHsc", + "CMAKE_CXX_FLAGS_DEBUG": "/%sd /Zi /Ob0 /Od /RTC1" % runtime, + "CMAKE_CXX_FLAGS_RELEASE": "/%s /O2 /Ob2 /DNDEBUG" % runtime, + "CMAKE_C_FLAGS": "/MP1 /DWIN32 /D_WINDOWS /W3", + "CMAKE_C_FLAGS_DEBUG": "/%sd /Zi /Ob0 /Od /RTC1" % runtime, + "CMAKE_C_FLAGS_RELEASE": "/%s /O2 /Ob2 /DNDEBUG" % runtime, + "CMAKE_SHARED_LINKER_FLAGS": "/machine:%s" % arch, + "CMAKE_EXE_LINKER_FLAGS": "/machine:%s" % arch, + "CMAKE_CXX_STANDARD": cppstd, + "CMAKE_CXX_EXTENSIONS": "OFF", + "BUILD_SHARED_LIBS": shared_str} + + def _verify_out(marker=">>"): + if shared: + self.assertIn("app_lib.dll", self.client.out) + else: + self.assertNotIn("app_lib.dll", self.client.out) + + out = str(self.client.out).splitlines() + for k, v in vals.items(): + self.assertIn("%s %s: %s" % (marker, k, v), out) + + _verify_out() + + toolchain = self.client.load("build/conan_toolchain.cmake") + include = self.client.load("build/conan_project_include.cmake") + opposite_build_type = "Release" if build_type == "Debug" else "Debug" + settings["build_type"] = opposite_build_type + self._run_build(settings, options) + # The generated toolchain files must be identical because it is a multi-config + self.assertEqual(toolchain, self.client.load("build/conan_toolchain.cmake")) + self.assertEqual(include, self.client.load("build/conan_project_include.cmake")) + + self._run_app("Release", bin_folder=True) + self._run_app("Debug", bin_folder=True) + + self._modify_code() + time.sleep(1) + self._incremental_build(build_type=build_type) + _verify_out(marker="++>>") + self._run_app(build_type, bin_folder=True, msg="AppImproved") + self._incremental_build(build_type=opposite_build_type) + self._run_app(opposite_build_type, bin_folder=True, msg="AppImproved") + @parameterized.expand([("Debug", "libstdc++", "4.9", "98", "x86_64", True), ("Release", "libstdc++", "4.9", "11", "x86_64", False)]) def test_toolchain_mingw_win(self, build_type, libcxx, version, cppstd, arch, shared): From 72f6bee298d8c492746890b4a8c344b837be53db Mon Sep 17 00:00:00 2001 From: memsharded Date: Sat, 12 Dec 2020 22:52:53 +0100 Subject: [PATCH 02/22] preliminary support for msvc compiler --- conan/tools/cmake/generic.py | 9 ++- conan/tools/cmake/utils.py | 10 ++- conans/client/conf/__init__.py | 8 +- .../test/integration/toolchains/test_cmake.py | 81 ++----------------- 4 files changed, 27 insertions(+), 81 deletions(-) diff --git a/conan/tools/cmake/generic.py b/conan/tools/cmake/generic.py index b1ebcf1c516..6fef03abccc 100644 --- a/conan/tools/cmake/generic.py +++ b/conan/tools/cmake/generic.py @@ -40,7 +40,7 @@ def get_generator_platform(settings, generator): if settings.get_safe("os") == "WindowsCE": return settings.get_safe("os.platform") - if (compiler == "Visual Studio" or compiler_base == "Visual Studio") and \ + if (compiler in ("Visual Studio", "msvc") or compiler_base == "Visual Studio") and \ generator and "Visual" in generator: return {"x86": "Win32", "x86_64": "x64", @@ -221,8 +221,11 @@ def _get_architecture(self): def _deduce_vs_static_runtime(self): settings = self._conanfile.settings - if (settings.get_safe("compiler") == "Visual Studio" and - "MT" in settings.get_safe("compiler.runtime")): + compiler = settings.get_safe("compiler") + runtime = settings.get_safe("compiler.runtime") + if compiler == "Visual Studio" and "MT" in runtime: + return True + if compiler == "msvc" and runtime == "static": return True return False diff --git a/conan/tools/cmake/utils.py b/conan/tools/cmake/utils.py index f8e94138900..95790221ac5 100644 --- a/conan/tools/cmake/utils.py +++ b/conan/tools/cmake/utils.py @@ -47,9 +47,17 @@ def get_generator(conanfile): return os.environ["CONAN_CMAKE_GENERATOR"] compiler = conanfile.settings.get_safe("compiler") + compiler_version = conanfile.settings.get_safe("compiler.version") + if compiler == "msvc": + _visuals = {'140': '14 2015', + '141': '15 2017', + '142': '16 2019'}[compiler_version] + base = "Visual Studio %s" % _visuals + return base + compiler_base = conanfile.settings.get_safe("compiler.base") arch = conanfile.settings.get_safe("arch") - compiler_version = conanfile.settings.get_safe("compiler.version") + compiler_base_version = conanfile.settings.get_safe("compiler.base.version") if hasattr(conanfile, 'settings_build'): os_build = conanfile.settings_build.get_safe('os') diff --git a/conans/client/conf/__init__.py b/conans/client/conf/__init__.py index c760303de1f..efc3fb67e6e 100644 --- a/conans/client/conf/__init__.py +++ b/conans/client/conf/__init__.py @@ -73,13 +73,13 @@ cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20] msvc: runtime: [static, dynamic] - toolset: + version: 140: 141: - version: [None, "1910", "1911", "1912", "1913", "1914", "1915", "1916"] + mscver: [None, "1910", "1911", "1912", "1913", "1914", "1915", "1916"] 142: - version: [None, "1920", "1921", "1922", "1923", "1924", "1925", "1926", - "1927", "1928"] + mscver: [None, "1920", "1921", "1922", "1923", "1924", "1925", "1926", + "1927", "1928"] cppstd: [None, 14, 17, 20] Visual Studio: &visual_studio runtime: [MD, MT, MTd, MDd] diff --git a/conans/test/integration/toolchains/test_cmake.py b/conans/test/integration/toolchains/test_cmake.py index 736b77835fe..8557a7a75da 100644 --- a/conans/test/integration/toolchains/test_cmake.py +++ b/conans/test/integration/toolchains/test_cmake.py @@ -165,10 +165,14 @@ def _run_app(self, build_type, bin_folder=False, msg="App", dyld_path=None): @unittest.skipUnless(platform.system() == "Windows", "Only for windows") class WinTest(Base): - @parameterized.expand([("Debug", "MTd", "15", "14", "x86", "v140", True), - ("Release", "MD", "15", "17", "x86_64", "", False)]) - def test_toolchain_win(self, build_type, runtime, version, cppstd, arch, toolset, shared): - settings = {"compiler": "Visual Studio", + @parameterized.expand([("Visual Studio", "Debug", "MTd", "15", "14", "x86", "v140", True), + ("Visual Studio", "Release", "MD", "15", "17", "x86_64", "", False), + ("msvc", "Debug", "static", "141", "14", "x86", None, True), + ("msvc", "Release", "dynamic", "141", "17", "x86_64", None, False)] + ) + def test_toolchain_win(self, compiler, build_type, runtime, version, cppstd, arch, toolset, + shared): + settings = {"compiler": compiler, "compiler.version": version, "compiler.toolset": toolset, "compiler.runtime": runtime, @@ -238,75 +242,6 @@ def _verify_out(marker=">>"): self._incremental_build(build_type=opposite_build_type) self._run_app(opposite_build_type, bin_folder=True, msg="AppImproved") - @parameterized.expand([("Debug", "static", "141", "14", "x86", True), - ("Release", "dynamic", "141", "17", "x86_64", False)]) - def test_toolchain_win_msvc(self, build_type, runtime, toolset, cppstd, arch, shared): - settings = {"compiler": "msvc", - "compiler.toolset": toolset, - "compiler.runtime": runtime, - "compiler.cppstd": cppstd, - "arch": arch, - "build_type": build_type, - } - options = {"shared": shared} - install_out = self._run_build(settings, options) - self.assertIn("WARN: Toolchain: Ignoring fPIC option defined for Windows", install_out) - - # FIXME: Hardcoded VS version and partial toolset check - self.assertIn('CMake command: cmake -G "Visual Studio 15 2017" ' - '-DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake"', self.client.out) - self.assertIn("Microsoft Visual Studio/2017", self.client.out) - - runtime = "MT" if runtime == "static" else "MD" - generator_platform = "x64" if arch == "x86_64" else "Win32" - arch = "x64" if arch == "x86_64" else "X86" - shared_str = "ON" if shared else "OFF" - vals = {"CMAKE_GENERATOR_PLATFORM": generator_platform, - "CMAKE_BUILD_TYPE": "", - "CMAKE_CXX_FLAGS": "/MP1 /DWIN32 /D_WINDOWS /W3 /GR /EHsc", - "CMAKE_CXX_FLAGS_DEBUG": "/%sd /Zi /Ob0 /Od /RTC1" % runtime, - "CMAKE_CXX_FLAGS_RELEASE": "/%s /O2 /Ob2 /DNDEBUG" % runtime, - "CMAKE_C_FLAGS": "/MP1 /DWIN32 /D_WINDOWS /W3", - "CMAKE_C_FLAGS_DEBUG": "/%sd /Zi /Ob0 /Od /RTC1" % runtime, - "CMAKE_C_FLAGS_RELEASE": "/%s /O2 /Ob2 /DNDEBUG" % runtime, - "CMAKE_SHARED_LINKER_FLAGS": "/machine:%s" % arch, - "CMAKE_EXE_LINKER_FLAGS": "/machine:%s" % arch, - "CMAKE_CXX_STANDARD": cppstd, - "CMAKE_CXX_EXTENSIONS": "OFF", - "BUILD_SHARED_LIBS": shared_str} - - def _verify_out(marker=">>"): - if shared: - self.assertIn("app_lib.dll", self.client.out) - else: - self.assertNotIn("app_lib.dll", self.client.out) - - out = str(self.client.out).splitlines() - for k, v in vals.items(): - self.assertIn("%s %s: %s" % (marker, k, v), out) - - _verify_out() - - toolchain = self.client.load("build/conan_toolchain.cmake") - include = self.client.load("build/conan_project_include.cmake") - opposite_build_type = "Release" if build_type == "Debug" else "Debug" - settings["build_type"] = opposite_build_type - self._run_build(settings, options) - # The generated toolchain files must be identical because it is a multi-config - self.assertEqual(toolchain, self.client.load("build/conan_toolchain.cmake")) - self.assertEqual(include, self.client.load("build/conan_project_include.cmake")) - - self._run_app("Release", bin_folder=True) - self._run_app("Debug", bin_folder=True) - - self._modify_code() - time.sleep(1) - self._incremental_build(build_type=build_type) - _verify_out(marker="++>>") - self._run_app(build_type, bin_folder=True, msg="AppImproved") - self._incremental_build(build_type=opposite_build_type) - self._run_app(opposite_build_type, bin_folder=True, msg="AppImproved") - @parameterized.expand([("Debug", "libstdc++", "4.9", "98", "x86_64", True), ("Release", "libstdc++", "4.9", "11", "x86_64", False)]) def test_toolchain_mingw_win(self, build_type, libcxx, version, cppstd, arch, shared): From 369143b47b43a8e9d865b35881c6ad761dcd2c52 Mon Sep 17 00:00:00 2001 From: memsharded Date: Sun, 13 Dec 2020 00:45:42 +0100 Subject: [PATCH 03/22] fix migration --- conans/client/migrations_settings.py | 110 +++++++++++++++++- .../test/integration/toolchains/test_cmake.py | 30 ++--- 2 files changed, 124 insertions(+), 16 deletions(-) diff --git a/conans/client/migrations_settings.py b/conans/client/migrations_settings.py index 4f16d879064..e4540bda693 100644 --- a/conans/client/migrations_settings.py +++ b/conans/client/migrations_settings.py @@ -1819,4 +1819,112 @@ settings_1_32_0 = settings_1_31_4 -settings_1_33_0 = settings_1_32_0 +settings_1_33_0 = """ +# Only for cross building, 'os_build/arch_build' is the system that runs Conan +os_build: [Windows, WindowsStore, Linux, Macos, FreeBSD, SunOS, AIX] +arch_build: [x86, x86_64, ppc32be, ppc32, ppc64le, ppc64, armv5el, armv5hf, armv6, armv7, armv7hf, armv7s, armv7k, armv8, armv8_32, armv8.3, sparc, sparcv9, mips, mips64, avr, s390, s390x, sh4le] + +# Only for building cross compilation tools, 'os_target/arch_target' is the system for +# which the tools generate code +os_target: [Windows, Linux, Macos, Android, iOS, watchOS, tvOS, FreeBSD, SunOS, AIX, Arduino, Neutrino] +arch_target: [x86, x86_64, ppc32be, ppc32, ppc64le, ppc64, armv5el, armv5hf, armv6, armv7, armv7hf, armv7s, armv7k, armv8, armv8_32, armv8.3, sparc, sparcv9, mips, mips64, avr, s390, s390x, asm.js, wasm, sh4le] + +# Rest of the settings are "host" settings: +# - For native building/cross building: Where the library/program will run. +# - For building cross compilation tools: Where the cross compiler will run. +os: + Windows: + subsystem: [None, cygwin, msys, msys2, wsl] + WindowsStore: + version: ["8.1", "10.0"] + WindowsCE: + platform: ANY + version: ["5.0", "6.0", "7.0", "8.0"] + Linux: + Macos: + version: [None, "10.6", "10.7", "10.8", "10.9", "10.10", "10.11", "10.12", "10.13", "10.14", "10.15", "11.0"] + Android: + api_level: ANY + iOS: + version: ["7.0", "7.1", "8.0", "8.1", "8.2", "8.3", "9.0", "9.1", "9.2", "9.3", "10.0", "10.1", "10.2", "10.3", "11.0", "11.1", "11.2", "11.3", "11.4", "12.0", "12.1", "12.2", "12.3", "12.4", "13.0", "13.1", "13.2", "13.3", "13.4", "13.5", "13.6"] + watchOS: + version: ["4.0", "4.1", "4.2", "4.3", "5.0", "5.1", "5.2", "5.3", "6.0", "6.1"] + tvOS: + version: ["11.0", "11.1", "11.2", "11.3", "11.4", "12.0", "12.1", "12.2", "12.3", "12.4", "13.0"] + FreeBSD: + SunOS: + AIX: + Arduino: + board: ANY + Emscripten: + Neutrino: + version: ["6.4", "6.5", "6.6", "7.0", "7.1"] +arch: [x86, x86_64, ppc32be, ppc32, ppc64le, ppc64, armv4, armv4i, armv5el, armv5hf, armv6, armv7, armv7hf, armv7s, armv7k, armv8, armv8_32, armv8.3, sparc, sparcv9, mips, mips64, avr, s390, s390x, asm.js, wasm, sh4le] +compiler: + sun-cc: + version: ["5.10", "5.11", "5.12", "5.13", "5.14", "5.15"] + threads: [None, posix] + libcxx: [libCstd, libstdcxx, libstlport, libstdc++] + gcc: &gcc + version: ["4.1", "4.4", "4.5", "4.6", "4.7", "4.8", "4.9", + "5", "5.1", "5.2", "5.3", "5.4", "5.5", + "6", "6.1", "6.2", "6.3", "6.4", "6.5", + "7", "7.1", "7.2", "7.3", "7.4", "7.5", + "8", "8.1", "8.2", "8.3", "8.4", + "9", "9.1", "9.2", "9.3", + "10", "10.1"] + libcxx: [libstdc++, libstdc++11] + threads: [None, posix, win32] # Windows MinGW + exception: [None, dwarf2, sjlj, seh] # Windows MinGW + cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20] + msvc: + runtime: [static, dynamic] + version: + 140: + 141: + mscver: [None, "1910", "1911", "1912", "1913", "1914", "1915", "1916"] + 142: + mscver: [None, "1920", "1921", "1922", "1923", "1924", "1925", "1926", + "1927", "1928"] + cppstd: [None, 14, 17, 20] + Visual Studio: &visual_studio + runtime: [MD, MT, MTd, MDd] + version: ["8", "9", "10", "11", "12", "14", "15", "16"] + toolset: [None, v90, v100, v110, v110_xp, v120, v120_xp, + v140, v140_xp, v140_clang_c2, LLVM-vs2012, LLVM-vs2012_xp, + LLVM-vs2013, LLVM-vs2013_xp, LLVM-vs2014, LLVM-vs2014_xp, + LLVM-vs2017, LLVM-vs2017_xp, v141, v141_xp, v141_clang_c2, v142, + llvm, ClangCL] + cppstd: [None, 14, 17, 20] + clang: + version: ["3.3", "3.4", "3.5", "3.6", "3.7", "3.8", "3.9", "4.0", + "5.0", "6.0", "7.0", "7.1", + "8", "9", "10", "11"] + libcxx: [None, libstdc++, libstdc++11, libc++, c++_shared, c++_static] + cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20] + runtime: [None, MD, MT, MTd, MDd] + apple-clang: &apple_clang + version: ["5.0", "5.1", "6.0", "6.1", "7.0", "7.3", "8.0", "8.1", "9.0", "9.1", "10.0", "11.0", "12.0"] + libcxx: [libstdc++, libc++] + cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20] + intel: + version: ["11", "12", "13", "14", "15", "16", "17", "18", "19", "19.1"] + base: + gcc: + <<: *gcc + threads: [None] + exception: [None] + Visual Studio: + <<: *visual_studio + apple-clang: + <<: *apple_clang + qcc: + version: ["4.4", "5.4", "8.3"] + libcxx: [cxx, gpp, cpp, cpp-ne, accp, acpp-ne, ecpp, ecpp-ne] + cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17] + +build_type: [None, Debug, Release, RelWithDebInfo, MinSizeRel] + + +cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20] # Deprecated, use compiler.cppstd +""" diff --git a/conans/test/integration/toolchains/test_cmake.py b/conans/test/integration/toolchains/test_cmake.py index 8557a7a75da..d134a59098f 100644 --- a/conans/test/integration/toolchains/test_cmake.py +++ b/conans/test/integration/toolchains/test_cmake.py @@ -192,7 +192,7 @@ def test_toolchain_win(self, compiler, build_type, runtime, version, cppstd, arc else: self.assertIn("Microsoft Visual Studio/2017", self.client.out) - runtime = "MT" if "MT" in runtime else "MD" + runtime = "MT" if "MT" in runtime or runtime == "static" else "MD" generator_platform = "x64" if arch == "x86_64" else "Win32" arch = "x64" if arch == "x86_64" else "X86" shared_str = "ON" if shared else "OFF" @@ -260,26 +260,26 @@ def test_toolchain_mingw_win(self, build_type, libcxx, version, cppstd, arch, sh '-DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake"', self.client.out) def _verify_out(marker=">>"): - vars = {"CMAKE_GENERATOR_PLATFORM": "", - "CMAKE_BUILD_TYPE": build_type, - "CMAKE_CXX_FLAGS": "-m64", - "CMAKE_CXX_FLAGS_DEBUG": "-g", - "CMAKE_CXX_FLAGS_RELEASE": "-O3 -DNDEBUG", - "CMAKE_C_FLAGS": "-m64", - "CMAKE_C_FLAGS_DEBUG": "-g", - "CMAKE_C_FLAGS_RELEASE": "-O3 -DNDEBUG", - "CMAKE_SHARED_LINKER_FLAGS": "-m64", - "CMAKE_EXE_LINKER_FLAGS": "-m64", - "CMAKE_CXX_STANDARD": cppstd, - "CMAKE_CXX_EXTENSIONS": "OFF", - "BUILD_SHARED_LIBS": "ON" if shared else "OFF"} + cmake_vars = {"CMAKE_GENERATOR_PLATFORM": "", + "CMAKE_BUILD_TYPE": build_type, + "CMAKE_CXX_FLAGS": "-m64", + "CMAKE_CXX_FLAGS_DEBUG": "-g", + "CMAKE_CXX_FLAGS_RELEASE": "-O3 -DNDEBUG", + "CMAKE_C_FLAGS": "-m64", + "CMAKE_C_FLAGS_DEBUG": "-g", + "CMAKE_C_FLAGS_RELEASE": "-O3 -DNDEBUG", + "CMAKE_SHARED_LINKER_FLAGS": "-m64", + "CMAKE_EXE_LINKER_FLAGS": "-m64", + "CMAKE_CXX_STANDARD": cppstd, + "CMAKE_CXX_EXTENSIONS": "OFF", + "BUILD_SHARED_LIBS": "ON" if shared else "OFF"} if shared: self.assertIn("app_lib.dll", self.client.out) else: self.assertNotIn("app_lib.dll", self.client.out) out = str(self.client.out).splitlines() - for k, v in vars.items(): + for k, v in cmake_vars.items(): self.assertIn("%s %s: %s" % (marker, k, v), out) _verify_out() From fb110ba3efa127a09fc58e7d221bb6de1d9be9d1 Mon Sep 17 00:00:00 2001 From: memsharded Date: Tue, 15 Dec 2020 13:49:49 +0100 Subject: [PATCH 04/22] changing to version 19.1, 19.11, etc --- conan/tools/cmake/utils.py | 7 ++++--- conans/client/conf/__init__.py | 10 +++------- conans/client/migrations_settings.py | 10 +++------- conans/test/integration/toolchains/test_cmake.py | 4 ++-- 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/conan/tools/cmake/utils.py b/conan/tools/cmake/utils.py index 95790221ac5..c525e659fa9 100644 --- a/conan/tools/cmake/utils.py +++ b/conan/tools/cmake/utils.py @@ -49,9 +49,10 @@ def get_generator(conanfile): compiler = conanfile.settings.get_safe("compiler") compiler_version = conanfile.settings.get_safe("compiler.version") if compiler == "msvc": - _visuals = {'140': '14 2015', - '141': '15 2017', - '142': '16 2019'}[compiler_version] + version = compiler_version[:4] # Remove the latest version number 19.1X if existing + _visuals = {'19.0': '14 2015', + '19.1': '15 2017', + '19.2': '16 2019'}[version] base = "Visual Studio %s" % _visuals return base diff --git a/conans/client/conf/__init__.py b/conans/client/conf/__init__.py index efc3fb67e6e..6bbb2da8b7c 100644 --- a/conans/client/conf/__init__.py +++ b/conans/client/conf/__init__.py @@ -72,14 +72,10 @@ exception: [None, dwarf2, sjlj, seh] # Windows MinGW cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20] msvc: + version: ["19.0", + "19.1", "19.10", "19.11", "19.12", "19.13", "19.14", "19.15", "19.16", + "19.2", "19.20", "19.21", "19.22", "19.23", "19.24", "19.25", "19.26", "19.27", "19.28"] runtime: [static, dynamic] - version: - 140: - 141: - mscver: [None, "1910", "1911", "1912", "1913", "1914", "1915", "1916"] - 142: - mscver: [None, "1920", "1921", "1922", "1923", "1924", "1925", "1926", - "1927", "1928"] cppstd: [None, 14, 17, 20] Visual Studio: &visual_studio runtime: [MD, MT, MTd, MDd] diff --git a/conans/client/migrations_settings.py b/conans/client/migrations_settings.py index e4540bda693..0481a37d21f 100644 --- a/conans/client/migrations_settings.py +++ b/conans/client/migrations_settings.py @@ -1878,14 +1878,10 @@ exception: [None, dwarf2, sjlj, seh] # Windows MinGW cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20] msvc: + version: ["19.0", + "19.1", "19.10", "19.11", "19.12", "19.13", "19.14", "19.15", "19.16", + "19.2", "19.20", "19.21", "19.22", "19.23", "19.24", "19.25", "19.26", "19.27", "19.28"] runtime: [static, dynamic] - version: - 140: - 141: - mscver: [None, "1910", "1911", "1912", "1913", "1914", "1915", "1916"] - 142: - mscver: [None, "1920", "1921", "1922", "1923", "1924", "1925", "1926", - "1927", "1928"] cppstd: [None, 14, 17, 20] Visual Studio: &visual_studio runtime: [MD, MT, MTd, MDd] diff --git a/conans/test/integration/toolchains/test_cmake.py b/conans/test/integration/toolchains/test_cmake.py index d134a59098f..4f5bc25f661 100644 --- a/conans/test/integration/toolchains/test_cmake.py +++ b/conans/test/integration/toolchains/test_cmake.py @@ -167,8 +167,8 @@ def _run_app(self, build_type, bin_folder=False, msg="App", dyld_path=None): class WinTest(Base): @parameterized.expand([("Visual Studio", "Debug", "MTd", "15", "14", "x86", "v140", True), ("Visual Studio", "Release", "MD", "15", "17", "x86_64", "", False), - ("msvc", "Debug", "static", "141", "14", "x86", None, True), - ("msvc", "Release", "dynamic", "141", "17", "x86_64", None, False)] + ("msvc", "Debug", "static", "19.1", "14", "x86", None, True), + ("msvc", "Release", "dynamic", "19.11", "17", "x86_64", None, False)] ) def test_toolchain_win(self, compiler, build_type, runtime, version, cppstd, arch, toolset, shared): From cfc28fe6e43ee01517e820f0624828929be9a3b4 Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 16 Dec 2020 02:27:00 +0100 Subject: [PATCH 05/22] working on static/dynamic runtime --- conan/tools/cmake/base.py | 18 +---- conan/tools/cmake/generic.py | 72 ++++++++++--------- conans/client/conf/__init__.py | 1 + conans/client/settings_preprocessor.py | 7 +- .../test/integration/toolchains/test_cmake.py | 5 +- 5 files changed, 51 insertions(+), 52 deletions(-) diff --git a/conan/tools/cmake/base.py b/conan/tools/cmake/base.py index a9b1b6f6361..b025e580c3b 100644 --- a/conan/tools/cmake/base.py +++ b/conan/tools/cmake/base.py @@ -85,22 +85,8 @@ class CMakeToolchainBase(object): message("Using Conan toolchain through ${CMAKE_TOOLCHAIN_FILE}.") {% if conan_project_include_cmake %} - if(CMAKE_VERSION VERSION_LESS "3.15") - message(WARNING - " CMake version less than 3.15 doesn't support CMAKE_PROJECT_INCLUDE variable\\n" - " used by Conan toolchain to work. In order to get the same behavior you will\\n" - " need to manually include the generated file after your 'project()' call in the\\n" - " main CMakeLists.txt file:\\n" - " \\n" - " project(YourProject C CXX)\\n" - " include(\\"\\${CMAKE_BINARY_DIR}/conan_project_include.cmake\\")\\n" - " \\n" - " This file contains some definitions and extra adjustments that depend on\\n" - " the build_type and it cannot be done in the toolchain.") - else() - # Will be executed after the 'project()' command - set(CMAKE_PROJECT_INCLUDE "{{ conan_project_include_cmake }}") - endif() + # Will be executed after the 'project()' command + set(CMAKE_PROJECT_INCLUDE "{{ conan_project_include_cmake }}") {% endif %} {% block main %} diff --git a/conan/tools/cmake/generic.py b/conan/tools/cmake/generic.py index 6fef03abccc..433962a44db 100644 --- a/conan/tools/cmake/generic.py +++ b/conan/tools/cmake/generic.py @@ -1,7 +1,9 @@ import os +import re import textwrap from conans.client.tools import cpu_count +from conans.util.files import load from conans.errors import ConanException from conan.tools.cmake.base import CMakeToolchainBase from conan.tools.cmake.utils import get_generator, is_multi_configuration, architecture_flag @@ -123,32 +125,16 @@ class CMakeGenericToolchain(CMakeToolchainBase): message(FATAL_ERROR "This file is expected to be used together with the Conan toolchain") endif() - ########### Utility macros and functions ########### - function(conan_get_policy policy_id policy) - if(POLICY "${policy_id}") - cmake_policy(GET "${policy_id}" _policy) - set(${policy} "${_policy}" PARENT_SCOPE) - else() - set(${policy} "" PARENT_SCOPE) - endif() - endfunction() - ########### End of Utility macros and functions ########### - - # Adjustments that depends on the build_type - {% if vs_static_runtime %} - conan_get_policy(CMP0091 policy_0091) - if(policy_0091 STREQUAL "NEW") - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") - else() - foreach(flag CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE - CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO - CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL - CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG) - if(DEFINED ${flag}) - string(REPLACE "/MD" "/MT" ${flag} "${${flag}}") - endif() - endforeach() - endif() + message(STATUS "Using CMAKE_PROJECT_INCLUDE included file") + + # Adjustments that depends on the build_type/configuration + {% if vs_runtimes %} + {% set genexpr = namespace(str='') %} + {%- for config, value in vs_runtimes.items() -%} + {%- set genexpr.str = genexpr.str + + '$<$' + value|string + '>' %} + {%- endfor -%} + set(CMAKE_MSVC_RUNTIME_LIBRARY "{{ genexpr.str }}") {% endif %} """) @@ -157,7 +143,7 @@ def __init__(self, conanfile, generator=None, generator_platform=None, build_typ super(CMakeGenericToolchain, self).__init__(conanfile) self.fpic = self._deduce_fpic() - self.vs_static_runtime = self._deduce_vs_static_runtime() + self.vs_runtimes = self._runtimes() self.parallel = parallel self.generator = generator or get_generator(self._conanfile) @@ -219,15 +205,33 @@ def _get_architecture(self): # This should be factorized and make it toolchain-private return architecture_flag(self._conanfile.settings) - def _deduce_vs_static_runtime(self): + def _runtimes(self): + # Parsing existing file to get existing configured runtimes + config_dict = {} + if os.path.exists(self.project_include_filename): + existing_include = load(self.project_include_filename) + existing_configs = re.search(r"set\(CMAKE_MSVC_RUNTIME_LIBRARY \"([^)]*)\"\)", + existing_include) + capture = existing_configs.group(1) + matches = re.findall(r"\$<\$([A-Za-z]*)>", capture) + config_dict = dict(matches) + settings = self._conanfile.settings compiler = settings.get_safe("compiler") + build_type = settings.get_safe("build_type") # FIXME: change for configuration runtime = settings.get_safe("compiler.runtime") - if compiler == "Visual Studio" and "MT" in runtime: - return True - if compiler == "msvc" and runtime == "static": - return True - return False + if compiler == "Visual Studio": + config_dict[build_type] = {"MT": "MultiThreaded", + "MTd": "MultiThreadedDebug", + "MD": "MultiThreadedDLL", + "MDd": "MultiThreadedDebugDLL"}[runtime] + if compiler == "msvc": + runtime_type = settings.get_safe("compiler.runtime_type") + rt = "MultiThreadedDebug" if runtime_type == "Debug" else "MultiThreaded" + if runtime != "static": + rt += "DLL" + config_dict[build_type] = rt + return config_dict def _get_libcxx(self): libcxx = self._conanfile.settings.get_safe("compiler.libcxx") @@ -288,5 +292,5 @@ def _get_template_context_data(self): "architecture": self.architecture, "compiler": self.compiler }) - ctxt_project_include.update({'vs_static_runtime': self.vs_static_runtime}) + ctxt_project_include.update({'vs_runtimes': self.vs_runtimes}) return ctxt_toolchain, ctxt_project_include diff --git a/conans/client/conf/__init__.py b/conans/client/conf/__init__.py index 6bbb2da8b7c..8602b5f9c54 100644 --- a/conans/client/conf/__init__.py +++ b/conans/client/conf/__init__.py @@ -76,6 +76,7 @@ "19.1", "19.10", "19.11", "19.12", "19.13", "19.14", "19.15", "19.16", "19.2", "19.20", "19.21", "19.22", "19.23", "19.24", "19.25", "19.26", "19.27", "19.28"] runtime: [static, dynamic] + runtime_type: [Debug, Release] cppstd: [None, 14, 17, 20] Visual Studio: &visual_studio runtime: [MD, MT, MTd, MDd] diff --git a/conans/client/settings_preprocessor.py b/conans/client/settings_preprocessor.py index 83db56048d1..8730b765959 100644 --- a/conans/client/settings_preprocessor.py +++ b/conans/client/settings_preprocessor.py @@ -49,17 +49,22 @@ def check_flag_available(values_range, value, setting_id): def _fill_runtime(settings): try: - runtime = "MDd" if settings.get_safe("build_type") == "Debug" else "MD" if settings.compiler == "Visual Studio": if settings.get_safe("compiler.runtime") is None: + runtime = "MDd" if settings.get_safe("build_type") == "Debug" else "MD" settings.compiler.runtime = runtime msg = "Setting 'compiler.runtime' not declared, automatically adjusted to '%s'" logger.info(msg % runtime) elif settings.compiler == "intel" and settings.get_safe("compiler.base") == "Visual Studio": if settings.get_safe("compiler.base.runtime") is None: + runtime = "MDd" if settings.get_safe("build_type") == "Debug" else "MD" settings.compiler.base.runtime = runtime msg = "Setting 'compiler.base.runtime' not declared, automatically adjusted to '%s'" logger.info(msg % runtime) + elif settings.compiler == "msvc": + if settings.get_safe("compiler.runtime_type") is None: + runtime = "Debug" if settings.get_safe("build_type") == "Debug" else "Release" + settings.compiler.runtime_type = runtime except Exception: # If the settings structure doesn't match these general # asumptions, like unexistant runtime pass diff --git a/conans/test/integration/toolchains/test_cmake.py b/conans/test/integration/toolchains/test_cmake.py index 4f5bc25f661..7b2c814e2d4 100644 --- a/conans/test/integration/toolchains/test_cmake.py +++ b/conans/test/integration/toolchains/test_cmake.py @@ -93,6 +93,7 @@ def build(self): def setUp(self): self.client = TestClient(path_with_spaces=True) + print(self.client.current_folder) conanfile = textwrap.dedent(""" from conans import ConanFile from conans.tools import save @@ -193,6 +194,7 @@ def test_toolchain_win(self, compiler, build_type, runtime, version, cppstd, arc self.assertIn("Microsoft Visual Studio/2017", self.client.out) runtime = "MT" if "MT" in runtime or runtime == "static" else "MD" + runtime = "MD" generator_platform = "x64" if arch == "x86_64" else "Win32" arch = "x64" if arch == "x86_64" else "X86" shared_str = "ON" if shared else "OFF" @@ -229,7 +231,8 @@ def _verify_out(marker=">>"): self._run_build(settings, options) # The generated toolchain files must be identical because it is a multi-config self.assertEqual(toolchain, self.client.load("build/conan_toolchain.cmake")) - self.assertEqual(include, self.client.load("build/conan_project_include.cmake")) + # It is not, the Runtime is added incrementally now + # self.assertEqual(include, self.client.load("build/conan_project_include.cmake")) self._run_app("Release", bin_folder=True) self._run_app("Debug", bin_folder=True) From b245c43e44b2740c07c760ef988ad6f533a2cae7 Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 16 Dec 2020 13:20:53 +0100 Subject: [PATCH 06/22] extracting toolchain checkers to use in CMake --- .../test/integration/toolchains/test_cmake.py | 10 ++++++ .../integration/toolchains/test_msbuild.py | 29 +++------------ conans/test/integration/utils.py | 36 +++++++++++++++++++ 3 files changed, 51 insertions(+), 24 deletions(-) create mode 100644 conans/test/integration/utils.py diff --git a/conans/test/integration/toolchains/test_cmake.py b/conans/test/integration/toolchains/test_cmake.py index 2a580624800..b7e198c7cf8 100644 --- a/conans/test/integration/toolchains/test_cmake.py +++ b/conans/test/integration/toolchains/test_cmake.py @@ -1,5 +1,6 @@ import os import platform +import re import textwrap import time import unittest @@ -10,6 +11,7 @@ from conans.model.ref import ConanFileReference, PackageReference from conans.test.assets.sources import gen_function_cpp, gen_function_h +from conans.test.integration.utils import check_vs_runtime, check_msc_ver from conans.test.utils.tools import TestClient @@ -228,7 +230,15 @@ def _verify_out(marker=">>"): self.assertEqual(include, self.client.load("build/conan_project_include.cmake")) self._run_app("Release", bin_folder=True) + check_msc_ver(toolset or "v141", self.client.out) + self.assertIn("main _MSVC_LANG20{}".format(cppstd), self.client.out) self._run_app("Debug", bin_folder=True) + check_msc_ver(toolset or "v141", self.client.out) + self.assertIn("main _MSVC_LANG20{}".format(cppstd), self.client.out) + check_vs_runtime("build/Release/app.exe", self.client, "15", build_type="Release", + static="MT" in runtime) + check_vs_runtime("build/Debug/app.exe", self.client, "15", build_type="Debug", + static="MT" in runtime) self._modify_code() time.sleep(1) diff --git a/conans/test/integration/toolchains/test_msbuild.py b/conans/test/integration/toolchains/test_msbuild.py index b7df26f1101..581b75865f8 100644 --- a/conans/test/integration/toolchains/test_msbuild.py +++ b/conans/test/integration/toolchains/test_msbuild.py @@ -1,14 +1,13 @@ import os import platform -import re import textwrap import unittest import pytest -from conan.tools.microsoft.visual import vcvars_command from conans.client.tools import vs_installation_path from conans.test.assets.sources import gen_function_cpp +from conans.test.integration.utils import check_vs_runtime, check_msc_ver from conans.test.utils.tools import TestClient @@ -297,17 +296,7 @@ def test_toolchain_win(self): self.assertIn("Visual Studio 2017", client.out) self.assertIn("[vcvarsall.bat] Environment initialized for: 'x86'", client.out) self._run_app(client, "x86", "Release") - version = re.search("main _MSC_VER19([0-9]*)", str(client.out)).group(1) - version = int(version) - self.assertTrue(10 <= version < 20) - self.assertIn("main _MSVC_LANG2017", client.out) - - vcvars = vcvars_command(version="15", architecture="x86") - cmd = ('%s && dumpbin /dependents "Release\\MyApp.exe"' % vcvars) - client.run_command(cmd) - # No other DLLs dependencies rather than kernel, it was MT, statically linked - self.assertIn("KERNEL32.dll", client.out) - self.assertEqual(1, str(client.out).count(".dll")) + check_msc_ver("v141", client.out) @pytest.mark.tool_cmake def test_toolchain_win_debug(self): @@ -340,14 +329,9 @@ def test_toolchain_win_debug(self): self.assertIn("Visual Studio 2017", client.out) self.assertIn("[vcvarsall.bat] Environment initialized for: 'x64'", client.out) self._run_app(client, "x64", "Debug") - self.assertIn("main _MSC_VER1900", client.out) + check_msc_ver("v140", client.out) self.assertIn("main _MSVC_LANG2014", client.out) - - vcvars = vcvars_command(version="15", architecture="amd64") - cmd = ('%s && dumpbin /dependents "x64\\Debug\\MyApp.exe"' % vcvars) - client.run_command(cmd) - self.assertIn("MSVCP140D.dll", client.out) - self.assertIn("VCRUNTIME140D.dll", client.out) + check_vs_runtime("x64/Debug/MyApp.exe", client, "15", static=False, build_type="Debug") @pytest.mark.tool_cmake def test_toolchain_win_multi(self): @@ -389,7 +373,4 @@ def test_toolchain_win_multi(self): self.assertIn("Visual Studio 2017", client.out) self.assertIn("[vcvarsall.bat] Environment initialized for: 'x64'", client.out) self._run_app(client, arch, build_type) - version = re.search("main _MSC_VER19([0-9]*)", str(client.out)).group(1) - version = int(version) - self.assertTrue(10 <= version < 20) - self.assertIn("main _MSVC_LANG2017", client.out) + check_msc_ver("v141", client.out) diff --git a/conans/test/integration/utils.py b/conans/test/integration/utils.py new file mode 100644 index 00000000000..f6f764f2fef --- /dev/null +++ b/conans/test/integration/utils.py @@ -0,0 +1,36 @@ +import re + +from conan.tools.microsoft.visual import vcvars_command + + +def check_vs_runtime(exe, client, vs_version, build_type, static, architecture="amd64"): + vcvars = vcvars_command(version=vs_version, architecture=architecture) + exe = exe.replace("/", "\\") + cmd = ('%s && dumpbin /dependents "%s"' % (vcvars, exe)) + client.run_command(cmd) + + if static: + assert "KERNEL32.dll" in client.out, "Error:{}".format(client.out) + assert "MSVC" not in client.out, "Error:{}".format(client.out) + assert "VCRUNTIME" not in client.out, "Error:{}".format(client.out) + else: + if vs_version == "15": + if build_type == "Debug": + assert "MSVCP140D.dll" in client.out, "Error:{}".format(client.out) + assert "VCRUNTIME140D.dll" in client.out, "Error:{}".format(client.out) + else: + assert "MSVCP140.dll" in client.out, "Error:{}".format(client.out) + assert "VCRUNTIME140.dll" in client.out, "Error:{}".format(client.out) + else: + raise NotImplementedError() + + +def check_msc_ver(toolset, output): + if toolset == "v140": + assert "main _MSC_VER1900" in output, "Error:{}".format(output) + elif toolset == "v141": + version = re.search("main _MSC_VER19([0-9]*)", str(output)).group(1) + version = int(version) + assert 10 <= version < 20, "Error:{}".format(output) + else: + raise NotImplementedError() From c363312ecabf08fcdb4da2cb49bafd0a37a53603 Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 16 Dec 2020 13:22:14 +0100 Subject: [PATCH 07/22] removed unused import --- conans/test/integration/toolchains/test_cmake.py | 1 - 1 file changed, 1 deletion(-) diff --git a/conans/test/integration/toolchains/test_cmake.py b/conans/test/integration/toolchains/test_cmake.py index b7e198c7cf8..fa534f7ab69 100644 --- a/conans/test/integration/toolchains/test_cmake.py +++ b/conans/test/integration/toolchains/test_cmake.py @@ -1,6 +1,5 @@ import os import platform -import re import textwrap import time import unittest From fb6b57b147fd961b5f943db5460f593445006d16 Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 16 Dec 2020 13:25:38 +0100 Subject: [PATCH 08/22] adding checks --- conans/test/integration/toolchains/test_msbuild.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/conans/test/integration/toolchains/test_msbuild.py b/conans/test/integration/toolchains/test_msbuild.py index 581b75865f8..a94fdcac251 100644 --- a/conans/test/integration/toolchains/test_msbuild.py +++ b/conans/test/integration/toolchains/test_msbuild.py @@ -297,6 +297,8 @@ def test_toolchain_win(self): self.assertIn("[vcvarsall.bat] Environment initialized for: 'x86'", client.out) self._run_app(client, "x86", "Release") check_msc_ver("v141", client.out) + self.assertIn("main _MSVC_LANG2017", client.out) + check_vs_runtime("Release/MyApp.exe", client, "15", static=True, build_type="Release") @pytest.mark.tool_cmake def test_toolchain_win_debug(self): From e98d911b7a3b761d2feae19d7973efdf82a9f62c Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 16 Dec 2020 13:27:29 +0100 Subject: [PATCH 09/22] adding check --- conans/test/integration/toolchains/test_msbuild.py | 1 + 1 file changed, 1 insertion(+) diff --git a/conans/test/integration/toolchains/test_msbuild.py b/conans/test/integration/toolchains/test_msbuild.py index a94fdcac251..433f224d469 100644 --- a/conans/test/integration/toolchains/test_msbuild.py +++ b/conans/test/integration/toolchains/test_msbuild.py @@ -376,3 +376,4 @@ def test_toolchain_win_multi(self): self.assertIn("[vcvarsall.bat] Environment initialized for: 'x64'", client.out) self._run_app(client, arch, build_type) check_msc_ver("v141", client.out) + self.assertIn("main _MSVC_LANG2017", client.out) From 3c3a7b32336a820b38cd5bedaf92e027a5d148a8 Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 16 Dec 2020 13:39:27 +0100 Subject: [PATCH 10/22] first proposal --- conan/tools/cmake/generic.py | 13 +++++++------ conans/test/functional/generators/cmake_test.py | 1 - conans/test/integration/toolchains/test_cmake.py | 2 -- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/conan/tools/cmake/generic.py b/conan/tools/cmake/generic.py index 433962a44db..60c1ec0dc2e 100644 --- a/conan/tools/cmake/generic.py +++ b/conan/tools/cmake/generic.py @@ -206,15 +206,16 @@ def _get_architecture(self): return architecture_flag(self._conanfile.settings) def _runtimes(self): - # Parsing existing file to get existing configured runtimes + # Parsing existing toolchain file to get existing configured runtimes config_dict = {} if os.path.exists(self.project_include_filename): existing_include = load(self.project_include_filename) - existing_configs = re.search(r"set\(CMAKE_MSVC_RUNTIME_LIBRARY \"([^)]*)\"\)", - existing_include) - capture = existing_configs.group(1) - matches = re.findall(r"\$<\$([A-Za-z]*)>", capture) - config_dict = dict(matches) + msvc_runtime_value = re.search(r"set\(CMAKE_MSVC_RUNTIME_LIBRARY \"([^)]*)\"\)", + existing_include) + if msvc_runtime_value: + capture = msvc_runtime_value.group(1) + matches = re.findall(r"\$<\$([A-Za-z]*)>", capture) + config_dict = dict(matches) settings = self._conanfile.settings compiler = settings.get_safe("compiler") diff --git a/conans/test/functional/generators/cmake_test.py b/conans/test/functional/generators/cmake_test.py index bde04dcd351..cb4a1f964f8 100644 --- a/conans/test/functional/generators/cmake_test.py +++ b/conans/test/functional/generators/cmake_test.py @@ -484,7 +484,6 @@ def build(self): message("comp compile options: ${tmp}") """) run_test("cmake_find_package", cmakelists) - print(client.out) # Test cmake_find_package generator without components run_test("cmake_find_package", cmakelists, with_components=False) diff --git a/conans/test/integration/toolchains/test_cmake.py b/conans/test/integration/toolchains/test_cmake.py index 02c8458f348..0ddc0d35422 100644 --- a/conans/test/integration/toolchains/test_cmake.py +++ b/conans/test/integration/toolchains/test_cmake.py @@ -94,7 +94,6 @@ def build(self): def setUp(self): self.client = TestClient(path_with_spaces=True) - print(self.client.current_folder) conanfile = textwrap.dedent(""" from conans import ConanFile from conans.tools import save @@ -505,5 +504,4 @@ def build(self): "CMakeLists.txt": cmakelist}) client.run("install .") client.run("build .") - print(client.out) self.assertIn("VALUE OF CONFIG STRING: my new value", client.out) From 3bb3e4da14f1754e4119a772356abbcf4c076faf Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 16 Dec 2020 17:30:13 +0100 Subject: [PATCH 11/22] msvc proposal for runtime --- conan/tools/cmake/android.py | 4 +- conan/tools/cmake/base.py | 19 ++------ conan/tools/cmake/generic.py | 48 +++++++------------ conan/tools/cmake/ios.py | 5 +- .../test/integration/toolchains/test_cmake.py | 33 +++++-------- 5 files changed, 37 insertions(+), 72 deletions(-) diff --git a/conan/tools/cmake/android.py b/conan/tools/cmake/android.py index edaf0599e56..7d7ef390559 100644 --- a/conan/tools/cmake/android.py +++ b/conan/tools/cmake/android.py @@ -82,7 +82,7 @@ def _guess_android_ndk(self): return android_ndk def _get_template_context_data(self): - ctxt_toolchain, _ = super(CMakeAndroidToolchain, self)._get_template_context_data() + ctxt_toolchain = super(CMakeAndroidToolchain, self)._get_template_context_data() ctxt_toolchain.update({ 'CMAKE_SYSTEM_NAME': 'Android', 'CMAKE_SYSTEM_VERSION': self._conanfile.settings.os.api_level, @@ -90,4 +90,4 @@ def _get_template_context_data(self): 'CMAKE_ANDROID_STL_TYPE': self._get_android_stl(), 'CMAKE_ANDROID_NDK': self._guess_android_ndk(), }) - return ctxt_toolchain, {} + return ctxt_toolchain diff --git a/conan/tools/cmake/base.py b/conan/tools/cmake/base.py index b025e580c3b..9dd7710836c 100644 --- a/conan/tools/cmake/base.py +++ b/conan/tools/cmake/base.py @@ -1,4 +1,3 @@ -import os import textwrap import warnings from collections import OrderedDict, defaultdict @@ -33,7 +32,6 @@ def configuration_types(self): class CMakeToolchainBase(object): filename = "conan_toolchain.cmake" - project_include_filename = "conan_project_include.cmake" _toolchain_macros_tpl = textwrap.dedent(""" {% macro iterate_configs(var_config, action) -%} @@ -137,8 +135,7 @@ def _get_templates(self): } def _get_template_context_data(self): - """ Returns two dictionaries, the context for the '_template_toolchain' and - the context for the '_template_project_include' templates. + """ Returns dict, the context for the '_template_toolchain' """ ctxt_toolchain = { "variables": self.variables, @@ -149,7 +146,7 @@ def _get_template_context_data(self): "cmake_module_path": self.cmake_module_path, "build_type": self.build_type, } - return ctxt_toolchain, {} + return ctxt_toolchain def write_toolchain_files(self): # Warning @@ -171,17 +168,7 @@ def generate(self): dict_loader = DictLoader(self._get_templates()) env = Environment(loader=dict_loader) - ctxt_toolchain, ctxt_project_include = self._get_template_context_data() - if ctxt_project_include: - # Make it absolute, wrt to current folder, set by the caller - conan_project_include_cmake = os.path.abspath(self.project_include_filename) - conan_project_include_cmake = conan_project_include_cmake.replace("\\", "/") - t = env.get_template(self.project_include_filename) - content = t.render(**ctxt_project_include) - save(conan_project_include_cmake, content) - - ctxt_toolchain.update({'conan_project_include_cmake': conan_project_include_cmake}) - + ctxt_toolchain = self._get_template_context_data() t = env.get_template(self.filename) content = t.render(**ctxt_toolchain) save(self.filename, content) diff --git a/conan/tools/cmake/generic.py b/conan/tools/cmake/generic.py index 60c1ec0dc2e..a05040fd42b 100644 --- a/conan/tools/cmake/generic.py +++ b/conan/tools/cmake/generic.py @@ -110,6 +110,15 @@ class CMakeGenericToolchain(CMakeToolchainBase): set(CMAKE_CXX_EXTENSIONS {{ cppstd_extensions }}) {%- endif %} + {% if vs_runtimes %} + {% set genexpr = namespace(str='') %} + {%- for config, value in vs_runtimes.items() -%} + {%- set genexpr.str = genexpr.str + + '$<$:' + value|string + '>' %} + {%- endfor -%} + set(CMAKE_MSVC_RUNTIME_LIBRARY "{{ genexpr.str }}") + {% endif %} + set(CMAKE_CXX_FLAGS_INIT "${CONAN_CXX_FLAGS}" CACHE STRING "" FORCE) set(CMAKE_C_FLAGS_INIT "${CONAN_C_FLAGS}" CACHE STRING "" FORCE) set(CMAKE_SHARED_LINKER_FLAGS_INIT "${CONAN_SHARED_LINKER_FLAGS}" CACHE STRING "" FORCE) @@ -117,27 +126,6 @@ class CMakeGenericToolchain(CMakeToolchainBase): {% endblock %} """) - _project_include_filename_tpl = textwrap.dedent(""" - # When using a Conan toolchain, this file is included as the last step of `project()` calls. - # https://cmake.org/cmake/help/latest/variable/CMAKE_PROJECT_INCLUDE.html - - if (NOT CONAN_TOOLCHAIN_INCLUDED) - message(FATAL_ERROR "This file is expected to be used together with the Conan toolchain") - endif() - - message(STATUS "Using CMAKE_PROJECT_INCLUDE included file") - - # Adjustments that depends on the build_type/configuration - {% if vs_runtimes %} - {% set genexpr = namespace(str='') %} - {%- for config, value in vs_runtimes.items() -%} - {%- set genexpr.str = genexpr.str + - '$<$' + value|string + '>' %} - {%- endfor -%} - set(CMAKE_MSVC_RUNTIME_LIBRARY "{{ genexpr.str }}") - {% endif %} - """) - def __init__(self, conanfile, generator=None, generator_platform=None, build_type=None, toolset=None, parallel=True): super(CMakeGenericToolchain, self).__init__(conanfile) @@ -181,8 +169,7 @@ def __init__(self, conanfile, generator=None, generator_platform=None, build_typ def _get_templates(self): templates = super(CMakeGenericToolchain, self)._get_templates() templates.update({ - CMakeToolchainBase.filename: self._toolchain_tpl, - CMakeToolchainBase.project_include_filename: self._project_include_filename_tpl + CMakeToolchainBase.filename: self._toolchain_tpl }) return templates @@ -208,13 +195,13 @@ def _get_architecture(self): def _runtimes(self): # Parsing existing toolchain file to get existing configured runtimes config_dict = {} - if os.path.exists(self.project_include_filename): - existing_include = load(self.project_include_filename) + if os.path.exists(self.filename): + existing_include = load(self.filename) msvc_runtime_value = re.search(r"set\(CMAKE_MSVC_RUNTIME_LIBRARY \"([^)]*)\"\)", existing_include) if msvc_runtime_value: capture = msvc_runtime_value.group(1) - matches = re.findall(r"\$<\$([A-Za-z]*)>", capture) + matches = re.findall(r"\$<\$:([A-Za-z]*)>", capture) config_dict = dict(matches) settings = self._conanfile.settings @@ -277,8 +264,7 @@ def _cppstd(self): return cppstd, cppstd_extensions def _get_template_context_data(self): - ctxt_toolchain, ctxt_project_include = \ - super(CMakeGenericToolchain, self)._get_template_context_data() + ctxt_toolchain = super(CMakeGenericToolchain, self)._get_template_context_data() ctxt_toolchain.update({ "generator_platform": self.generator_platform, "toolset": self.toolset, @@ -291,7 +277,7 @@ def _get_template_context_data(self): "cppstd_extensions": self.cppstd_extensions, "shared_libs": self._build_shared_libs, "architecture": self.architecture, - "compiler": self.compiler + "compiler": self.compiler, + 'vs_runtimes': self.vs_runtimes }) - ctxt_project_include.update({'vs_runtimes': self.vs_runtimes}) - return ctxt_toolchain, ctxt_project_include + return ctxt_toolchain diff --git a/conan/tools/cmake/ios.py b/conan/tools/cmake/ios.py index 397f875e128..04db1f6ab58 100644 --- a/conan/tools/cmake/ios.py +++ b/conan/tools/cmake/ios.py @@ -72,7 +72,6 @@ def _get_architecture(self): "x86_64": "x86_64", "armv8": "arm64", "armv8_32": "arm64_32"}.get(arch, arch) - return None # TODO: refactor, comes from conans.client.tools.apple.py def _apple_sdk_name(self): @@ -92,11 +91,11 @@ def _apple_sdk_name(self): 'tvOS': 'appletvos'}.get(str(os_), None) def _get_template_context_data(self): - ctxt_toolchain, _ = super(CMakeiOSToolchain, self)._get_template_context_data() + ctxt_toolchain = super(CMakeiOSToolchain, self)._get_template_context_data() ctxt_toolchain.update({ "CMAKE_OSX_ARCHITECTURES": self.host_architecture, "CMAKE_SYSTEM_NAME": self.host_os, "CMAKE_SYSTEM_VERSION": self.host_os_version, "CMAKE_OSX_SYSROOT": self.host_sdk_name }) - return ctxt_toolchain, {} + return ctxt_toolchain diff --git a/conans/test/integration/toolchains/test_cmake.py b/conans/test/integration/toolchains/test_cmake.py index 0ddc0d35422..b887ac2737b 100644 --- a/conans/test/integration/toolchains/test_cmake.py +++ b/conans/test/integration/toolchains/test_cmake.py @@ -54,11 +54,9 @@ def build(self): main = gen_function_cpp(name="main", includes=["app"], calls=["app"]) cmakelist = textwrap.dedent(""" - cmake_minimum_required(VERSION 2.8) + cmake_minimum_required(VERSION 3.15) project(App C CXX) - if(CONAN_TOOLCHAIN_INCLUDED AND CMAKE_VERSION VERSION_LESS "3.15") - include("${CMAKE_BINARY_DIR}/conan_project_include.cmake") - endif() + if(NOT CMAKE_TOOLCHAIN_FILE) message(FATAL ">> Not using toolchain") endif() @@ -173,6 +171,7 @@ class WinTest(Base): ) def test_toolchain_win(self, compiler, build_type, runtime, version, cppstd, arch, toolset, shared): + print(self.client.current_folder) settings = {"compiler": compiler, "compiler.version": version, "compiler.toolset": toolset, @@ -183,6 +182,7 @@ def test_toolchain_win(self, compiler, build_type, runtime, version, cppstd, arc } options = {"shared": shared} install_out = self._run_build(settings, options) + print(self.client.out) self.assertIn("WARN: Toolchain: Ignoring fPIC option defined for Windows", install_out) # FIXME: Hardcoded VS version and partial toolset check @@ -193,19 +193,17 @@ def test_toolchain_win(self, compiler, build_type, runtime, version, cppstd, arc else: self.assertIn("Microsoft Visual Studio/2017", self.client.out) - runtime = "MT" if "MT" in runtime or runtime == "static" else "MD" - runtime = "MD" generator_platform = "x64" if arch == "x86_64" else "Win32" arch = "x64" if arch == "x86_64" else "X86" shared_str = "ON" if shared else "OFF" vals = {"CMAKE_GENERATOR_PLATFORM": generator_platform, "CMAKE_BUILD_TYPE": "", - "CMAKE_CXX_FLAGS": "/MP1 /DWIN32 /D_WINDOWS /W3 /GR /EHsc", - "CMAKE_CXX_FLAGS_DEBUG": "/%sd /Zi /Ob0 /Od /RTC1" % runtime, - "CMAKE_CXX_FLAGS_RELEASE": "/%s /O2 /Ob2 /DNDEBUG" % runtime, - "CMAKE_C_FLAGS": "/MP1 /DWIN32 /D_WINDOWS /W3", - "CMAKE_C_FLAGS_DEBUG": "/%sd /Zi /Ob0 /Od /RTC1" % runtime, - "CMAKE_C_FLAGS_RELEASE": "/%s /O2 /Ob2 /DNDEBUG" % runtime, + "CMAKE_CXX_FLAGS": "/MP1 /DWIN32 /D_WINDOWS /GR /EHsc", + "CMAKE_CXX_FLAGS_DEBUG": "/Zi /Ob0 /Od /RTC1", + "CMAKE_CXX_FLAGS_RELEASE": "/O2 /Ob2 /DNDEBUG", + "CMAKE_C_FLAGS": "/MP1 /DWIN32 /D_WINDOWS", + "CMAKE_C_FLAGS_DEBUG": "/Zi /Ob0 /Od /RTC1", + "CMAKE_C_FLAGS_RELEASE": "/O2 /Ob2 /DNDEBUG", "CMAKE_SHARED_LINKER_FLAGS": "/machine:%s" % arch, "CMAKE_EXE_LINKER_FLAGS": "/machine:%s" % arch, "CMAKE_CXX_STANDARD": cppstd, @@ -224,15 +222,9 @@ def _verify_out(marker=">>"): _verify_out() - toolchain = self.client.load("build/conan_toolchain.cmake") - include = self.client.load("build/conan_project_include.cmake") opposite_build_type = "Release" if build_type == "Debug" else "Debug" settings["build_type"] = opposite_build_type self._run_build(settings, options) - # The generated toolchain files must be identical because it is a multi-config - self.assertEqual(toolchain, self.client.load("build/conan_toolchain.cmake")) - # It is not, the Runtime is added incrementally now - # self.assertEqual(include, self.client.load("build/conan_project_include.cmake")) self._run_app("Release", bin_folder=True) check_msc_ver(toolset or "v141", self.client.out) @@ -240,10 +232,11 @@ def _verify_out(marker=">>"): self._run_app("Debug", bin_folder=True) check_msc_ver(toolset or "v141", self.client.out) self.assertIn("main _MSVC_LANG20{}".format(cppstd), self.client.out) + static = (runtime == "static" or "MT" in runtime) check_vs_runtime("build/Release/app.exe", self.client, "15", build_type="Release", - static="MT" in runtime) + static=static) check_vs_runtime("build/Debug/app.exe", self.client, "15", build_type="Debug", - static="MT" in runtime) + static=static) self._modify_code() time.sleep(1) From ef36fd2e00cff3df904d83a46d69f02e8536bcf1 Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 16 Dec 2020 17:43:28 +0100 Subject: [PATCH 12/22] fix migration test --- conans/client/migrations_settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/conans/client/migrations_settings.py b/conans/client/migrations_settings.py index 8eab7c0477b..90cbeb7f939 100644 --- a/conans/client/migrations_settings.py +++ b/conans/client/migrations_settings.py @@ -1883,6 +1883,7 @@ "19.1", "19.10", "19.11", "19.12", "19.13", "19.14", "19.15", "19.16", "19.2", "19.20", "19.21", "19.22", "19.23", "19.24", "19.25", "19.26", "19.27", "19.28"] runtime: [static, dynamic] + runtime_type: [Debug, Release] cppstd: [None, 14, 17, 20] Visual Studio: &visual_studio runtime: [MD, MT, MTd, MDd] From 2000c850eaeaebb994062a819aa30b4142e1a875 Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 16 Dec 2020 18:36:28 +0100 Subject: [PATCH 13/22] fixing tests --- .../integration/toolchains/cmake/test_ninja.py | 14 ++++---------- conans/test/integration/toolchains/test_cmake.py | 6 ++++-- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/conans/test/integration/toolchains/cmake/test_ninja.py b/conans/test/integration/toolchains/cmake/test_ninja.py index e2ebef0003c..af4e422dfa0 100644 --- a/conans/test/integration/toolchains/cmake/test_ninja.py +++ b/conans/test/integration/toolchains/cmake/test_ninja.py @@ -4,6 +4,7 @@ from conan.tools.microsoft.visual import vcvars_command from conans.test.assets.sources import gen_function_cpp +from conans.test.integration.utils import check_vs_runtime from conans.test.utils.tools import TestClient from conans.client.tools import which @@ -13,11 +14,8 @@ class CMakeNinjaTestCase(unittest.TestCase): main_cpp = gen_function_cpp(name="main") cmake = textwrap.dedent(""" - cmake_minimum_required(VERSION 2.8.12) + cmake_minimum_required(VERSION 3.15) project(App CXX) - if(CMAKE_VERSION VERSION_LESS "3.15") - include(${CMAKE_BINARY_DIR}/conan_project_include.cmake) - endif() set(CMAKE_VERBOSE_MAKEFILE ON) add_executable(App main.cpp) install(TARGETS App RUNTIME DESTINATION bin) @@ -106,9 +104,7 @@ def test_locally_build_windows(self): self.assertIn("main _MSC_VER19", client.out) self.assertIn("main _MSVC_LANG2014", client.out) - client.run_command('{} && dumpbin /dependents /summary /directives "App.exe"'.format(vcvars)) - self.assertIn("MSVCP140.dll", client.out) - self.assertIn("VCRUNTIME140.dll", client.out) + check_vs_runtime("App.exe", client, "15", build_type="Release", static=False) @unittest.skipIf(platform.system() != "Windows", "Only windows") def test_locally_build_windows_debug(self): @@ -142,6 +138,4 @@ def test_locally_build_windows_debug(self): self.assertIn("main _MSC_VER19", client.out) self.assertIn("main _MSVC_LANG2014", client.out) - client.run_command('{} && dumpbin /dependents /summary /directives "App.exe"'.format(vcvars)) - self.assertIn("KERNEL32.dll", client.out) - self.assertEqual(1, str(client.out).count(".dll")) + check_vs_runtime("App.exe", client, "15", build_type="Debug", static=True) diff --git a/conans/test/integration/toolchains/test_cmake.py b/conans/test/integration/toolchains/test_cmake.py index b887ac2737b..427d0d0056d 100644 --- a/conans/test/integration/toolchains/test_cmake.py +++ b/conans/test/integration/toolchains/test_cmake.py @@ -171,7 +171,6 @@ class WinTest(Base): ) def test_toolchain_win(self, compiler, build_type, runtime, version, cppstd, arch, toolset, shared): - print(self.client.current_folder) settings = {"compiler": compiler, "compiler.version": version, "compiler.toolset": toolset, @@ -182,7 +181,6 @@ def test_toolchain_win(self, compiler, build_type, runtime, version, cppstd, arc } options = {"shared": shared} install_out = self._run_build(settings, options) - print(self.client.out) self.assertIn("WARN: Toolchain: Ignoring fPIC option defined for Windows", install_out) # FIXME: Hardcoded VS version and partial toolset check @@ -224,6 +222,10 @@ def _verify_out(marker=">>"): opposite_build_type = "Release" if build_type == "Debug" else "Debug" settings["build_type"] = opposite_build_type + if runtime == "MTd": + settings["compiler.runtime"] = "MT" + if runtime == "MD": + settings["compiler.runtime"] = "MDd" self._run_build(settings, options) self._run_app("Release", bin_folder=True) From 640b1348d15ea2e086eec0e2ec7b6298cdc04633 Mon Sep 17 00:00:00 2001 From: memsharded Date: Thu, 17 Dec 2020 00:41:11 +0100 Subject: [PATCH 14/22] binary compatibility --- conans/client/graph/graph_binaries.py | 3 +++ conans/model/info.py | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/conans/client/graph/graph_binaries.py b/conans/client/graph/graph_binaries.py index aa74c5acfb6..bac67a77584 100644 --- a/conans/client/graph/graph_binaries.py +++ b/conans/client/graph/graph_binaries.py @@ -339,6 +339,9 @@ def _compute_package_id(self, node, default_package_id_mode, default_python_requ python_requires=python_requires, default_python_requires_id_mode= default_python_requires_id_mode) + msvc_compatible = conanfile.info.msvc_compatible() + if msvc_compatible: + conanfile.compatible_packages.append(msvc_compatible) # Once we are done, call package_id() to narrow and change possible values with conanfile_exception_formatter(str(conanfile), "package_id"): diff --git a/conans/model/info.py b/conans/model/info.py index e5d492d4cbf..587963a85dc 100644 --- a/conans/model/info.py +++ b/conans/model/info.py @@ -575,6 +575,27 @@ def header_only(self): self.options.clear() self.requires.clear() + def msvc_compatible(self): + if self.settings.compiler != "msvc": + return + + compatible = self.clone() + version = compatible.settings.compiler.version + runtime = compatible.settings.compiler.runtime + runtime_type = compatible.settings.compiler.runtime_type + + compatible.settings.compiler = "Visual Studio" + version = str(version)[:4] + _visuals = {'19.0': '14', + '19.1': '15', + '19.2': '16'} + compatible.settings.compiler.version = _visuals[version] + runtime = "MT" if runtime == "static" else "MD" + if runtime_type == "Debug": + runtime = "{}d".format(runtime) + compatible.settings.compiler.runtime = runtime + return compatible + def vs_toolset_compatible(self): """Default behaviour, same package for toolset v140 with compiler=Visual Studio 15 than using Visual Studio 14""" From 59c2ab2968143a674e6b01d26d0f431eae554a47 Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 23 Dec 2020 11:59:15 +0100 Subject: [PATCH 15/22] fix test --- conans/test/integration/toolchains/test_cmake.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conans/test/integration/toolchains/test_cmake.py b/conans/test/integration/toolchains/test_cmake.py index 5d4720bd930..5bbc7c60f70 100644 --- a/conans/test/integration/toolchains/test_cmake.py +++ b/conans/test/integration/toolchains/test_cmake.py @@ -165,7 +165,7 @@ class WinTest(Base): @parameterized.expand([("Visual Studio", "Debug", "MTd", "15", "14", "x86", "v140", True), ("Visual Studio", "Release", "MD", "15", "17", "x86_64", "", False), ("msvc", "Debug", "static", "19.1", "14", "x86", None, True), - ("msvc", "Release", "dynamic", "19.11", "17", "x86_64", None, False) + ("msvc", "Release", "dynamic", "19.11", "17", "x86_64", None, False)] ) def test_toolchain_win(self, compiler, build_type, runtime, version, cppstd, arch, toolset, shared): From 0766d143ec9a903b6f9fae8623005cd31ed32ef4 Mon Sep 17 00:00:00 2001 From: memsharded Date: Mon, 28 Dec 2020 00:32:08 +0100 Subject: [PATCH 16/22] opt-out compatibility and helper for runtime flag --- conan/tools/microsoft/__init__.py | 14 ++++++++++++ conans/client/conf/__init__.py | 8 +++++++ conans/client/graph/graph_binaries.py | 7 +++--- .../functional/package_id/compatible_test.py | 15 +++++++++++++ .../integration/toolchains/test_msbuild.py | 22 +++++++++++++++++++ 5 files changed, 63 insertions(+), 3 deletions(-) diff --git a/conan/tools/microsoft/__init__.py b/conan/tools/microsoft/__init__.py index 2ad4777a326..68d390c3fc7 100644 --- a/conan/tools/microsoft/__init__.py +++ b/conan/tools/microsoft/__init__.py @@ -2,3 +2,17 @@ from .toolchain import MSBuildToolchain from .msbuild import MSBuild from .msbuilddeps import MSBuildDeps + + +def msvc_runtime_flag(conanfile): + settings = conanfile.settings + compiler = settings.get_safe("compiler") + runtime = settings.get_safe("compiler.runtime") + if compiler == "Visual Studio": + return runtime + if compiler == "msvc": + runtime_type = settings.get_safe("compiler.runtime_type") + if runtime == "static": + return "MTd" if runtime_type == "Debug" else "MT" + else: + return "MDd" if runtime_type == "Debug" else "MD" diff --git a/conans/client/conf/__init__.py b/conans/client/conf/__init__.py index 8602b5f9c54..57bee68e7cd 100644 --- a/conans/client/conf/__init__.py +++ b/conans/client/conf/__init__.py @@ -492,6 +492,14 @@ def full_transitive_package_id(self): except ConanException: return None + @property + def msvc_visual_incompatible(self): + try: + visual_comp = self.get_item("general.msvc_visual_incompatible") + return visual_comp.lower() in ("1", "true") + except ConanException: + return None + @property def short_paths_home(self): short_paths_home = get_env("CONAN_USER_HOME_SHORT") diff --git a/conans/client/graph/graph_binaries.py b/conans/client/graph/graph_binaries.py index bac67a77584..4a0980fcd4e 100644 --- a/conans/client/graph/graph_binaries.py +++ b/conans/client/graph/graph_binaries.py @@ -339,9 +339,10 @@ def _compute_package_id(self, node, default_package_id_mode, default_python_requ python_requires=python_requires, default_python_requires_id_mode= default_python_requires_id_mode) - msvc_compatible = conanfile.info.msvc_compatible() - if msvc_compatible: - conanfile.compatible_packages.append(msvc_compatible) + if not self._cache.config.msvc_visual_incompatible: + msvc_compatible = conanfile.info.msvc_compatible() + if msvc_compatible: + conanfile.compatible_packages.append(msvc_compatible) # Once we are done, call package_id() to narrow and change possible values with conanfile_exception_formatter(str(conanfile), "package_id"): diff --git a/conans/test/functional/package_id/compatible_test.py b/conans/test/functional/package_id/compatible_test.py index f35d6b9d9c6..ca235c5bbf4 100644 --- a/conans/test/functional/package_id/compatible_test.py +++ b/conans/test/functional/package_id/compatible_test.py @@ -492,3 +492,18 @@ def package_id(self): self.assertIn("pkg/0.1@user/testing:1ebf4db7209535776307f9cd06e00d5a8034bc84 - Cache", client.out) self.assertIn("pkg/0.1@user/testing: Already installed!", client.out) + + +def test_msvc_visual_incompatible(): + conanfile = GenConanfile().with_settings("os", "compiler", "build_type", "arch") + client = TestClient() + client.save({"conanfile.py": conanfile}) + client.run('create . pkg/0.1@ -s os=Windows -s compiler="Visual Studio" -s compiler.version=15 ' + '-s compiler.runtime=MD -s build_type=Release -s arch=x86_64') + client.run("install pkg/0.1@ -s os=Windows -s compiler=msvc -s compiler.version=19.1 " + "-s compiler.runtime=dynamic -s build_type=Release -s arch=x86_64") + assert "Using compatible package" in client.out + client.run("config set general.msvc_visual_incompatible=1") + client.run("install pkg/0.1@ -s os=Windows -s compiler=msvc -s compiler.version=19.1 " + "-s compiler.runtime=dynamic -s build_type=Release -s arch=x86_64", assert_error=True) + assert "ERROR: Missing prebuilt package for 'pkg/0.1'" in client.out diff --git a/conans/test/integration/toolchains/test_msbuild.py b/conans/test/integration/toolchains/test_msbuild.py index 433f224d469..a194130ea01 100644 --- a/conans/test/integration/toolchains/test_msbuild.py +++ b/conans/test/integration/toolchains/test_msbuild.py @@ -219,6 +219,28 @@ """ +@pytest.mark.tool_visual_studio +def test_msvc_runtime_flag(): + client = TestClient() + conanfile = textwrap.dedent(""" + from conans import ConanFile + from conan.tools.microsoft import msvc_runtime_flag + class App(ConanFile): + settings = "os", "arch", "compiler", "build_type" + + def generate(self): + self.output.info("MSVC FLAG={}!!".format(msvc_runtime_flag(self))) + """) + client.save({"conanfile.py": conanfile}) + client.run('install . -s compiler="Visual Studio" -s compiler.version=15 -s compiler.runtime=MD') + assert "MSVC FLAG=MD!!" in client.out + client.run('install . -s compiler=msvc -s compiler.version=19.1 -s compiler.runtime=static ' + '-s compiler.runtime_type=Debug') + assert "MSVC FLAG=MTd!!" in client.out + client.run('install . -s compiler=msvc -s compiler.version=19.1 -s compiler.runtime=dynamic') + assert "MSVC FLAG=MD!!" in client.out + + @unittest.skipUnless(platform.system() == "Windows", "Only for windows") @pytest.mark.tool_visual_studio class WinTest(unittest.TestCase): From 315de0590057fa6553fa173c7ddf66048067c1f4 Mon Sep 17 00:00:00 2001 From: memsharded Date: Mon, 28 Dec 2020 20:25:22 +0100 Subject: [PATCH 17/22] review --- conan/tools/microsoft/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/conan/tools/microsoft/__init__.py b/conan/tools/microsoft/__init__.py index 68d390c3fc7..29940fbaa1d 100644 --- a/conan/tools/microsoft/__init__.py +++ b/conan/tools/microsoft/__init__.py @@ -12,7 +12,7 @@ def msvc_runtime_flag(conanfile): return runtime if compiler == "msvc": runtime_type = settings.get_safe("compiler.runtime_type") - if runtime == "static": - return "MTd" if runtime_type == "Debug" else "MT" - else: - return "MDd" if runtime_type == "Debug" else "MD" + runtime = "MT" if runtime == "static" else "MD" + if runtime_type == "Debug": + runtime = "{}d".format(runtime) + return runtime From 72adaf3dbc1b91e5a0474c58a6bbfbad6f046d48 Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 13 Jan 2021 02:22:05 +0100 Subject: [PATCH 18/22] protection --- conan/tools/cmake/utils.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/conan/tools/cmake/utils.py b/conan/tools/cmake/utils.py index 3263df02173..7973585e02d 100644 --- a/conan/tools/cmake/utils.py +++ b/conan/tools/cmake/utils.py @@ -1,5 +1,6 @@ import os +from conans.errors import ConanException from conans.util.log import logger @@ -50,10 +51,16 @@ def get_generator(conanfile): compiler_version = conanfile.settings.get_safe("compiler.version") if compiler == "msvc": + if compiler_version is None: + raise ConanException("compiler.version must be defined") version = compiler_version[:4] # Remove the latest version number 19.1X if existing - _visuals = {'19.0': '14 2015', - '19.1': '15 2017', - '19.2': '16 2019'}[version] + try: + _visuals = {'19.0': '14 2015', + '19.1': '15 2017', + '19.2': '16 2019'}[version] + except KeyError: + raise ConanException("compiler.version '{}' doesn't map " + "to a known VS version".format(version)) base = "Visual Studio %s" % _visuals return base From b252e836b29d04c6215b65c329aa136402e9a06c Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 13 Jan 2021 20:19:09 +0100 Subject: [PATCH 19/22] adding msvc cppstd flag --- conans/client/build/cppstd_flags.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/conans/client/build/cppstd_flags.py b/conans/client/build/cppstd_flags.py index a1e58de92a6..b4c3e7f3b9d 100644 --- a/conans/client/build/cppstd_flags.py +++ b/conans/client/build/cppstd_flags.py @@ -32,6 +32,7 @@ def cppstd_flag(compiler, compiler_version, cppstd, compiler_base=None): "clang": _cppstd_clang, "apple-clang": _cppstd_apple_clang, "Visual Studio": _cppstd_visualstudio, + "msvc": _cppstd_msvc, "intel": cppstd_intel, "mcst-lcc": _cppstd_mcst_lcc}.get(str(compiler), None) flag = None @@ -112,6 +113,23 @@ def _cppstd_visualstudio(visual_version, cppstd): return "/std:%s" % flag if flag else None +def _cppstd_msvc(visual_version, cppstd): + # https://docs.microsoft.com/en-us/cpp/build/reference/std-specify-language-standard-version + v14 = None + v17 = None + v20 = None + + if Version(visual_version) >= "19.0": + v14 = "c++14" + v17 = "c++latest" + if Version(visual_version) >= "19.1": + v17 = "c++17" + v20 = "c++latest" + + flag = {"14": v14, "17": v17, "20": v20}.get(str(cppstd), None) + return "/std:%s" % flag if flag else None + + def _cppstd_apple_clang(clang_version, cppstd): """ Inspired in: From 637a9e795e102c2d02c1d85ca06328e1cad3cb1b Mon Sep 17 00:00:00 2001 From: memsharded Date: Wed, 13 Jan 2021 20:34:27 +0100 Subject: [PATCH 20/22] fix migration test --- conans/client/conf/__init__.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/conans/client/conf/__init__.py b/conans/client/conf/__init__.py index 4d2925f3609..b623768e271 100644 --- a/conans/client/conf/__init__.py +++ b/conans/client/conf/__init__.py @@ -75,13 +75,6 @@ threads: [None, posix, win32] # Windows MinGW exception: [None, dwarf2, sjlj, seh] # Windows MinGW cppstd: [None, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20] - msvc: - version: ["19.0", - "19.1", "19.10", "19.11", "19.12", "19.13", "19.14", "19.15", "19.16", - "19.2", "19.20", "19.21", "19.22", "19.23", "19.24", "19.25", "19.26", "19.27", "19.28"] - runtime: [static, dynamic] - runtime_type: [Debug, Release] - cppstd: [None, 14, 17, 20] Visual Studio: &visual_studio runtime: [MD, MT, MTd, MDd] version: ["8", "9", "10", "11", "12", "14", "15", "16"] @@ -91,6 +84,13 @@ LLVM-vs2017, LLVM-vs2017_xp, v141, v141_xp, v141_clang_c2, v142, llvm, ClangCL] cppstd: [None, 14, 17, 20] + msvc: + version: ["19.0", + "19.1", "19.10", "19.11", "19.12", "19.13", "19.14", "19.15", "19.16", + "19.2", "19.20", "19.21", "19.22", "19.23", "19.24", "19.25", "19.26", "19.27", "19.28"] + runtime: [static, dynamic] + runtime_type: [Debug, Release] + cppstd: [None, 14, 17, 20] clang: version: ["3.3", "3.4", "3.5", "3.6", "3.7", "3.8", "3.9", "4.0", "5.0", "6.0", "7.0", "7.1", From 2738424173972eef3e2e1f0e4d7113c3b1b6c2be Mon Sep 17 00:00:00 2001 From: memsharded Date: Thu, 14 Jan 2021 11:46:35 +0100 Subject: [PATCH 21/22] requiring compiler.cppstd to be defined --- conans/client/settings_preprocessor.py | 8 ++++++++ conans/test/functional/toolchains/test_msbuild.py | 5 +++-- conans/test/integration/package_id/compatible_test.py | 6 ++++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/conans/client/settings_preprocessor.py b/conans/client/settings_preprocessor.py index 8730b765959..243765d9044 100644 --- a/conans/client/settings_preprocessor.py +++ b/conans/client/settings_preprocessor.py @@ -15,6 +15,14 @@ def _check_cppstd(settings): cppstd = settings.get_safe("cppstd") compiler_cppstd = settings.get_safe("compiler.cppstd") + if compiler == "msvc": + # This is hardcoded at the moment, because the minimum defined version is 19.0, with c++14 + # TODO: When older versions of msvc are defined in settings, cppstd can be None + if compiler_cppstd is None: + raise ConanException("compiler.cppstd is not defined for 'msvc' compiler. The minimum " + "and compiler version default is 'compiler.cppstd=14'") + return + if not cppstd and not compiler_cppstd: return diff --git a/conans/test/functional/toolchains/test_msbuild.py b/conans/test/functional/toolchains/test_msbuild.py index 4a538c43a5c..17bfb3c73b8 100644 --- a/conans/test/functional/toolchains/test_msbuild.py +++ b/conans/test/functional/toolchains/test_msbuild.py @@ -321,9 +321,10 @@ def generate(self): client.run('install . -s compiler="Visual Studio" -s compiler.version=15 -s compiler.runtime=MD') assert "MSVC FLAG=MD!!" in client.out client.run('install . -s compiler=msvc -s compiler.version=19.1 -s compiler.runtime=static ' - '-s compiler.runtime_type=Debug') + '-s compiler.runtime_type=Debug -s compiler.cppstd=14') assert "MSVC FLAG=MTd!!" in client.out - client.run('install . -s compiler=msvc -s compiler.version=19.1 -s compiler.runtime=dynamic') + client.run('install . -s compiler=msvc -s compiler.version=19.1 -s compiler.runtime=dynamic ' + '-s compiler.cppstd=14') assert "MSVC FLAG=MD!!" in client.out diff --git a/conans/test/integration/package_id/compatible_test.py b/conans/test/integration/package_id/compatible_test.py index ca235c5bbf4..a54b9a47592 100644 --- a/conans/test/integration/package_id/compatible_test.py +++ b/conans/test/integration/package_id/compatible_test.py @@ -501,9 +501,11 @@ def test_msvc_visual_incompatible(): client.run('create . pkg/0.1@ -s os=Windows -s compiler="Visual Studio" -s compiler.version=15 ' '-s compiler.runtime=MD -s build_type=Release -s arch=x86_64') client.run("install pkg/0.1@ -s os=Windows -s compiler=msvc -s compiler.version=19.1 " - "-s compiler.runtime=dynamic -s build_type=Release -s arch=x86_64") + "-s compiler.runtime=dynamic -s build_type=Release -s arch=x86_64 " + "-s compiler.cppstd=14") assert "Using compatible package" in client.out client.run("config set general.msvc_visual_incompatible=1") client.run("install pkg/0.1@ -s os=Windows -s compiler=msvc -s compiler.version=19.1 " - "-s compiler.runtime=dynamic -s build_type=Release -s arch=x86_64", assert_error=True) + "-s compiler.runtime=dynamic -s build_type=Release -s arch=x86_64 " + "-s compiler.cppstd=14", assert_error=True) assert "ERROR: Missing prebuilt package for 'pkg/0.1'" in client.out From 47c339b1c43e49dc2c20f7a6d68f6d436e06547b Mon Sep 17 00:00:00 2001 From: memsharded Date: Thu, 14 Jan 2021 14:11:18 +0100 Subject: [PATCH 22/22] removing cppstd=None --- conans/client/conf/__init__.py | 4 ++-- conans/client/migrations_settings.py | 2 +- conans/client/settings_preprocessor.py | 8 -------- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/conans/client/conf/__init__.py b/conans/client/conf/__init__.py index 992e6336926..eccdbbcb789 100644 --- a/conans/client/conf/__init__.py +++ b/conans/client/conf/__init__.py @@ -91,7 +91,7 @@ "19.2", "19.20", "19.21", "19.22", "19.23", "19.24", "19.25", "19.26", "19.27", "19.28"] runtime: [static, dynamic] runtime_type: [Debug, Release] - cppstd: [None, 14, 17, 20] + cppstd: [14, 17, 20] clang: version: ["3.3", "3.4", "3.5", "3.6", "3.7", "3.8", "3.9", "4.0", "5.0", "6.0", "7.0", "7.1", @@ -510,7 +510,7 @@ def msvc_visual_incompatible(self): visual_comp = self.get_item("general.msvc_visual_incompatible") return visual_comp.lower() in ("1", "true") except ConanException: - return None + return False @property def short_paths_home(self): diff --git a/conans/client/migrations_settings.py b/conans/client/migrations_settings.py index ab53f995abf..1333ed58bfc 100644 --- a/conans/client/migrations_settings.py +++ b/conans/client/migrations_settings.py @@ -1896,7 +1896,7 @@ "19.2", "19.20", "19.21", "19.22", "19.23", "19.24", "19.25", "19.26", "19.27", "19.28"] runtime: [static, dynamic] runtime_type: [Debug, Release] - cppstd: [None, 14, 17, 20] + cppstd: [14, 17, 20] clang: version: ["3.3", "3.4", "3.5", "3.6", "3.7", "3.8", "3.9", "4.0", "5.0", "6.0", "7.0", "7.1", diff --git a/conans/client/settings_preprocessor.py b/conans/client/settings_preprocessor.py index 243765d9044..8730b765959 100644 --- a/conans/client/settings_preprocessor.py +++ b/conans/client/settings_preprocessor.py @@ -15,14 +15,6 @@ def _check_cppstd(settings): cppstd = settings.get_safe("cppstd") compiler_cppstd = settings.get_safe("compiler.cppstd") - if compiler == "msvc": - # This is hardcoded at the moment, because the minimum defined version is 19.0, with c++14 - # TODO: When older versions of msvc are defined in settings, cppstd can be None - if compiler_cppstd is None: - raise ConanException("compiler.cppstd is not defined for 'msvc' compiler. The minimum " - "and compiler version default is 'compiler.cppstd=14'") - return - if not cppstd and not compiler_cppstd: return