summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames <james@conan.io>2021-09-29 12:16:16 +0200
committerGitHub <noreply@github.com>2021-09-29 12:16:16 +0200
commitf3a6e13f0b73392117af866ec619f531d1a9b0f2 (patch)
tree0d82b6e8810f090669c7c1b17d96539614fb0737
parent7532ccc7bb2968b47310fc7a183d809cc70f7f07 (diff)
MSBuildDeps handle build_requires executables (#9686)
* MSBuildDeps handle build_requires executables * fix py27 error * review * removed unused file
-rw-r--r--conan/tools/cmake/cmakedeps/cmakedeps.py5
-rw-r--r--conan/tools/microsoft/msbuilddeps.py77
-rw-r--r--conans/test/functional/toolchains/microsoft/test_msbuilddeps.py129
-rw-r--r--origin)0
4 files changed, 190 insertions, 21 deletions
diff --git a/conan/tools/cmake/cmakedeps/cmakedeps.py b/conan/tools/cmake/cmakedeps/cmakedeps.py
index 2e26b657..80c0bff4 100644
--- a/conan/tools/cmake/cmakedeps/cmakedeps.py
+++ b/conan/tools/cmake/cmakedeps/cmakedeps.py
@@ -1,5 +1,4 @@
import os
-from fnmatch import fnmatch
from conan.tools._check_build_profile import check_using_build_profile
from conan.tools.cmake.cmakedeps.templates.config import ConfigTemplate
@@ -17,6 +16,7 @@ FIND_MODE_CONFIG = "config"
FIND_MODE_NONE = "none"
FIND_MODE_BOTH = "both"
+
class CMakeDeps(object):
def __init__(self, conanfile):
@@ -81,7 +81,8 @@ class CMakeDeps(object):
if dep.is_build_context and dep.ref.name not in self.build_context_activated:
continue
- cmake_find_mode = dep.new_cpp_info.get_property("cmake_find_mode", "CMakeDeps") or FIND_MODE_CONFIG
+ cmake_find_mode = dep.new_cpp_info.get_property("cmake_find_mode", "CMakeDeps")
+ cmake_find_mode = cmake_find_mode or FIND_MODE_CONFIG
cmake_find_mode = cmake_find_mode.lower()
# Skip from the requirement
if cmake_find_mode == FIND_MODE_NONE:
diff --git a/conan/tools/microsoft/msbuilddeps.py b/conan/tools/microsoft/msbuilddeps.py
index 9b986851..5cc1f6a4 100644
--- a/conan/tools/microsoft/msbuilddeps.py
+++ b/conan/tools/microsoft/msbuilddeps.py
@@ -7,7 +7,6 @@ from jinja2 import Template
from conan.tools._check_build_profile import check_using_build_profile
from conans.errors import ConanException
-from conans.model.build_info import DepCppInfo
from conans.util.files import load, save
VALID_LIB_EXTENSIONS = (".so", ".lib", ".a", ".dylib", ".bc")
@@ -20,16 +19,18 @@ class MSBuildDeps(object):
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="ConanVariables">
<Conan{{name}}RootFolder>{{root_folder}}</Conan{{name}}RootFolder>
+ <Conan{{name}}BinaryDirectories>{{bin_dirs}}</Conan{{name}}BinaryDirectories>
+ <Conan{{name}}Dependencies>{{dependencies}}</Conan{{name}}Dependencies>
+ {% if host_context %}
<Conan{{name}}CompilerFlags>{{compiler_flags}}</Conan{{name}}CompilerFlags>
<Conan{{name}}LinkerFlags>{{linker_flags}}</Conan{{name}}LinkerFlags>
<Conan{{name}}PreprocessorDefinitions>{{definitions}}</Conan{{name}}PreprocessorDefinitions>
<Conan{{name}}IncludeDirectories>{{include_dirs}}</Conan{{name}}IncludeDirectories>
<Conan{{name}}ResourceDirectories>{{res_dirs}}</Conan{{name}}ResourceDirectories>
<Conan{{name}}LibraryDirectories>{{lib_dirs}}</Conan{{name}}LibraryDirectories>
- <Conan{{name}}BinaryDirectories>{{bin_dirs}}</Conan{{name}}BinaryDirectories>
<Conan{{name}}Libraries>{{libs}}</Conan{{name}}Libraries>
<Conan{{name}}SystemLibs>{{system_libs}}</Conan{{name}}SystemLibs>
- <Conan{{name}}Dependencies>{{dependencies}}</Conan{{name}}Dependencies>
+ {% endif %}
</PropertyGroup>
</Project>
""")
@@ -45,6 +46,7 @@ class MSBuildDeps(object):
<ImportGroup Label="PropertySheets">
<Import Project="{{vars_filename}}"/>
</ImportGroup>
+ {% if host_context %}
<PropertyGroup>
<LocalDebuggerEnvironment>PATH=%PATH%;$(Conan{{name}}BinaryDirectories)$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
@@ -73,6 +75,11 @@ class MSBuildDeps(object):
<AdditionalOptions>$(Conan{{name}}CompilerFlags) %(AdditionalOptions)</AdditionalOptions>
</ResourceCompile>
</ItemDefinitionGroup>
+ {% else %}
+ <PropertyGroup>
+ <ExecutablePath>$(Conan{{name}}BinaryDirectories)$(ExecutablePath)</ExecutablePath>
+ </PropertyGroup>
+ {% endif %}
</Project>
""")
@@ -142,7 +149,7 @@ class MSBuildDeps(object):
condition = " And ".join("'$(%s)' == '%s'" % (k, v) for k, v in props)
return condition
- def _vars_props_file(self, name, cpp_info, deps):
+ def _vars_props_file(self, dep, name, cpp_info, deps, build=False):
"""
content for conan_vars_poco_x86_release.props, containing the variables
"""
@@ -151,25 +158,30 @@ class MSBuildDeps(object):
ext = os.path.splitext(libname)[1]
return '%s;' % libname if ext in VALID_LIB_EXTENSIONS else '%s.lib;' % libname
+ package_folder = dep.package_folder.replace('\\', '/')\
+ .replace('$', '\\$').replace('"', '\\"')
+ pkg_placeholder = "$(Conan{}RootFolder)/".format(name)
fields = {
'name': name,
- 'root_folder': cpp_info.rootpath,
- 'bin_dirs': "".join("%s;" % p for p in cpp_info.bin_paths),
- 'res_dirs': "".join("%s;" % p for p in cpp_info.res_paths),
- 'include_dirs': "".join("%s;" % p for p in cpp_info.include_paths),
- 'lib_dirs': "".join("%s;" % p for p in cpp_info.lib_paths),
+ 'root_folder': package_folder,
+ 'bin_dirs': "".join("%s;" % (pkg_placeholder + p) for p in cpp_info.bindirs),
+ 'res_dirs': "".join("%s;" % (pkg_placeholder + p) for p in cpp_info.resdirs),
+ 'include_dirs': "".join("%s;" % (pkg_placeholder + p) for p in cpp_info.includedirs),
+ 'lib_dirs': "".join("%s;" % (pkg_placeholder + p) for p in cpp_info.libdirs),
'libs': "".join([add_valid_ext(lib) for lib in cpp_info.libs]),
'system_libs': "".join([add_valid_ext(sys_dep) for sys_dep in cpp_info.system_libs]),
'definitions': "".join("%s;" % d for d in cpp_info.defines),
'compiler_flags': " ".join(cpp_info.cxxflags + cpp_info.cflags),
'linker_flags': " ".join(cpp_info.sharedlinkflags),
'exe_flags': " ".join(cpp_info.exelinkflags),
- 'dependencies': ";".join(deps)
+ 'dependencies': ";".join(deps),
+ 'host_context': not build
}
- formatted_template = Template(self._vars_props).render(**fields)
+ formatted_template = Template(self._vars_props, trim_blocks=True,
+ lstrip_blocks=True).render(**fields)
return formatted_template
- def _conf_props_file(self, dep_name, vars_props_name, deps):
+ def _conf_props_file(self, dep_name, vars_props_name, deps, build=False):
"""
content for conan_poco_x86_release.props, containing the activation
"""
@@ -185,7 +197,8 @@ class MSBuildDeps(object):
ca_exclude = self.exclude_code_analysis
template = Template(self._conf_props, trim_blocks=True, lstrip_blocks=True)
- content_multi = template.render(name=dep_name, ca_exclude=ca_exclude,
+ content_multi = template.render(host_context=not build,
+ name=dep_name, ca_exclude=ca_exclude,
vars_filename=vars_props_name, deps=deps)
return content_multi
@@ -232,8 +245,10 @@ class MSBuildDeps(object):
dom = minidom.parseString(content_multi)
import_group = dom.getElementsByTagName('ImportGroup')[0]
children = import_group.getElementsByTagName("Import")
- for dep in deps:
+ for req, dep in deps.items():
dep_name = dep.ref.name.replace(".", "_")
+ if req.build:
+ dep_name += "_build"
conf_props_name = "conan_%s.props" % dep_name
for node in children:
if conf_props_name == node.getAttribute("Project"):
@@ -261,21 +276,20 @@ class MSBuildDeps(object):
general_name = "conandeps.props"
conf_name = self._config_filename()
condition = self._condition()
- # Include all direct build_requires for host context. This might change
- direct_deps = self._conanfile.dependencies.filter({"direct": True, "build": False})
+
host_req = list(self._conanfile.dependencies.host.values())
test_req = list(self._conanfile.dependencies.test.values())
- result[general_name] = self._all_props_file(general_name, direct_deps.values())
for dep in host_req + test_req:
dep_name = dep.ref.name
dep_name = dep_name.replace(".", "_")
- cpp_info = DepCppInfo(dep.cpp_info) # To account for automatic component aggregation
+ cpp_info = dep.new_cpp_info.copy()
+ cpp_info.aggregate_components()
public_deps = [d.ref.name.replace(".", "_")
for r, d in dep.dependencies.direct_host.items() if r.visible]
# One file per configuration, with just the variables
vars_props_name = "conan_%s_vars%s.props" % (dep_name, conf_name)
- result[vars_props_name] = self._vars_props_file(dep_name, cpp_info, public_deps)
+ result[vars_props_name] = self._vars_props_file(dep, dep_name, cpp_info, public_deps)
props_name = "conan_%s%s.props" % (dep_name, conf_name)
result[props_name] = self._conf_props_file(dep_name, vars_props_name, public_deps)
@@ -284,4 +298,29 @@ class MSBuildDeps(object):
dep_content = self._dep_props_file(dep_name, file_dep_name, props_name, condition)
result[file_dep_name] = dep_content
+ build_req = list(self._conanfile.dependencies.build.values())
+ for dep in build_req:
+ dep_name = dep.ref.name
+ dep_name = dep_name.replace(".", "_") + "_build"
+ cpp_info = dep.new_cpp_info.copy()
+ cpp_info.aggregate_components()
+ public_deps = [d.ref.name.replace(".", "_")
+ for r, d in dep.dependencies.direct_host.items() if r.visible]
+ # One file per configuration, with just the variables
+ vars_props_name = "conan_%s_vars%s.props" % (dep_name, conf_name)
+ result[vars_props_name] = self._vars_props_file(dep, dep_name, cpp_info, public_deps,
+ build=True)
+ props_name = "conan_%s%s.props" % (dep_name, conf_name)
+ result[props_name] = self._conf_props_file(dep_name, vars_props_name, public_deps,
+ build=True)
+
+ # The entry point for each package, it will have conditionals to the others
+ file_dep_name = "conan_%s.props" % dep_name
+ dep_content = self._dep_props_file(dep_name, file_dep_name, props_name, condition)
+ result[file_dep_name] = dep_content
+
+ # Include all direct build_requires for host context. This might change
+ direct_deps = self._conanfile.dependencies.filter({"direct": True})
+ result[general_name] = self._all_props_file(general_name, direct_deps)
+
return result
diff --git a/conans/test/functional/toolchains/microsoft/test_msbuilddeps.py b/conans/test/functional/toolchains/microsoft/test_msbuilddeps.py
index 81c42016..63b60e1f 100644
--- a/conans/test/functional/toolchains/microsoft/test_msbuilddeps.py
+++ b/conans/test/functional/toolchains/microsoft/test_msbuilddeps.py
@@ -857,3 +857,132 @@ def test_private_transitive():
pkg_data_props = client.load("conan_pkg_release_x64.props")
assert "conan_dep.props" not in pkg_data_props
+
+
+@pytest.mark.skipif(platform.system() != "Windows", reason="Requires MSBuild")
+def test_build_requires():
+ # https://github.com/conan-io/conan/issues/9545
+ client = TestClient()
+ package = "self.copy('*', src=str(self.settings.arch), dst='bin')"
+ dep = GenConanfile().with_exports("*").with_settings("arch").with_package(package)
+ consumer = textwrap.dedent("""
+ from conans import ConanFile
+ from conan.tools.microsoft import MSBuild
+ class Pkg(ConanFile):
+ settings = "os", "compiler", "build_type", "arch"
+ build_requires = "dep/0.1"
+ generators = "MSBuildDeps", "MSBuildToolchain"
+ def build(self):
+ msbuild = MSBuild(self)
+ msbuild.build("hello.sln")
+ """)
+ hello_vcxproj = textwrap.dedent( r"""<?xml version="1.0" encoding="utf-8"?>
+ <Project DefaultTargets="Build" ToolsVersion="15.0"
+ xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>15.0</VCProjectVersion>
+ <ProjectGuid>{6F392A05-B151-490C-9505-B2A49720C4D9}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>MyProject</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+
+ <ImportGroup Label="PropertySheets">
+ <Import Project="..\conandeps.props" />
+ </ImportGroup>
+
+ <PropertyGroup Label="UserMacros" />
+
+ <ItemGroup>
+ <CustomBuild Include="data.proto">
+ <FileType>Document</FileType>
+ <Outputs>data.proto.h</Outputs>
+ <Command>dep1tool</Command>
+ </CustomBuild>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+ </Project>""")
+
+ hello_sln = textwrap.dedent(r"""
+ Microsoft Visual Studio Solution File, Format Version 12.00
+ # Visual Studio 15
+ VisualStudioVersion = 15.0.28307.757
+ MinimumVisualStudioVersion = 10.0.40219.1
+ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MyProject", "MyProject\MyProject.vcxproj", "{6F392A05-B151-490C-9505-B2A49720C4D9}"
+ EndProject
+ Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6F392A05-B151-490C-9505-B2A49720C4D9}.Release|x64.ActiveCfg = Release|x64
+ {6F392A05-B151-490C-9505-B2A49720C4D9}.Release|x64.Build.0 = Release|x64
+ {6F392A05-B151-490C-9505-B2A49720C4D9}.Release|x86.ActiveCfg = Release|Win32
+ {6F392A05-B151-490C-9505-B2A49720C4D9}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {DE6E462F-E299-4F9C-951A-F9404EB51521}
+ EndGlobalSection
+ EndGlobal
+ """)
+ client.save({"dep/conanfile.py": dep,
+ "dep/x86/dep1tool.bat": "@echo Invoking 32bit dep_1 build tool",
+ "dep/x86_64/dep1tool.bat": "@echo Invoking 64bit dep_1 build tool",
+ "consumer/conanfile.py": consumer,
+ "consumer/hello.sln": hello_sln,
+ "consumer/MyProject/MyProject.vcxproj": hello_vcxproj,
+ "consumer/MyProject/data.proto": "dataproto"})
+ client.run("create dep dep/0.1@ -s arch=x86")
+ client.run("create dep dep/0.1@ -s arch=x86_64")
+ with client.chdir("consumer"):
+ client.run('install . -s compiler="Visual Studio" -s compiler.version=15 '
+ " -s arch=x86_64 -s build_type=Release")
+ assert "dep/0.1:c0519e2d9702ec12d057bb15adb7a02baaf18107 - Cache" in client.out
+ deps_props = client.load("conandeps.props")
+ assert "conan_dep_build.props" in deps_props
+ client.run("build .")
+ assert "Invoking 64bit dep_1 build tool" in client.out
+
+ client.run('install . -s compiler="Visual Studio" -s compiler.version=15 '
+ " -s arch=x86 -s build_type=Release")
+ client.run("build .")
+ assert "Invoking 32bit dep_1 build tool" in client.out
+
+ # Make sure it works with 2 profiles too
+ client.run('install . -s compiler="Visual Studio" -s compiler.version=15 '
+ " -s arch=x86_64 -s build_type=Release -s:b os=Windows -s:h os=Windows")
+ client.run("build .")
+ assert "Invoking 64bit dep_1 build tool" in client.out
diff --git a/origin) b/origin)
deleted file mode 100644
index e69de29b..00000000
--- a/origin)
+++ /dev/null