Skip to content

Commit

Permalink
Feature: MSBuildDeps generator: CAExcludePath (#8682)
Browse files Browse the repository at this point in the history
* - add CAExcludePath

Signed-off-by: SSE4 <tomskside@gmail.com>

* Update conan/tools/microsoft/msbuilddeps.py

Co-authored-by: James <james@conan.io>

* Update conan/tools/microsoft/msbuilddeps.py

Co-authored-by: James <james@conan.io>

* Update conan/tools/microsoft/msbuilddeps.py

Co-authored-by: James <james@conan.io>

* fixing code

* remove boolean config, force only lists

Co-authored-by: James <james@conan.io>
  • Loading branch information
SSE4 and memsharded committed Mar 29, 2021
1 parent ba02860 commit 2f7de1b
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 16 deletions.
57 changes: 41 additions & 16 deletions conan/tools/microsoft/msbuilddeps.py
@@ -1,7 +1,9 @@
import fnmatch
import os
import textwrap
from xml.dom import minidom

from jinja2 import Template

from conans.errors import ConanException
from conans.model.build_info import DepCppInfo
Expand Down Expand Up @@ -38,31 +40,34 @@ class MSBuildDeps(object):
<ImportGroup Label="Configurations">
</ImportGroup>
<PropertyGroup>
<conan_{name}_props_imported>True</conan_{name}_props_imported>
<conan_{{name}}_props_imported>True</conan_{{name}}_props_imported>
</PropertyGroup>
<PropertyGroup>
<LocalDebuggerEnvironment>PATH=%PATH%;$(Conan{name}BinaryDirectories)$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
<LocalDebuggerEnvironment>PATH=%PATH%;$(Conan{{name}}BinaryDirectories)$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
{% if ca_exclude -%}
<CAExcludePath>$(Conan{{name}}IncludeDirectories);$(CAExcludePath)</CAExcludePath>
{%- endif %}
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(Conan{name}IncludeDirectories)%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>$(Conan{name}PreprocessorDefinitions)%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>$(Conan{name}CompilerFlags) %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>$(Conan{{name}}IncludeDirectories)%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>$(Conan{{name}}PreprocessorDefinitions)%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>$(Conan{{name}}CompilerFlags) %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(Conan{name}LibraryDirectories)%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>$(Conan{name}Libraries)%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>$(Conan{name}SystemDeps)%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>$(Conan{name}LinkerFlags) %(AdditionalOptions)</AdditionalOptions>
<AdditionalLibraryDirectories>$(Conan{{name}}LibraryDirectories)%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>$(Conan{{name}}Libraries)%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>$(Conan{{name}}SystemDeps)%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>$(Conan{{name}}LinkerFlags) %(AdditionalOptions)</AdditionalOptions>
</Link>
<Midl>
<AdditionalIncludeDirectories>$(Conan{name}IncludeDirectories)%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(Conan{{name}}IncludeDirectories)%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</Midl>
<ResourceCompile>
<AdditionalIncludeDirectories>$(Conan{name}IncludeDirectories)%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>$(Conan{name}PreprocessorDefinitions)%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>$(Conan{name}CompilerFlags) %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>$(Conan{{name}}IncludeDirectories)%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>$(Conan{{name}}PreprocessorDefinitions)%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>$(Conan{{name}}CompilerFlags) %(AdditionalOptions)</AdditionalOptions>
</ResourceCompile>
</ItemDefinitionGroup>
</Project>
Expand All @@ -75,6 +80,15 @@ def __init__(self, conanfile):
'x86_64': 'x64'}.get(str(conanfile.settings.arch))
# TODO: this is ugly, improve this
self.output_path = os.getcwd()
# ca_exclude section
self.exclude_code_analysis = None
ca_exclude = self._conanfile.conf["tools.microsoft.msbuilddeps"].exclude_code_analysis
if ca_exclude is not None:
# TODO: Accept single strings, not lists
self.exclude_code_analysis = eval(ca_exclude)
if not isinstance(self.exclude_code_analysis, list):
raise ConanException("tools.microsoft.msbuilddeps:exclude_code_analysis must be a"
" list of package names patterns like ['pkga*']")

def generate(self):
# TODO: Apply config from command line, something like
Expand Down Expand Up @@ -165,7 +179,7 @@ def add_valid_ext(libname):
'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)
'exe_flags': " ".join(cpp_info.exelinkflags),
}
formatted_template = self._vars_conf_props.format(**fields)
return formatted_template
Expand All @@ -178,7 +192,18 @@ def _pkg_props(self, name_multi, dep_name, vars_props_name, condition, cpp_info)
else:
content_multi = self._dep_props

content_multi = content_multi.format(name=dep_name)
# TODO: This must include somehow the user/channel, most likely pattern to exclude/include
# Probably also the negation pattern, exclude all not @mycompany/*
ca_exclude = False
if isinstance(self.exclude_code_analysis, list):
for pattern in self.exclude_code_analysis:
if fnmatch.fnmatch(dep_name, pattern):
ca_exclude = True
break
else:
ca_exclude = self.exclude_code_analysis

content_multi = Template(content_multi).render(name=dep_name, ca_exclude=ca_exclude)

# parse the multi_file and add new import statement if needed
dom = minidom.parseString(content_multi)
Expand Down Expand Up @@ -228,7 +253,7 @@ def _content(self):
direct_deps = self._conanfile.dependencies.direct_host_requires
result[general_name] = self._deps_props(general_name, direct_deps)
for dep in self._conanfile.dependencies.host_requires:
cpp_info = DepCppInfo(dep.cpp_info) # To account for automatic component aggregation
cpp_info = DepCppInfo(dep.cpp_info) # To account for automatic component aggregation
# One file per configuration, with just the variables
vars_props_name = "conan_%s%s.props" % (dep.name, conf_name)
vars_conf_content = self._pkg_config_props(dep.name, cpp_info)
Expand Down
52 changes: 52 additions & 0 deletions conans/test/functional/toolchains/microsoft/test_msbuilddeps.py
Expand Up @@ -5,6 +5,8 @@

import pytest

from parameterized import parameterized

from conans.test.assets.cpp_test_files import cpp_hello_conan_files
from conans.test.assets.genconanfile import GenConanfile
from conans.test.assets.sources import gen_function_cpp
Expand Down Expand Up @@ -607,3 +609,53 @@ def build(self):
self.assertIn("conan_tool.props", deps)
client.run("create . pkg/0.1@")
self.assertIn("Conan_tools.props in deps", client.out)

@parameterized.expand([("['*']", True, True),
("['pkga']", True, False),
("['pkgb']", False, True),
("['pkg*']", True, True),
("['pkga', 'pkgb']", True, True),
("['*a', '*b']", True, True),
("['nonexist']", False, False),
])
def test_exclude_code_analysis(self, pattern, exclude_a, exclude_b):
client = TestClient()
client.save({"conanfile.py": GenConanfile()})
client.run("create . pkga/1.0@")
client.run("create . pkgb/1.0@")

conanfile = textwrap.dedent("""
from conans import ConanFile, MSBuild
class HelloConan(ConanFile):
settings = "os", "build_type", "compiler", "arch"
requires = "pkgb/1.0@", "pkga/1.0"
generators = "msbuild"
def build(self):
msbuild = MSBuild(self)
msbuild.build("MyProject.sln")
""")
profile = textwrap.dedent("""
include(default)
[conf]
tools.microsoft.msbuilddeps:exclude_code_analysis = %s
""" % pattern)

client.save({"conanfile.py": conanfile,
"profile": profile})
client.run("install . --profile profile")
depa = client.load("conan_pkga.props")
depb = client.load("conan_pkgb.props")

if exclude_a:
inc = "$(ConanpkgaIncludeDirectories)"
ca_exclude = "<CAExcludePath>%s;$(CAExcludePath)</CAExcludePath>" % inc
assert ca_exclude in depa
else:
assert "CAExcludePath" not in depa

if exclude_b:
inc = "$(ConanpkgbIncludeDirectories)"
ca_exclude = "<CAExcludePath>%s;$(CAExcludePath)</CAExcludePath>" % inc
assert ca_exclude in depb
else:
assert "CAExcludePath" not in depb

0 comments on commit 2f7de1b

Please sign in to comment.