Skip to content

Commit

Permalink
VCVars generator (#9230)
Browse files Browse the repository at this point in the history
* Missing more tests

* Added tests

* Removed comment

* None is activated by default

* Hide write_conanvcvars

* Fixed call to vcvars
  • Loading branch information
lasote committed Jul 9, 2021
1 parent 8cba45a commit c218ea2
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 60 deletions.
4 changes: 2 additions & 2 deletions conan/tools/cmake/toolchain.py
Expand Up @@ -11,7 +11,7 @@
from conan.tools._check_build_profile import check_using_build_profile
from conan.tools._compilers import architecture_flag, use_win_mingw
from conan.tools.cmake.utils import is_multi_configuration, get_file_name
from conan.tools.microsoft.toolchain import write_conanvcvars
from conan.tools.microsoft import VCVars
from conan.tools.microsoft.visual import vs_ide_version
from conans.errors import ConanException
from conans.util.files import load, save
Expand Down Expand Up @@ -729,7 +729,7 @@ def generate(self):
save(self.filename, self.content)
# Generators like Ninja or NMake requires an active vcvars
if self.generator is not None and "Visual" not in self.generator:
write_conanvcvars(self._conanfile)
VCVars(self._conanfile).generate()
self._writebuild(toolchain_file)

def _writebuild(self, toolchain_file):
Expand Down
4 changes: 2 additions & 2 deletions conan/tools/meson/toolchain.py
Expand Up @@ -4,7 +4,7 @@

from conan.tools._check_build_profile import check_using_build_profile
from conan.tools.env import VirtualBuildEnv
from conan.tools.microsoft.toolchain import write_conanvcvars
from conan.tools.microsoft import VCVars
from conans.client.build.cppstd_flags import cppstd_from_settings
from conans.client.tools.oss import cross_building, get_cross_building_settings
from conans.util.files import save
Expand Down Expand Up @@ -313,4 +313,4 @@ def generate(self):
self._write_cross_file()
else:
self._write_native_file()
write_conanvcvars(self._conanfile)
VCVars(self._conanfile).generate()
2 changes: 1 addition & 1 deletion conan/tools/microsoft/__init__.py
@@ -1,5 +1,5 @@
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
from conan.tools.microsoft.visual import msvc_runtime_flag, VCVars
from conan.tools.microsoft.subsystems import unix_path
53 changes: 2 additions & 51 deletions conan/tools/microsoft/toolchain.py
Expand Up @@ -3,59 +3,10 @@
from xml.dom import minidom

from conan.tools._check_build_profile import check_using_build_profile
from conan.tools.env.environment import register_environment_script
from conan.tools.microsoft.visual import vcvars_command, vcvars_arch
from conans.client.tools import intel_compilervars_command
from conan.tools.microsoft.visual import VCVars
from conans.errors import ConanException
from conans.util.files import save, load

CONAN_VCVARS_FILE = "conanvcvars.bat"


def write_conanvcvars(conanfile, auto_activate=True):
# FIXME: Write a VCVars generator for the final user
"""
write a conanvcvars.bat file with the good args from settings
"""
os_ = conanfile.settings.get_safe("os")
if os_ != "Windows":
return

compiler = conanfile.settings.get_safe("compiler")
cvars = None
if compiler == "intel":
cvars = intel_compilervars_command(conanfile)
elif compiler == "Visual Studio" or compiler == "msvc":
vs_version = vs_ide_version(conanfile)
vcvarsarch = vcvars_arch(conanfile)
vcvars_ver = None
if compiler == "Visual Studio":
toolset = conanfile.settings.get_safe("compiler.toolset")
if toolset is not None:
vcvars_ver = {"v140": "14.0",
"v141": "14.1",
"v142": "14.2"}.get(toolset)
else:
# Code similar to CMakeToolchain toolset one
compiler_version = str(conanfile.settings.compiler.version)
version_components = compiler_version.split(".")
assert len(version_components) >= 2 # there is a 19.XX
minor = version_components[1]
# The equivalent of compiler 19.26 is toolset 14.26
vcvars_ver = "14.{}".format(minor)
cvars = vcvars_command(vs_version, architecture=vcvarsarch, platform_type=None,
winsdk_version=None, vcvars_ver=vcvars_ver)
if cvars:
content = textwrap.dedent("""\
@echo off
{}
""".format(cvars))
path = os.path.join(conanfile.generators_folder, CONAN_VCVARS_FILE)
save(path, content)

if auto_activate:
register_environment_script(conanfile, path)


def vs_ide_version(conanfile):
compiler = conanfile.settings.get_safe("compiler")
Expand Down Expand Up @@ -105,7 +56,7 @@ def generate(self):
config_filename = "conantoolchain{}.props".format(name)
self._write_config_toolchain(config_filename)
self._write_main_toolchain(config_filename, condition)
write_conanvcvars(self._conanfile)
VCVars(self._conanfile).generate()

@staticmethod
def _msvs_toolset(settings):
Expand Down
58 changes: 58 additions & 0 deletions conan/tools/microsoft/visual.py
@@ -1,7 +1,65 @@
import os
import textwrap

from conan.tools.env.environment import register_environment_script
from conans.client.tools import intel_compilervars_command
from conans.client.tools.win import vs_installation_path
from conans.errors import ConanException
from conans.util.files import save

CONAN_VCVARS_FILE = "conanvcvars.bat"


class VCVars:
def __init__(self, conanfile):
self._conanfile = conanfile

def generate(self, auto_activate=True):
_write_conanvcvars(self._conanfile, auto_activate=auto_activate)


def _write_conanvcvars(conanfile, auto_activate=True):
"""
write a conanvcvars.bat file with the good args from settings
"""
os_ = conanfile.settings.get_safe("os")
if os_ != "Windows":
return

compiler = conanfile.settings.get_safe("compiler")
cvars = None
if compiler == "intel":
cvars = intel_compilervars_command(conanfile)
elif compiler == "Visual Studio" or compiler == "msvc":
vs_version = vs_ide_version(conanfile)
vcvarsarch = vcvars_arch(conanfile)
vcvars_ver = None
if compiler == "Visual Studio":
toolset = conanfile.settings.get_safe("compiler.toolset")
if toolset is not None:
vcvars_ver = {"v140": "14.0",
"v141": "14.1",
"v142": "14.2"}.get(toolset)
else:
# Code similar to CMakeToolchain toolset one
compiler_version = str(conanfile.settings.compiler.version)
version_components = compiler_version.split(".")
assert len(version_components) >= 2 # there is a 19.XX
minor = version_components[1]
# The equivalent of compiler 19.26 is toolset 14.26
vcvars_ver = "14.{}".format(minor)
cvars = vcvars_command(vs_version, architecture=vcvarsarch, platform_type=None,
winsdk_version=None, vcvars_ver=vcvars_ver)
if cvars:
content = textwrap.dedent("""\
@echo off
{}
""".format(cvars))
path = os.path.join(conanfile.generators_folder, CONAN_VCVARS_FILE)
save(path, content)

if auto_activate:
register_environment_script(conanfile, path)


def vs_ide_version(conanfile):
Expand Down
6 changes: 5 additions & 1 deletion conans/client/generators/__init__.py
Expand Up @@ -71,7 +71,8 @@ def __init__(self):
self._new_generators = ["CMakeToolchain", "CMakeDeps", "MSBuildToolchain",
"MesonToolchain", "MSBuildDeps", "QbsToolchain", "msbuild",
"VirtualRunEnv", "VirtualBuildEnv", "AutotoolsDeps",
"AutotoolsToolchain", "BazelDeps", "BazelToolchain", "PkgConfigDeps"]
"AutotoolsToolchain", "BazelDeps", "BazelToolchain", "PkgConfigDeps",
"VCVars"]

def add(self, name, generator_class, custom=False):
if name not in self._generators or custom:
Expand Down Expand Up @@ -115,6 +116,9 @@ def _new_generator(self, generator_name, output):
elif generator_name in ("MSBuildDeps", "msbuild"):
from conan.tools.microsoft import MSBuildDeps
return MSBuildDeps
elif generator_name == "VCVars":
from conan.tools.microsoft import VCVars
return VCVars
elif generator_name == "QbsToolchain" or generator_name == "QbsProfile":
from conan.tools.qbs.qbsprofile import QbsProfile
return QbsProfile
Expand Down
Expand Up @@ -30,7 +30,7 @@ def test_autotools_bash_complete():
conanfile = textwrap.dedent("""
from conans import ConanFile
from conan.tools.gnu import Autotools
from conan.tools.microsoft.toolchain import write_conanvcvars
from conan.tools.microsoft import VCVars
from conan.tools.env import Environment
class TestConan(ConanFile):
Expand All @@ -41,8 +41,7 @@ class TestConan(ConanFile):
def generate(self):
# Add vcvars launcher
# FIXME: Write a generator class for the vcvars
write_conanvcvars(self)
VCVars(self).generate()
# Force autotools to use "cl" compiler
# FIXME: Should this be added to AutotoolsToolchain when visual?
Expand Down
Empty file.
53 changes: 53 additions & 0 deletions conans/test/integration/toolchains/microsoft/vcvars_test.py
@@ -0,0 +1,53 @@
import platform
import textwrap
import os

import pytest

from conans.test.utils.tools import TestClient


@pytest.mark.skipif(platform.system() not in ["Windows"], reason="Requires Windows")
@pytest.mark.parametrize("auto_activate", [False, True, None])
def test_vcvars_generator(auto_activate):
client = TestClient(path_with_spaces=False)

conanfile = textwrap.dedent("""
from conans import ConanFile
from conan.tools.microsoft import VCVars
class TestConan(ConanFile):
settings = "os", "compiler", "arch", "build_type"
def generate(self):
VCVars(self).generate({})
""".format("True" if auto_activate else "False" if auto_activate is False else ""))

client.save({"conanfile.py": conanfile})
client.run('install . -s os=Windows -s compiler="msvc" -s compiler.version=19.1 '
'-s compiler.cppstd=14 -s compiler.runtime=static')

assert os.path.exists(os.path.join(client.current_folder, "conanvcvars.bat"))

if auto_activate is True or auto_activate is None:
bat_contents = client.load("conanenv.bat")
assert "conanvcvars.bat" in bat_contents
else:
assert not os.path.exists(os.path.join(client.current_folder, "conanenv.bat"))


@pytest.mark.skipif(platform.system() not in ["Windows"], reason="Requires Windows")
def test_vcvars_generator_string():
client = TestClient(path_with_spaces=False)

conanfile = textwrap.dedent("""
from conans 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=19.1 '
'-s compiler.cppstd=14 -s compiler.runtime=static')

assert os.path.exists(os.path.join(client.current_folder, "conanvcvars.bat"))

0 comments on commit c218ea2

Please sign in to comment.