Skip to content

Commit

Permalink
adding tools.microsoft:winsdk_version conf (#15272)
Browse files Browse the repository at this point in the history
* adding tools.microsoft:winsdk_version conf

* fix tests

* wip

* fix

* review
  • Loading branch information
memsharded authored Dec 15, 2023
1 parent 018441d commit 7921be1
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 27 deletions.
54 changes: 51 additions & 3 deletions conan/tools/cmake/toolchain/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 %}
Expand All @@ -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 %}
""")
Expand Down Expand Up @@ -771,6 +788,32 @@ def _get_cross_build(self):

return system_name, system_version, system_processor

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:
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.settings.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 system_version, winsdk_version, gen_platform_sdk_version

def context(self):
generator = self._toolchain.generator
generator_platform = self._get_generator_platform(generator)
Expand All @@ -781,12 +824,17 @@ 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

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,
"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):
Expand Down
8 changes: 8 additions & 0 deletions conan/tools/microsoft/toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ class MSBuildToolchain(object):
</ResourceCompile>
</ItemDefinitionGroup>
<PropertyGroup Label="Configuration">
{% if winsdk_version %}
<WindowsTargetPlatformVersion>{{ winsdk_version}}</WindowsTargetPlatformVersion>
{% endif %}
<PlatformToolset>{{ toolset }}</PlatformToolset>
{% for k, v in properties.items() %}
<{{k}}>{{ v }}</{{k}}>
Expand Down Expand Up @@ -149,6 +152,10 @@ def format_macro(key, value):
"\n <ProcessorNumber>{}</ProcessorNumber>".format(njobs)])
compile_options = "".join("\n <{k}>{v}</{k}>".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),
Expand All @@ -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):
Expand Down
8 changes: 5 additions & 3 deletions conan/tools/microsoft/visual.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,21 +132,23 @@ 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.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
# 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("""\
@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)

Expand Down
1 change: 1 addition & 0 deletions conans/model/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,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",
Expand Down
18 changes: 18 additions & 0 deletions conans/test/functional/toolchains/cmake/test_cmake_toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,24 @@ 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")
# TODO: when we have CMake 3.27 in CI
# cmake = cmake.replace("cmake_minimum_required(VERSION 3.15)",
# "cmake_minimum_required(VERSION 3.27)")
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


@pytest.mark.tool("cmake", "3.23")
def test_cmake_presets_missing_option():
client = TestClient(path_with_spaces=False)
Expand Down
Original file line number Diff line number Diff line change
@@ -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 = """
<ImportGroup Label="PropertySheets">
<Import Project="conan\\conantoolchain_release_x64.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
Expand All @@ -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' <ImportGroup Label="PropertySheets">', 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
19 changes: 19 additions & 0 deletions conans/test/integration/toolchains/microsoft/vcvars_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 7921be1

Please sign in to comment.