From 8f869ce2cf75a0ae3bab5c45f5f4d84df494baa9 Mon Sep 17 00:00:00 2001 From: memsharded Date: Thu, 14 Dec 2023 00:51:29 +0100 Subject: [PATCH 1/5] adding tools.microsoft:winsdk_version conf --- conan/tools/microsoft/visual.py | 4 +++- conans/model/conf.py | 1 + .../toolchains/microsoft/vcvars_test.py | 19 +++++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/conan/tools/microsoft/visual.py b/conan/tools/microsoft/visual.py index e485376ca4d..07fdd209590 100644 --- a/conan/tools/microsoft/visual.py +++ b/conan/tools/microsoft/visual.py @@ -132,12 +132,14 @@ def generate(self, scope="build"): vcvars_ver = _vcvars_vers(conanfile, compiler, vs_version) vcvarsarch = _vcvars_arch(conanfile) + winsdk_version = conanfile.conf.get("tools.microsoft:winsdk_version", check_type=str) + winsdk_version = winsdk_version or conanfile.setttings.get_safe("os.version") # The vs_install_path is like # C:\Program Files (x86)\Microsoft Visual Studio\2019\Community # C:\Program Files (x86)\Microsoft Visual Studio\2017\Community # C:\Program Files (x86)\Microsoft Visual Studio 14.0 vcvars = vcvars_command(vs_version, architecture=vcvarsarch, platform_type=None, - winsdk_version=None, vcvars_ver=vcvars_ver, + winsdk_version=winsdk_version, vcvars_ver=vcvars_ver, vs_install_path=vs_install_path) content = textwrap.dedent("""\ diff --git a/conans/model/conf.py b/conans/model/conf.py index ec8711e9e5d..a21f810f669 100644 --- a/conans/model/conf.py +++ b/conans/model/conf.py @@ -80,6 +80,7 @@ "tools.google.bazel:bazelrc_path": "List of paths to bazelrc files to be used as 'bazel --bazelrc=rcpath1 ... build'", "tools.meson.mesontoolchain:backend": "Any Meson backend: ninja, vs, vs2010, vs2012, vs2013, vs2015, vs2017, vs2019, xcode", "tools.meson.mesontoolchain:extra_machine_files": "List of paths for any additional native/cross file references to be appended to the existing Conan ones", + "tools.microsoft:winsdk_version": "Use this winsdk_version in vcvars", "tools.microsoft.msbuild:vs_version": "Defines the IDE version (15, 16, 17) when using the msvc compiler. Necessary if compiler.version specifies a toolset that is not the IDE default", "tools.microsoft.msbuild:max_cpu_count": "Argument for the /m when running msvc to build parallel projects", "tools.microsoft.msbuild:installation_path": "VS install path, to avoid auto-detect via vswhere, like C:/Program Files (x86)/Microsoft Visual Studio/2019/Community. Use empty string to disable", diff --git a/conans/test/integration/toolchains/microsoft/vcvars_test.py b/conans/test/integration/toolchains/microsoft/vcvars_test.py index eb43b63e9ee..d17f42cee1a 100644 --- a/conans/test/integration/toolchains/microsoft/vcvars_test.py +++ b/conans/test/integration/toolchains/microsoft/vcvars_test.py @@ -107,3 +107,22 @@ class TestConan(ConanFile): vcvars = client.load("conanvcvars.bat") assert 'vcvarsall.bat" x86_amd64' in vcvars assert "-vcvars_ver" not in vcvars + + +@pytest.mark.skipif(platform.system() != "Windows", reason="Requires Windows") +def test_vcvars_winsdk_version(): + client = TestClient(path_with_spaces=False) + + conanfile = textwrap.dedent(""" + from conan import ConanFile + class TestConan(ConanFile): + generators = "VCVars" + settings = "os", "compiler", "arch", "build_type" + """) + client.save({"conanfile.py": conanfile}) + client.run('install . -s os=Windows -s compiler=msvc -s compiler.version=193 ' + '-s compiler.cppstd=14 -s compiler.runtime=static ' + '-c tools.microsoft:winsdk_version=8.1') + + vcvars = client.load("conanvcvars.bat") + assert 'vcvarsall.bat" amd64 8.1 -vcvars_ver=14.3' in vcvars From 88f39dbe8ae994f2154e1ec2fc96f2f8b7f6132f Mon Sep 17 00:00:00 2001 From: memsharded Date: Thu, 14 Dec 2023 13:22:49 +0100 Subject: [PATCH 2/5] fix tests --- conan/tools/microsoft/visual.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conan/tools/microsoft/visual.py b/conan/tools/microsoft/visual.py index 07fdd209590..8a0937c7eae 100644 --- a/conan/tools/microsoft/visual.py +++ b/conan/tools/microsoft/visual.py @@ -133,7 +133,7 @@ def generate(self, scope="build"): vcvarsarch = _vcvars_arch(conanfile) winsdk_version = conanfile.conf.get("tools.microsoft:winsdk_version", check_type=str) - winsdk_version = winsdk_version or conanfile.setttings.get_safe("os.version") + winsdk_version = winsdk_version or conanfile.settings.get_safe("os.version") # The vs_install_path is like # C:\Program Files (x86)\Microsoft Visual Studio\2019\Community # C:\Program Files (x86)\Microsoft Visual Studio\2017\Community From 680be061999a0420c411fb4c0730c2b39cf20929 Mon Sep 17 00:00:00 2001 From: memsharded Date: Fri, 15 Dec 2023 01:34:08 +0100 Subject: [PATCH 3/5] wip --- conan/tools/cmake/toolchain/blocks.py | 43 +++++++++++++++++-- conan/tools/microsoft/toolchain.py | 8 ++++ conan/tools/microsoft/visual.py | 4 +- .../toolchains/cmake/test_cmake_toolchain.py | 14 ++++++ .../microsoft/test_msbuildtoolchain.py | 40 ++++++++--------- 5 files changed, 83 insertions(+), 26 deletions(-) diff --git a/conan/tools/cmake/toolchain/blocks.py b/conan/tools/cmake/toolchain/blocks.py index ad5e5ee7484..ba119d7ccc3 100644 --- a/conan/tools/cmake/toolchain/blocks.py +++ b/conan/tools/cmake/toolchain/blocks.py @@ -577,7 +577,7 @@ def context(self): check_type=bool) if android_ndk_path and (cxxflags or cflags) and android_legacy_toolchain is not False: self._conanfile.output.warning("tools.build:cxxflags or cflags are defined, but Android NDK toolchain may be overriding " - "the values. Consider setting tools.android:cmake_legacy_toolchain to False.") + "the values. Consider setting tools.android:cmake_legacy_toolchain to False.") return { "cxxflags": cxxflags, @@ -641,6 +641,9 @@ def context(self): class GenericSystemBlock(Block): template = textwrap.dedent(""" + ########## generic_system block ############# + # Definition of system, platform and toolset + ############################################# {% if cmake_sysroot %} set(CMAKE_SYSROOT {{ cmake_sysroot }}) {% endif %} @@ -656,10 +659,24 @@ class GenericSystemBlock(Block): set(CMAKE_SYSTEM_PROCESSOR {{ cmake_system_processor }}) {% endif %} - {% if generator_platform %} + {% if generator_platform and not winsdk_version %} set(CMAKE_GENERATOR_PLATFORM "{{ generator_platform }}" CACHE STRING "" FORCE) + {% elif winsdk_version %} + if(POLICY CMP0149) + cmake_policy(GET CMP0149 _POLICY_WINSDK_VERSION) + endif() + if(_POLICY_WINSDK_VERSION STREQUAL "NEW") + message(STATUS "Conan toolchain: CMAKE_GENERATOR_PLATFORM={{gen_platform_sdk_version}}") + set(CMAKE_GENERATOR_PLATFORM "{{ gen_platform_sdk_version }}" CACHE STRING "" FORCE) + else() + # winsdk_version will be taken from above CMAKE_SYSTEM_VERSION + message(STATUS "Conan toolchain: CMAKE_GENERATOR_PLATFORM={{generator_platform}}") + set(CMAKE_GENERATOR_PLATFORM "{{ generator_platform }}" CACHE STRING "" FORCE) + endif() {% endif %} + {% if toolset %} + message(STATUS "Conan toolchain: CMAKE_GENERATOR_TOOLSET={{ toolset }}") set(CMAKE_GENERATOR_TOOLSET "{{ toolset }}" CACHE STRING "" FORCE) {% endif %} """) @@ -781,12 +798,32 @@ def context(self): cmake_sysroot = self._conanfile.conf.get("tools.build:sysroot") cmake_sysroot = cmake_sysroot.replace("\\", "/") if cmake_sysroot is not None else None + winsdk_version = self._conanfile.conf.get("tools.microsoft:winsdk_version", check_type=str) + if winsdk_version: + if system_version: + self._conanfile.output.warning("Both cmake_system_version and winsdk_version confs" + " defined, prioritizing winsdk_version") + system_version = winsdk_version + elif "Windows" in self._conanfile.get_safe("os", ""): + winsdk_version = self._conanfile.settings.get_safe("os.version") + if system_version: + if winsdk_version: + self._conanfile.output.warning("Both cmake_system_version conf and os.version" + " defined, prioritizing cmake_system_version") + winsdk_version = system_version + + gen_platform_sdk_version = [generator_platform, + f"version={winsdk_version}" if winsdk_version else None] + gen_platform_sdk_version = ",".join(d for d in gen_platform_sdk_version if d) + return {"toolset": toolset, "generator_platform": generator_platform, "cmake_system_name": system_name, "cmake_system_version": system_version, "cmake_system_processor": system_processor, - "cmake_sysroot": cmake_sysroot} + "cmake_sysroot": cmake_sysroot, + "winsdk_version": winsdk_version, + "gen_platform_sdk_version": gen_platform_sdk_version} class OutputDirsBlock(Block): diff --git a/conan/tools/microsoft/toolchain.py b/conan/tools/microsoft/toolchain.py index 395dcd1ba91..e5427001cae 100644 --- a/conan/tools/microsoft/toolchain.py +++ b/conan/tools/microsoft/toolchain.py @@ -37,6 +37,9 @@ class MSBuildToolchain(object): + {% if winsdk_version %} + {{ winsdk_version}} + {% endif %} {{ toolset }} {% for k, v in properties.items() %} <{{k}}>{{ v }} @@ -149,6 +152,10 @@ def format_macro(key, value): "\n {}".format(njobs)]) compile_options = "".join("\n <{k}>{v}".format(k=k, v=v) for k, v in self.compile_options.items()) + + winsdk_version = self._conanfile.conf.get("tools.microsoft:winsdk_version", check_type=str) + winsdk_version = winsdk_version or self._conanfile.settings.get_safe("os.version") + return { 'defines': defines, 'compiler_flags': " ".join(self.cxxflags + self.cflags), @@ -159,6 +166,7 @@ def format_macro(key, value): "compile_options": compile_options, "parallel": parallel, "properties": self.properties, + "winsdk_version": winsdk_version } def _write_config_toolchain(self, config_filename): diff --git a/conan/tools/microsoft/visual.py b/conan/tools/microsoft/visual.py index 8a0937c7eae..157ca4833da 100644 --- a/conan/tools/microsoft/visual.py +++ b/conan/tools/microsoft/visual.py @@ -146,9 +146,9 @@ def generate(self, scope="build"): @echo off set __VSCMD_ARG_NO_LOGO=1 set VSCMD_SKIP_SENDTELEMETRY=1 - echo conanvcvars.bat: Activating environment Visual Studio {} - {} - vcvars_ver={} + echo conanvcvars.bat: Activating environment Visual Studio {} - {} - winsdk_version={} - vcvars_ver={} {} - """.format(vs_version, vcvarsarch, vcvars_ver, vcvars)) + """.format(vs_version, vcvarsarch, winsdk_version, vcvars_ver, vcvars)) from conan.tools.env.environment import create_env_script create_env_script(conanfile, content, CONAN_VCVARS_FILE, scope) diff --git a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py index be6dfc837cc..68f2908ff0d 100644 --- a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py +++ b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py @@ -555,6 +555,20 @@ def test_cmake_toolchain_runtime_types_cmake_older_than_3_15(): assert "LIBCMTD" in client.out +@pytest.mark.skipif(platform.system() != "Windows", reason="Only for windows") +# @pytest.mark.tool("cmake", "3.28") +def test_cmake_toolchain_winsdk_version(): + client = TestClient(path_with_spaces=False) + client.run("new cmake_lib -d name=hello -d version=0.1") + # cmake = client.load("CMakeLists.txt") + # cmake = cmake.replace("cmake_minimum_required(VERSION 3.15)", + # "cmake_minimum_required(VERSION 3.27)") + # client.save({"CMakeLists.txt": cmake}) + client.run("create . -s arch=x86_64 -s compiler.version=193 " + "-c tools.microsoft:winsdk_version=8.1") + assert "Conan toolchain: CMAKE_GENERATOR_PLATFORM=x64" in client.out + + @pytest.mark.tool("cmake", "3.23") def test_cmake_presets_missing_option(): client = TestClient(path_with_spaces=False) diff --git a/conans/test/functional/toolchains/microsoft/test_msbuildtoolchain.py b/conans/test/functional/toolchains/microsoft/test_msbuildtoolchain.py index b11d4fa4ae4..2d454d50099 100644 --- a/conans/test/functional/toolchains/microsoft/test_msbuildtoolchain.py +++ b/conans/test/functional/toolchains/microsoft/test_msbuildtoolchain.py @@ -1,25 +1,12 @@ import platform -import sys import textwrap -import os import pytest -try: - from unittest.mock import MagicMock -except: - from mock import MagicMock -from conan.tools.files import replace_in_file from conans.test.utils.tools import TestClient -toolchain_props = """ - - -""" - -@pytest.mark.skipif(sys.version_info.major == 2, reason="Meson not supported in Py2") -@pytest.mark.skipif(platform.system() not in ["Windows"], reason="Requires Windows") +@pytest.mark.skipif(platform.system() != "Windows", reason="Requires Windows") def test_msbuildtoolchain_props_with_extra_flags(): """ Real test which is injecting some compiler/linker options and other dummy defines and @@ -39,14 +26,25 @@ def test_msbuildtoolchain_props_with_extra_flags(): """) client = TestClient(path_with_spaces=False) client.run("new msbuild_exe -d name=hello -d version=0.1") - client.save({ - "myprofile": profile - }) - # Let's import manually the created conantoolchain_release_x64.props - replace_in_file(MagicMock(), os.path.join(client.current_folder, "hello.vcxproj"), - r' ', toolchain_props) - client.run("create . -pr myprofile -tf=\"\"") + client.save({"myprofile": profile}) + # conantoolchain.props is already imported in the msbuild_exe tempalte + client.run("create . -pr myprofile -tf=") assert "/analyze:quiet /doc src/hello.cpp" in client.out assert r"/VERBOSE:UNUSEDLIBS /PDB:mypdbfile x64\Release\hello.obj" in client.out assert "/D DEF1 /D DEF2" in client.out assert "Build succeeded." in client.out + + +@pytest.mark.skipif(platform.system() != "Windows", reason="Requires Windows") +def test_msbuildtoolchain_winsdk_version(): + """ + Configure sdk_version + """ + client = TestClient(path_with_spaces=False) + client.run("new msbuild_lib -d name=hello -d version=0.1") + # conantoolchain.props is already imported in the msbuild_exe tempalte + client.run("create . -s arch=x86_64 -s compiler.version=193 " + "-c tools.microsoft:winsdk_version=8.1") + # I have verified also opening VS IDE that the setting is correctly configured + # because the test always run over vcvars that already activates it + assert "amd64 - winsdk_version=8.1 - vcvars_ver=14.3" in client.out From 8ebb938e1560b393c3731c36f195d8d097ccf706 Mon Sep 17 00:00:00 2001 From: memsharded Date: Fri, 15 Dec 2023 02:43:07 +0100 Subject: [PATCH 4/5] fix --- conan/tools/cmake/toolchain/blocks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conan/tools/cmake/toolchain/blocks.py b/conan/tools/cmake/toolchain/blocks.py index ba119d7ccc3..c587534edf6 100644 --- a/conan/tools/cmake/toolchain/blocks.py +++ b/conan/tools/cmake/toolchain/blocks.py @@ -804,7 +804,7 @@ def context(self): self._conanfile.output.warning("Both cmake_system_version and winsdk_version confs" " defined, prioritizing winsdk_version") system_version = winsdk_version - elif "Windows" in self._conanfile.get_safe("os", ""): + elif "Windows" in self._conanfile.settings.get_safe("os", ""): winsdk_version = self._conanfile.settings.get_safe("os.version") if system_version: if winsdk_version: From 0b7830fdde57ccfc3b1e8dbd17c2f25064b1f8f8 Mon Sep 17 00:00:00 2001 From: memsharded Date: Fri, 15 Dec 2023 12:01:33 +0100 Subject: [PATCH 5/5] review --- conan/tools/cmake/toolchain/blocks.py | 29 +++++++++++++------ .../toolchains/cmake/test_cmake_toolchain.py | 8 +++-- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/conan/tools/cmake/toolchain/blocks.py b/conan/tools/cmake/toolchain/blocks.py index c587534edf6..e90ed2f2682 100644 --- a/conan/tools/cmake/toolchain/blocks.py +++ b/conan/tools/cmake/toolchain/blocks.py @@ -788,15 +788,11 @@ def _get_cross_build(self): return system_name, system_version, system_processor - def context(self): - generator = self._toolchain.generator - generator_platform = self._get_generator_platform(generator) - toolset = self._get_toolset(generator) - system_name, system_version, system_processor = self._get_cross_build() - - # This is handled by the tools.apple:sdk_path and CMAKE_OSX_SYSROOT in Apple - cmake_sysroot = self._conanfile.conf.get("tools.build:sysroot") - cmake_sysroot = cmake_sysroot.replace("\\", "/") if cmake_sysroot is not None else None + def _get_winsdk_version(self, system_version, generator_platform): + compiler = self._conanfile.settings.get_safe("compiler") + if compiler not in ("msvc", "clang") or "Visual" not in str(self._toolchain.generator): + # Ninja will get it from VCVars, not from toolchain + return system_version, None, None winsdk_version = self._conanfile.conf.get("tools.microsoft:winsdk_version", check_type=str) if winsdk_version: @@ -816,6 +812,21 @@ def context(self): f"version={winsdk_version}" if winsdk_version else None] gen_platform_sdk_version = ",".join(d for d in gen_platform_sdk_version if d) + return system_version, winsdk_version, gen_platform_sdk_version + + def context(self): + generator = self._toolchain.generator + generator_platform = self._get_generator_platform(generator) + toolset = self._get_toolset(generator) + system_name, system_version, system_processor = self._get_cross_build() + + # This is handled by the tools.apple:sdk_path and CMAKE_OSX_SYSROOT in Apple + cmake_sysroot = self._conanfile.conf.get("tools.build:sysroot") + cmake_sysroot = cmake_sysroot.replace("\\", "/") if cmake_sysroot is not None else None + + result = self._get_winsdk_version(system_version, generator) + system_version, winsdk_version, gen_platform_sdk_version = result + return {"toolset": toolset, "generator_platform": generator_platform, "cmake_system_name": system_name, diff --git a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py index 998c2d0ac28..5a40a22c169 100644 --- a/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py +++ b/conans/test/functional/toolchains/cmake/test_cmake_toolchain.py @@ -560,12 +560,16 @@ def test_cmake_toolchain_runtime_types_cmake_older_than_3_15(): def test_cmake_toolchain_winsdk_version(): client = TestClient(path_with_spaces=False) client.run("new cmake_lib -d name=hello -d version=0.1") - # cmake = client.load("CMakeLists.txt") + cmake = client.load("CMakeLists.txt") + # TODO: when we have CMake 3.27 in CI # cmake = cmake.replace("cmake_minimum_required(VERSION 3.15)", # "cmake_minimum_required(VERSION 3.27)") - # client.save({"CMakeLists.txt": cmake}) + cmake += 'message(STATUS "CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION = ' \ + '${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")' + client.save({"CMakeLists.txt": cmake}) client.run("create . -s arch=x86_64 -s compiler.version=193 " "-c tools.microsoft:winsdk_version=8.1") + assert "CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION = 8.1" in client.out assert "Conan toolchain: CMAKE_GENERATOR_PLATFORM=x64" in client.out