Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

definition of custom VS version for msvc compiler in MSBuild #8603

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 4 additions & 17 deletions conan/tools/microsoft/__init__.py
@@ -1,17 +1,4 @@
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")
runtime = "MT" if runtime == "static" else "MD"
if runtime_type == "Debug":
runtime = "{}d".format(runtime)
return runtime
from conan.tools.microsoft.toolchain import MSBuildToolchain
from conan.tools.microsoft.msbuild import MSBuild
from conan.tools.microsoft.msbuilddeps import MSBuildDeps
from conan.tools.microsoft.visual import msvc_runtime_flag
24 changes: 3 additions & 21 deletions conan/tools/microsoft/msbuild.py
@@ -1,5 +1,3 @@
from conan.tools.microsoft.visual import vcvars_arch, vcvars_command
from conans.client.tools import intel_compilervars_command
from conans.errors import ConanException


Expand All @@ -14,17 +12,6 @@ def msbuild_verbosity_cmd_line_arg(conanfile):
class MSBuild(object):
def __init__(self, conanfile):
self._conanfile = conanfile
self.compiler = conanfile.settings.get_safe("compiler")
# This is assuming this is the Visual Studio IDE version, used for the vcvars
self.version = (conanfile.settings.get_safe("compiler.base.version") or
conanfile.settings.get_safe("compiler.version"))
if self.compiler == "msvc":
version = self.version[:4] # Remove the latest version number 19.1X if existing
_visuals = {'19.0': '14', # TODO: This is common to CMake, refactor
'19.1': '15',
'19.2': '16'}
self.version = _visuals[version]
self.vcvars_arch = vcvars_arch(conanfile)
self.build_type = conanfile.settings.get_safe("build_type")
msvc_arch = {'x86': 'x86',
'x86_64': 'x64',
Expand All @@ -39,14 +26,9 @@ def __init__(self, conanfile):
self.platform = msvc_arch

def command(self, sln):
if self.compiler == "intel":
cvars = intel_compilervars_command(self._conanfile)
else:
cvars = vcvars_command(self.version, architecture=self.vcvars_arch,
platform_type=None, winsdk_version=None,
vcvars_ver=None)
cmd = ('%s && msbuild "%s" /p:Configuration=%s /p:Platform=%s'
% (cvars, sln, self.build_type, self.platform))
install_folder = self._conanfile.install_folder
cmd = ('%s/conanvcvars.bat && msbuild "%s" /p:Configuration=%s /p:Platform=%s'
% (install_folder, sln, self.build_type, self.platform))

verbosity = msbuild_verbosity_cmd_line_arg(self._conanfile)
if verbosity:
Expand Down
5 changes: 4 additions & 1 deletion conan/tools/microsoft/msbuilddeps.py
Expand Up @@ -2,10 +2,12 @@
import textwrap
from xml.dom import minidom

from conans.client.tools import VALID_LIB_EXTENSIONS

from conans.errors import ConanException
from conans.util.files import load, save

VALID_LIB_EXTENSIONS = (".so", ".lib", ".a", ".dylib", ".bc")


class MSBuildDeps(object):

Expand Down Expand Up @@ -213,6 +215,7 @@ def _pkg_props(self, name_multi, dep_name, vars_props_name, condition, cpp_info)
return content_multi

def _content(self):
# We cannot use self._conanfile.warn(), because that fails for virtual conanfile
print("*** The 'msbuild' generator is EXPERIMENTAL ***")
if not self._conanfile.settings.get_safe("build_type"):
raise ConanException("The 'msbuild' generator requires a 'build_type' setting value")
Expand Down
35 changes: 35 additions & 0 deletions conan/tools/microsoft/toolchain.py
Expand Up @@ -2,6 +2,8 @@
import textwrap
from xml.dom import minidom

from conan.tools.microsoft.visual import vcvars_command, vcvars_arch
from conans.client.tools import intel_compilervars_command
from conans.errors import ConanException
from conans.util.files import save, load

Expand All @@ -19,6 +21,25 @@ def __init__(self, conanfile):
self.cppstd = conanfile.settings.get_safe("compiler.cppstd")
self.toolset = self._msvs_toolset(conanfile.settings)

# For VCVARS stuff
self.compiler = conanfile.settings.get_safe("compiler")
# This is assuming this is the Visual Studio IDE version, used for the vcvars
compiler_version = (conanfile.settings.get_safe("compiler.base.version") or
conanfile.settings.get_safe("compiler.version"))
self.vcvars_arch = vcvars_arch(conanfile)
if self.compiler == "msvc":
toolset_override = self._conanfile.conf["tools.microsoft.msbuild"].vs_version
if toolset_override:
self.visual_version = toolset_override
else:
version = compiler_version[:4] # Remove the latest version number 19.1X if existing
_visuals = {'19.0': '14', # TODO: This is common to CMake, refactor
'19.1': '15',
'19.2': '16'}
self.visual_version = _visuals[version]
else:
self.visual_version = compiler_version

def _name_condition(self, settings):
props = [("Configuration", self.configuration),
# FIXME: This probably requires mapping ARM architectures
Expand All @@ -34,6 +55,20 @@ def generate(self):
config_filename = "conantoolchain{}.props".format(name)
self._write_config_toolchain(config_filename)
self._write_main_toolchain(config_filename, condition)
self._write_vcvars()

def _write_vcvars(self):
if self.compiler == "intel":
cvars = intel_compilervars_command(self._conanfile)
else:
cvars = vcvars_command(self.visual_version, architecture=self.vcvars_arch,
platform_type=None, winsdk_version=None,
vcvars_ver=None)
content = textwrap.dedent("""\
@echo off
{}
""".format(cvars))
save("conanvcvars.bat", content)

@staticmethod
def _msvs_toolset(settings):
Expand Down
14 changes: 14 additions & 0 deletions conan/tools/microsoft/visual.py
Expand Up @@ -4,6 +4,20 @@
from conans.errors import ConanException


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")
runtime = "MT" if runtime == "static" else "MD"
if runtime_type == "Debug":
runtime = "{}d".format(runtime)
return runtime


def vcvars_command(version, architecture=None, platform_type=None, winsdk_version=None,
vcvars_ver=None, start_dir_cd=True):
""" conan-agnostic construction of vcvars command
Expand Down
26 changes: 21 additions & 5 deletions conans/test/functional/toolchains/test_basic.py
@@ -1,4 +1,5 @@
import os
import platform
import textwrap
import unittest

Expand Down Expand Up @@ -34,8 +35,7 @@ def test_declarative(self):
from conans import ConanFile
class Pkg(ConanFile):
settings = "os", "compiler", "arch", "build_type"
generators = ("CMakeToolchain", "CMakeDeps", "MesonToolchain", "MakeToolchain",
"MSBuildToolchain")
generators = ("CMakeToolchain", "CMakeDeps", "MesonToolchain", "MakeToolchain")
""")
client = TestClient()
client.save({"conanfile.py": conanfile})
Expand All @@ -44,17 +44,31 @@ class Pkg(ConanFile):
self.assertIn("conanfile.py: Generator 'CMakeToolchain' calling 'generate()'", client.out)
self.assertIn("conanfile.py: Generator 'MesonToolchain' calling 'generate()'", client.out)
self.assertIn("conanfile.py: Generator 'MakeToolchain' calling 'generate()'", client.out)
self.assertIn("conanfile.py: Generator 'MSBuildToolchain' calling 'generate()'", client.out)
self.assertIn("conanfile.py: Generator 'CMakeDeps' calling 'generate()'", client.out)
toolchain = client.load("conan_toolchain.cmake")
self.assertIn("Conan automatically generated toolchain file", toolchain)
toolchain = client.load("conantoolchain.props")
self.assertIn("<?xml version", toolchain)
toolchain = client.load("conan_toolchain.mak")
self.assertIn("# Conan generated toolchain file", toolchain)
toolchain = client.load("conan_meson_native.ini")
self.assertIn("[project options]", toolchain)

@pytest.mark.tool_visual_studio
@pytest.mark.skipif(platform.system() != "Windows", reason="Only for windows")
def test_declarative_msbuildtoolchain(self):
conanfile = textwrap.dedent("""
from conans import ConanFile
class Pkg(ConanFile):
settings = "os", "compiler", "arch", "build_type"
generators = ("MSBuildToolchain", )
""")
client = TestClient()
client.save({"conanfile.py": conanfile})
client.run("install .")

self.assertIn("conanfile.py: Generator 'MSBuildToolchain' calling 'generate()'", client.out)
toolchain = client.load("conantoolchain.props")
self.assertIn("<?xml version", toolchain)

def test_error_missing_settings(self):
conanfile = textwrap.dedent("""
from conans import ConanFile
Expand Down Expand Up @@ -121,6 +135,8 @@ def toolchain(self):
client.run("install .", assert_error=True)
self.assertIn("The 'toolchain' attribute or method has been deprecated", client.out)

@pytest.mark.tool_visual_studio
@pytest.mark.skipif(platform.system() != "Windows", reason="Only for windows")
def test_toolchain_windows(self):
client = TestClient()
conanfile = textwrap.dedent("""
Expand Down
27 changes: 19 additions & 8 deletions conans/test/functional/toolchains/test_msbuild.py
Expand Up @@ -393,19 +393,28 @@ def _run_app(client, arch, build_type, shared=None):
shutil.copy(command_str, new_cmd)
client.run_command(new_cmd)

@pytest.mark.tool_cmake
@parameterized.expand([("Visual Studio", "15", "MT"),
("msvc", "19.1", "static")]
@parameterized.expand([("Visual Studio", "15", "MT", "17"),
("msvc", "19.1", "static", "17"),
("msvc", "19.0", "static", "14")]
)
def test_toolchain_win(self, compiler, version, runtime):
@pytest.mark.tool_cmake
def test_toolchain_win(self, compiler, version, runtime, cppstd):
client = TestClient(path_with_spaces=False)
settings = {"compiler": compiler,
"compiler.version": version,
"compiler.cppstd": "17",
"compiler.cppstd": cppstd,
"compiler.runtime": runtime,
"build_type": "Release",
"arch": "x86"}

profile = textwrap.dedent("""
[settings]
os=Windows

[conf]
tools.microsoft.msbuild:vs_version=15
""")
client.save({"myprofile": profile})
# Build the profile according to the settings provided
settings = " ".join('-s %s="%s"' % (k, v) for k, v in settings.items() if v)

Expand All @@ -416,11 +425,12 @@ def test_toolchain_win(self, compiler, version, runtime):
client.save({"conanfile.py": self.conanfile,
"MyProject.sln": sln_file,
"MyApp/MyApp.vcxproj": myapp_vcxproj,
"MyApp/MyApp.cpp": self.app},
"MyApp/MyApp.cpp": self.app,
"myprofile": profile},
clean_first=True)

# Run the configure corresponding to this test case
client.run("install . %s -if=conan" % (settings, ))
client.run("install . %s -if=conan -pr=myprofile" % (settings, ))
self.assertIn("conanfile.py: MSBuildToolchain created conantoolchain_release_win32.props",
client.out)
client.run("build . -if=conan")
Expand All @@ -429,7 +439,8 @@ def test_toolchain_win(self, compiler, version, runtime):

self._run_app(client, "x86", "Release")
self.assertIn("Hello World Release", client.out)
check_exe_run(client.out, "main", "msvc", "19.1", "Release", "x86", "17",
compiler_version = version if compiler == "msvc" else "19.1"
check_exe_run(client.out, "main", "msvc", compiler_version, "Release", "x86", cppstd,
{"DEFINITIONS_BOTH": "True",
"DEFINITIONS_CONFIG": "Release"})
check_vs_runtime("Release/MyApp.exe", client, "15", static=True, build_type="Release")
Expand Down
33 changes: 28 additions & 5 deletions conans/test/functional/toolchains/test_txt_cmdline.py
@@ -1,3 +1,4 @@
import platform
import textwrap
import unittest

Expand All @@ -15,7 +16,6 @@ def test_declarative(self):
CMakeToolchain
MesonToolchain
MakeToolchain
MSBuildToolchain
""")
client = TestClient()
client.save({"conanfile.txt": conanfile})
Expand All @@ -26,11 +26,8 @@ def _check(self, client):
self.assertIn("conanfile.txt: Generator 'CMakeToolchain' calling 'generate()'", client.out)
self.assertIn("conanfile.txt: Generator 'MesonToolchain' calling 'generate()'", client.out)
self.assertIn("conanfile.txt: Generator 'MakeToolchain' calling 'generate()'", client.out)
self.assertIn("conanfile.txt: Generator 'MSBuildToolchain' calling 'generate()'", client.out)
toolchain = client.load("conan_toolchain.cmake")
self.assertIn("Conan automatically generated toolchain file", toolchain)
toolchain = client.load("conantoolchain.props")
self.assertIn("<?xml version", toolchain)
toolchain = client.load("conan_toolchain.mak")
self.assertIn("# Conan generated toolchain file", toolchain)
toolchain = client.load("conan_meson_native.ini")
Expand All @@ -40,5 +37,31 @@ def test_command_line(self):
client = TestClient()
client.save({"conanfile.txt": ""})
client.run("install . -g CMakeToolchain -g MesonToolchain "
"-g MakeToolchain -g MSBuildToolchain")
"-g MakeToolchain")
self._check(client)


@pytest.mark.tool_visual_studio
@pytest.mark.skipif(platform.system() != "Windows", reason="Only for windows")
class TestTxtCommandLineMSBuild(unittest.TestCase):

def test_declarative(self):
conanfile = textwrap.dedent("""
[generators]
MSBuildToolchain
""")
client = TestClient()
client.save({"conanfile.txt": conanfile})
client.run("install .")
self._check(client)

def _check(self, client):
self.assertIn("conanfile.txt: Generator 'MSBuildToolchain' calling 'generate()'", client.out)
toolchain = client.load("conantoolchain.props")
self.assertIn("<?xml version", toolchain)

def test_command_line(self):
client = TestClient()
client.save({"conanfile.txt": ""})
client.run("install . -g MSBuildToolchain")
self._check(client)
Expand Up @@ -106,8 +106,6 @@ def test_config_profile_forbidden(client):
"'cache:verbosity=Minimal' not allowed in profiles" in client.out)


@pytest.mark.tool_visual_studio
@pytest.mark.skipif(platform.system() != "Windows", reason="Only for windows")
def test_msbuild_config():
client = TestClient()
conanfile = textwrap.dedent("""
Expand Down Expand Up @@ -137,6 +135,8 @@ def build(self):
assert "/verbosity:Minimal" in client.out


@pytest.mark.tool_visual_studio
@pytest.mark.skipif(platform.system() != "Windows", reason="Only for windows")
def test_msbuild_compile_options():
client = TestClient()
conanfile = textwrap.dedent("""
Expand Down
4 changes: 4 additions & 0 deletions conans/test/integration/toolchain/test_msbuild_toolchain.py
@@ -1,5 +1,7 @@
import platform
import textwrap

import pytest
from parameterized import parameterized

from conans.test.utils.tools import TestClient
Expand All @@ -8,6 +10,8 @@
@parameterized.expand([("msvc", "19.0", "dynamic"),
("msvc", "19.1", "static")]
)
@pytest.mark.tool_visual_studio
@pytest.mark.skipif(platform.system() != "Windows", reason="Only for windows")
def test_toolchain_win(compiler, version, runtime):
client = TestClient(path_with_spaces=False)
settings = {"compiler": compiler,
Expand Down