Skip to content

Commit 32b8cc6

Browse files
author
Felix Faber
committed
Rebasing...
1 parent fa5b1d5 commit 32b8cc6

2 files changed

Lines changed: 186 additions & 33 deletions

File tree

lib/importproject.cpp

Lines changed: 177 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ ImportProject::Type ImportProject::import(const std::string &filename, Settings
191191

192192
const std::vector<std::string> fileFilters =
193193
settings ? settings->fileFilters : std::vector<std::string>();
194+
std::vector<SharedItemsProject> sharedItemsProjects{};
194195

195196
if (endsWith(filename, ".json")) {
196197
if (importCompileCommands(fin)) {
@@ -204,7 +205,7 @@ ImportProject::Type ImportProject::import(const std::string &filename, Settings
204205
}
205206
} else if (endsWith(filename, ".vcxproj")) {
206207
std::map<std::string, std::string, cppcheck::stricmp> variables;
207-
if (importVcxproj(filename, variables, emptyString, fileFilters)) {
208+
if (importVcxproj(filename, variables, emptyString, fileFilters, sharedItemsProjects)) {
208209
setRelativePaths(filename);
209210
return ImportProject::Type::VS_VCXPROJ;
210211
}
@@ -446,7 +447,7 @@ bool ImportProject::importSln(std::istream &istr, const std::string &path, const
446447
variables["SolutionDir"] = path;
447448

448449
bool found = false;
449-
450+
std::vector<SharedItemsProject> sharedItemsProjects{};
450451
while (std::getline(istr,line)) {
451452
if (!startsWith(line,"Project("))
452453
continue;
@@ -824,15 +825,15 @@ bool ImportProject::importVcxproj(const std::string &filename, std::map<std::str
824825
return true;
825826
}
826827

827-
828-
bool ImportProject::importVcxitems(const std::string& filename, std::map<std::string, std::string, cppcheck::stricmp>& variables, const std::string& additionalIncludeDirectories, const std::vector<std::string>& fileFilters)
828+
bool ImportProject::importVcxproj(const std::string& filename, std::map<std::string, std::string, cppcheck::stricmp>& variables, const std::string& additionalIncludeDirectories, const std::vector<std::string>& fileFilters, std::vector<SharedItemsProject>& cache)
829829
{
830830
variables["ProjectDir"] = Path::simplifyPath(Path::getPathFromFilename(filename));
831831

832832
std::list<ProjectConfiguration> projectConfigurationList;
833833
std::list<std::string> compileList;
834834
std::list<ItemDefinitionGroup> itemDefinitionGroupList;
835835
std::string includePath;
836+
std::vector<SharedItemsProject> sharedItemsProjects;
836837

837838
bool useOfMfc = false;
838839

@@ -888,45 +889,57 @@ bool ImportProject::importVcxitems(const std::string& filename, std::map<std::st
888889
}
889890
}
890891
}
891-
}
892-
}
893-
// # TODO: support signedness of char via /J (and potential XML option for it)?
894-
// we can only set it globally but in this context it needs to be treated per file
895-
for (const std::string& c : compileList) {
896-
std::string cfilename = Path::simplifyPath(Path::isAbsolute(c) ? c : Path::getPathFromFilename(filename) + c);
897-
898-
// Remove "msbuild this file directory"
899-
{
900-
std::string toRemove("$(MSBuildThisFileDirectory)");
901-
size_t pos = cfilename.find(toRemove);
902-
while (pos != std::string::npos)
903-
{
904-
auto test = cfilename.erase(pos, toRemove.length());
905-
pos = cfilename.find(toRemove);
892+
else if (labelAttribute && std::strcmp(labelAttribute, "Shared") == 0) {
893+
for (const tinyxml2::XMLElement* e = node->FirstChildElement(); e; e = e->NextSiblingElement()) {
894+
if (std::strcmp(e->Name(), "Import") == 0) {
895+
const char* projectAttribute = e->Attribute("Project");
896+
if (projectAttribute)
897+
{
898+
std::string pathToSharedItemsFile(projectAttribute);
899+
if (!simplifyPathWithVariables(pathToSharedItemsFile, variables)) {
900+
printError("Could not simplify path to referenced shared items project");
901+
exit(-1);
902+
}
903+
sharedItemsProjects.emplace_back(importVcxitems(pathToSharedItemsFile, fileFilters, cache));
904+
}
905+
}
906+
}
906907
}
907908
}
909+
}
908910

911+
// Project files
912+
for (const std::string& c : compileList) {
913+
const std::string cfilename = Path::simplifyPath(Path::isAbsolute(c) ? c : Path::getPathFromFilename(filename) + c);
909914
if (!fileFilters.empty() && !matchglobs(fileFilters, cfilename))
910915
continue;
911916

912-
// TODO(Felix): make this robust by iterating over the projects,
913-
// checking retrieving their configurations and add them
914-
// if this the shared item project is referenced
915-
916-
// Assuming x64 configuration
917-
std::string configs[] = { "Debug|x64", "Release|x64", };
918-
for (auto& c : configs)
919-
{
917+
for (const ProjectConfiguration& p : projectConfigurationList) {
918+
919+
if (!guiProject.checkVsConfigs.empty()) {
920+
const bool doChecking = std::any_of(guiProject.checkVsConfigs.cbegin(), guiProject.checkVsConfigs.cend(), [&](const std::string& c) {
921+
return c == p.configuration;
922+
});
923+
if (!doChecking)
924+
continue;
925+
}
926+
920927
FileSettings fs;
921928
fs.filename = cfilename;
922-
fs.cfg = c;
923-
// TODO: detect actual MSC version
929+
fs.cfg = p.name;
924930
fs.msc = true;
925931
fs.useMfc = useOfMfc;
926-
fs.defines = "_WIN32=1;_WIN64=1";
927-
fs.platformType = cppcheck::Platform::Type::Win64;
932+
fs.defines = "_WIN32=1";
933+
if (p.platform == ProjectConfiguration::Win32)
934+
fs.platformType = cppcheck::Platform::Type::Win32W;
935+
else if (p.platform == ProjectConfiguration::x64) {
936+
fs.platformType = cppcheck::Platform::Type::Win64;
937+
fs.defines += ";_WIN64=1";
938+
}
928939
std::string additionalIncludePaths;
929940
for (const ItemDefinitionGroup& i : itemDefinitionGroupList) {
941+
if (!i.conditionIsTrue(p))
942+
continue;
930943
fs.standard = Standards::getCPP(i.cppstd);
931944
fs.defines += ';' + i.preprocessorDefinitions;
932945
if (i.enhancedInstructionSet == "StreamingSIMDExtensions")
@@ -947,9 +960,142 @@ bool ImportProject::importVcxitems(const std::string& filename, std::map<std::st
947960
}
948961
}
949962

963+
// Shared items files
964+
for (const auto& sharedProject : sharedItemsProjects) {
965+
for (const auto& c : sharedProject.sourceFiles) {
966+
const std::string cfilename = Path::simplifyPath(c);
967+
if (!fileFilters.empty() && !matchglobs(fileFilters, cfilename))
968+
continue;
969+
970+
for (const ProjectConfiguration& p : projectConfigurationList) {
971+
if (!guiProject.checkVsConfigs.empty()) {
972+
const bool doChecking = std::any_of(guiProject.checkVsConfigs.cbegin(), guiProject.checkVsConfigs.cend(), [&](const std::string& c) {
973+
return c == p.configuration;
974+
});
975+
if (!doChecking)
976+
continue;
977+
}
978+
979+
FileSettings fs;
980+
fs.filename = cfilename;
981+
fs.cfg = p.name;
982+
fs.msc = true;
983+
fs.useMfc = useOfMfc;
984+
fs.defines = "_WIN32=1";
985+
if (p.platform == ProjectConfiguration::Win32)
986+
fs.platformType = cppcheck::Platform::Type::Win32W;
987+
else if (p.platform == ProjectConfiguration::x64) {
988+
fs.platformType = cppcheck::Platform::Type::Win64;
989+
fs.defines += ";_WIN64=1";
990+
}
991+
std::string additionalIncludePaths;
992+
for (const ItemDefinitionGroup& i : itemDefinitionGroupList) {
993+
if (!i.conditionIsTrue(p))
994+
continue;
995+
fs.standard = Standards::getCPP(i.cppstd);
996+
fs.defines += ';' + i.preprocessorDefinitions;
997+
if (i.enhancedInstructionSet == "StreamingSIMDExtensions")
998+
fs.defines += ";__SSE__";
999+
else if (i.enhancedInstructionSet == "StreamingSIMDExtensions2")
1000+
fs.defines += ";__SSE2__";
1001+
else if (i.enhancedInstructionSet == "AdvancedVectorExtensions")
1002+
fs.defines += ";__AVX__";
1003+
else if (i.enhancedInstructionSet == "AdvancedVectorExtensions2")
1004+
fs.defines += ";__AVX2__";
1005+
else if (i.enhancedInstructionSet == "AdvancedVectorExtensions512")
1006+
fs.defines += ";__AVX512__";
1007+
additionalIncludePaths += ';' + i.additionalIncludePaths;
1008+
}
1009+
fs.setDefines(fs.defines);
1010+
fs.setIncludePaths(Path::getPathFromFilename(filename), toStringList(includePath + ';' + additionalIncludePaths), variables);
1011+
for (const auto& toAddIncludePath : sharedProject.includePaths) {
1012+
fs.includePaths.emplace_back(Path::simplifyPath(toAddIncludePath));
1013+
}
1014+
fileSettings.push_back(std::move(fs));
1015+
}
1016+
}
1017+
}
1018+
9501019
return true;
9511020
}
9521021

1022+
static std::string stringReplace(const std::string& original, const std::string& toReplace, const std::string& replaceWith)
1023+
{
1024+
std::string result(original);
1025+
size_t pos = result.find(toReplace);
1026+
while (pos != std::string::npos) {
1027+
result.replace(pos, toReplace.length(), replaceWith);
1028+
pos = result.find(toReplace);
1029+
}
1030+
return result;
1031+
}
1032+
1033+
ImportProject::SharedItemsProject ImportProject::importVcxitems(const std::string& filename, const std::vector<std::string>& fileFilters, std::vector<SharedItemsProject> &cache)
1034+
{
1035+
for (const auto& entry : cache)
1036+
{
1037+
if (filename == entry.pathToProjectFile)
1038+
{
1039+
return entry;
1040+
}
1041+
}
1042+
1043+
std::string projectDir = Path::simplifyPath(Path::getPathFromFilename(filename));
1044+
if (projectDir.empty())
1045+
{
1046+
projectDir = std::string("./");
1047+
}
1048+
1049+
SharedItemsProject result{};
1050+
result.pathToProjectFile = filename;
1051+
1052+
tinyxml2::XMLDocument doc;
1053+
const tinyxml2::XMLError error = doc.LoadFile(filename.c_str());
1054+
if (error != tinyxml2::XML_SUCCESS) {
1055+
printError(std::string("Visual Studio project file is not a valid XML - ") + tinyxml2::XMLDocument::ErrorIDToName(error));
1056+
exit(-1);
1057+
}
1058+
const tinyxml2::XMLElement* const rootnode = doc.FirstChildElement();
1059+
if (rootnode == nullptr) {
1060+
printError("Visual Studio project file has no XML root node");
1061+
exit(-1);
1062+
}
1063+
for (const tinyxml2::XMLElement* node = rootnode->FirstChildElement(); node; node = node->NextSiblingElement()) {
1064+
if (std::strcmp(node->Name(), "ItemGroup") == 0) {
1065+
const char* labelAttribute = node->Attribute("Label");
1066+
for (const tinyxml2::XMLElement* e = node->FirstChildElement(); e; e = e->NextSiblingElement()) {
1067+
if (std::strcmp(e->Name(), "ClCompile") == 0) {
1068+
const char* include = e->Attribute("Include");
1069+
if (include && Path::acceptFile(include)) {
1070+
std::string filename = stringReplace(include, "$(MSBuildThisFileDirectory)", projectDir);
1071+
1072+
// Don't include file if it matches the filter
1073+
if (!fileFilters.empty() && !matchglobs(fileFilters, filename))
1074+
continue;
1075+
1076+
result.sourceFiles.emplace_back(filename);
1077+
} else {
1078+
printError("Could not find shared items source file");
1079+
exit(-1);
1080+
}
1081+
}
1082+
}
1083+
}
1084+
else if (std::strcmp(node->Name(), "ItemDefinitionGroup") == 0) {
1085+
ItemDefinitionGroup temp(node, "");
1086+
for (const auto& includePath : toStringList(temp.additionalIncludePaths)) {
1087+
if (includePath == std::string("%(AdditionalIncludeDirectories)"))
1088+
continue;
1089+
1090+
result.includePaths.emplace_back(stringReplace(includePath, "$(MSBuildThisFileDirectory)", projectDir));
1091+
}
1092+
}
1093+
}
1094+
1095+
cache.emplace_back(result);
1096+
return result;
1097+
}
1098+
9531099
bool ImportProject::importBcb6Prj(const std::string &projectFilename)
9541100
{
9551101
tinyxml2::XMLDocument doc;

lib/importproject.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,17 @@ class CPPCHECKLIB WARN_UNUSED ImportProject {
9999
bool importCompileCommands(std::istream &istr);
100100
bool importCppcheckGuiProject(std::istream &istr, Settings *settings);
101101
virtual bool sourceFileExists(const std::string &file);
102+
102103
private:
104+
struct SharedItemsProject {
105+
std::string pathToProjectFile;
106+
std::vector<std::string> includePaths;
107+
std::vector<std::string> sourceFiles;
108+
};
109+
103110
bool importSln(std::istream &istr, const std::string &path, const std::vector<std::string> &fileFilters);
104-
bool importVcxproj(const std::string &filename, std::map<std::string, std::string, cppcheck::stricmp> &variables, const std::string &additionalIncludeDirectories, const std::vector<std::string> &fileFilters);
105-
bool importVcxitems(const std::string& filename, std::map<std::string, std::string, cppcheck::stricmp>& variables, const std::string& additionalIncludeDirectories, const std::vector<std::string>& fileFilters);
111+
static SharedItemsProject importVcxitems(const std::string& filename, const std::vector<std::string>& fileFilters, std::vector<SharedItemsProject> &cache);
112+
bool importVcxproj(const std::string &filename, std::map<std::string, std::string, cppcheck::stricmp> &variables, const std::string &additionalIncludeDirectories, const std::vector<std::string> &fileFilters, std::vector<SharedItemsProject> &cache);
106113
bool importBcb6Prj(const std::string &projectFilename);
107114

108115
static void printError(const std::string &message);

0 commit comments

Comments
 (0)