Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 42 additions & 9 deletions lib/importproject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <initializer_list>
#include <iostream>
#include <iterator>
#include <regex>
#include <stack>
#include <stdexcept>
#include <unordered_set>
Expand Down Expand Up @@ -816,6 +817,32 @@ namespace {
bool useOfMfc = false;
bool useUnicode = false;
};

struct ItemGroupClCompile {
explicit ItemGroupClCompile(std::string file) : filename(std::move(file)) {}
ItemGroupClCompile(const tinyxml2::XMLElement* element, std::string file) : filename(std::move(file)) {
for (const tinyxml2::XMLElement* childElement = element->FirstChildElement(); childElement; childElement = childElement->NextSiblingElement()) {
const char* name = childElement->Name();
if (!name)
continue;
if (std::strcmp(name, "ExcludedFromBuild") == 0) {
const char* condition = childElement->Attribute("Condition");
const char* text = childElement->GetText();
if (!condition || !text)
continue;
const std::string cond(condition);
// Check if the condition is of the form: '$(Configuration)|$(Platform)' == 'Debug|x64'
const std::regex rgx("==\\s*'([^']+)'");
std::smatch match;
if (std::regex_search(cond, match, rgx) && match.size() > 1 && std::strcmp(text, "true") == 0)
exclude.insert(match[1]);
}
// TODO: ForcedIncludeFiles and PrecompiledHeaderFile
}
}
std::string filename;
std::set<std::string> exclude;
};
}

static std::list<std::string> toStringList(const std::string &s)
Expand Down Expand Up @@ -923,7 +950,7 @@ bool ImportProject::importVcxproj(const std::string &filename, const tinyxml2::X
variables["ProjectDir"] = Path::simplifyPath(Path::getPathFromFilename(filename));

std::list<ProjectConfiguration> projectConfigurationList;
std::list<std::string> compileList;
std::list<ItemGroupClCompile> compileList;
std::list<ItemDefinitionGroup> itemDefinitionGroupList;
std::vector<ConfigurationPropertyGroup> configurationPropertyGroups;
std::string includePath;
Expand Down Expand Up @@ -954,7 +981,8 @@ bool ImportProject::importVcxproj(const std::string &filename, const tinyxml2::X
const char *include = e->Attribute("Include");
if (include && Path::acceptFile(include)) {
std::string toInclude = Path::simplifyPath(Path::isAbsolute(include) ? include : Path::getPathFromFilename(filename) + include);
compileList.emplace_back(toInclude);
findAndReplace(toInclude, "$(MSBuildThisFileDirectory)", "./");
compileList.emplace_back(e, toInclude);
}
}
}
Expand Down Expand Up @@ -1016,7 +1044,7 @@ bool ImportProject::importVcxproj(const std::string &filename, const tinyxml2::X
for (const auto& sharedProject : sharedItemsProjects) {
for (const auto &file : sharedProject.sourceFiles) {
std::string pathToFile = Path::simplifyPath(Path::getPathFromFilename(sharedProject.pathToProjectFile) + file);
compileList.emplace_back(std::move(pathToFile));
compileList.emplace_back(pathToFile);
}
for (const auto &p : sharedProject.includePaths) {
std::string path = Path::simplifyPath(Path::getPathFromFilename(sharedProject.pathToProjectFile) + p);
Expand All @@ -1026,8 +1054,8 @@ bool ImportProject::importVcxproj(const std::string &filename, const tinyxml2::X

// Project files
PathMatch filtermatcher(fileFilters, Path::getCurrentPath());
for (const std::string &cfilename : compileList) {
if (!fileFilters.empty() && !filtermatcher.match(cfilename))
for (const ItemGroupClCompile &compile : compileList) {
if (!fileFilters.empty() && !filtermatcher.match(compile.filename))
continue;

for (const ProjectConfiguration &p : projectConfigurationList) {
Expand All @@ -1040,7 +1068,11 @@ bool ImportProject::importVcxproj(const std::string &filename, const tinyxml2::X
continue;
}

FileSettings fs{cfilename, Standards::Language::None, 0}; // file will be identified later on
// check if the file should be excluded for this configuration
if (!compile.exclude.empty() && compile.exclude.find(p.name) != compile.exclude.end())
continue;

FileSettings fs{ compile.filename, Standards::Language::None, 0}; // file will be identified later on
fs.cfg = p.name;
// TODO: detect actual MSC version
fs.msc = true;
Expand All @@ -1053,7 +1085,7 @@ bool ImportProject::importVcxproj(const std::string &filename, const tinyxml2::X
}
std::string additionalIncludePaths;
for (const ItemDefinitionGroup &i : itemDefinitionGroupList) {
if (!i.conditionIsTrue(p, cfilename, errors))
if (!i.conditionIsTrue(p, compile.filename, errors))
continue;
fs.standard = Standards::getCPP(i.cppstd);
fs.defines += ';' + i.preprocessorDefinitions;
Expand All @@ -1071,7 +1103,7 @@ bool ImportProject::importVcxproj(const std::string &filename, const tinyxml2::X
}
bool useUnicode = false;
for (const ConfigurationPropertyGroup &c : configurationPropertyGroups) {
if (!c.conditionIsTrue(p, cfilename, errors))
if (!c.conditionIsTrue(p, compile.filename, errors))
continue;
// in msbuild the last definition wins
useUnicode = c.useUnicode;
Expand All @@ -1081,10 +1113,11 @@ bool ImportProject::importVcxproj(const std::string &filename, const tinyxml2::X
fs.defines += ";UNICODE=1;_UNICODE=1";
}
fsSetDefines(fs, fs.defines);
fsSetIncludePaths(fs, Path::getPathFromFilename(filename), toStringList(includePath + ';' + additionalIncludePaths), variables);
fsSetIncludePaths(fs, Path::getPathFromFilename(compile.filename), toStringList(includePath + ';' + additionalIncludePaths), variables);
for (const auto &path : sharedItemsIncludePaths) {
fs.includePaths.emplace_back(path);
}

fileSettings.push_back(std::move(fs));
}
}
Expand Down
8 changes: 8 additions & 0 deletions test/cli/exclude/DebugX64.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include <iostream>

int foo()
{
std::cout << "DebugX64\n";
int x = 3 / 0; (void)x; // ERROR
return 0;
}
8 changes: 8 additions & 0 deletions test/cli/exclude/ReleaseX64.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include <iostream>

int foo()
{
std::cout << "ReleaseX64\n";
int x = 3 / 0; (void)x; // ERROR
return 0;
}
16 changes: 16 additions & 0 deletions test/cli/exclude/exclude.cppcheck
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="1">
<builddir>exclude-cppcheck-build-dir</builddir>
<importproject>exclude.slnx</importproject>
<analyze-all-vs-configs>false</analyze-all-vs-configs>
<check-headers>true</check-headers>
<check-unused-templates>true</check-unused-templates>
<inline-suppression>true</inline-suppression>
<max-ctu-depth>2</max-ctu-depth>
<max-template-recursion>100</max-template-recursion>
<vs-configurations>
<config>Debug</config>
</vs-configurations>
<check-level-normal/>
<project-name>exclude</project-name>
</project>
6 changes: 6 additions & 0 deletions test/cli/exclude/exclude.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<Solution>
<Configurations>
<Platform Name="x64" />
</Configurations>
<Project Path="exclude.vcxproj" Id="c9d1dca1-d8ff-4c05-9159-f00816645319" />
</Solution>
94 changes: 94 additions & 0 deletions test/cli/exclude/exclude.vcxproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>18.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{c9d1dca1-d8ff-4c05-9159-f00816645319}</ProjectGuid>
<RootNamespace>exclude</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Manifest>
<EnableSegmentHeap>true</EnableSegmentHeap>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Manifest>
<EnableSegmentHeap>true</EnableSegmentHeap>
</Manifest>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="DebugX64.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="ReleaseX64.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="foo.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
1 change: 1 addition & 0 deletions test/cli/exclude/foo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int foo();
20 changes: 20 additions & 0 deletions test/cli/exclude_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

# python -m pytest exclude_test.py

import os

from testutils import cppcheck

__script_dir = os.path.dirname(os.path.abspath(__file__))
__proj_dir = os.path.join(__script_dir, 'exclude')

def test_exclude():
args = [
'--template=cppcheck1',
'--project=exclude/exclude.cppcheck',
'--no-cppcheck-build-dir'
]
ret, stdout, stderr = cppcheck(args, cwd=__script_dir)
filename = os.path.join('exclude', 'DebugX64.cpp')
assert ret == 0, stdout
assert stderr == '[%s:6]: (error) Division by zero.\n' % filename
Loading