3636#include < stack>
3737#include < unordered_set>
3838#include < utility>
39+ #include < vector>
3940
4041#include " xml.h"
4142
@@ -527,51 +528,11 @@ namespace {
527528 std::string platformStr;
528529 };
529530
530- struct ItemDefinitionGroup {
531- explicit ItemDefinitionGroup (const tinyxml2::XMLElement *idg, std::string includePaths) : additionalIncludePaths(std::move(includePaths)) {
531+ struct ConditionalGroup {
532+ explicit ConditionalGroup (const tinyxml2::XMLElement *idg) {
532533 const char *condAttr = idg->Attribute (" Condition" );
533534 if (condAttr)
534535 condition = condAttr;
535- for (const tinyxml2::XMLElement *e1 = idg->FirstChildElement (); e1 ; e1 = e1 ->NextSiblingElement ()) {
536- const char * name = e1 ->Name ();
537- if (std::strcmp (name, " ClCompile" ) == 0 ) {
538- enhancedInstructionSet = " StreamingSIMDExtensions2" ;
539- for (const tinyxml2::XMLElement *e = e1 ->FirstChildElement (); e; e = e->NextSiblingElement ()) {
540- const char * const text = e->GetText ();
541- if (!text)
542- continue ;
543- const char * const ename = e->Name ();
544- if (std::strcmp (ename, " PreprocessorDefinitions" ) == 0 )
545- preprocessorDefinitions = text;
546- else if (std::strcmp (ename, " AdditionalIncludeDirectories" ) == 0 ) {
547- if (!additionalIncludePaths.empty ())
548- additionalIncludePaths += ' ;' ;
549- additionalIncludePaths += text;
550- } else if (std::strcmp (ename, " LanguageStandard" ) == 0 ) {
551- if (std::strcmp (text, " stdcpp14" ) == 0 )
552- cppstd = Standards::CPP14;
553- else if (std::strcmp (text, " stdcpp17" ) == 0 )
554- cppstd = Standards::CPP17;
555- else if (std::strcmp (text, " stdcpp20" ) == 0 )
556- cppstd = Standards::CPP20;
557- else if (std::strcmp (text, " stdcpplatest" ) == 0 )
558- cppstd = Standards::CPPLatest;
559- } else if (std::strcmp (ename, " EnableEnhancedInstructionSet" ) == 0 ) {
560- enhancedInstructionSet = text;
561- }
562- }
563- }
564- else if (std::strcmp (name, " Link" ) == 0 ) {
565- for (const tinyxml2::XMLElement *e = e1 ->FirstChildElement (); e; e = e->NextSiblingElement ()) {
566- const char * const text = e->GetText ();
567- if (!text)
568- continue ;
569- if (std::strcmp (e->Name (), " EntryPointSymbol" ) == 0 ) {
570- entryPointSymbol = text;
571- }
572- }
573- }
574- }
575536 }
576537
577538 static void replaceAll (std::string &c, const std::string &from, const std::string &to) {
@@ -623,13 +584,75 @@ namespace {
623584 }
624585 return false ;
625586 }
587+ private:
626588 std::string condition;
589+ };
590+
591+ struct ItemDefinitionGroup : ConditionalGroup {
592+ explicit ItemDefinitionGroup (const tinyxml2::XMLElement *idg, std::string includePaths) : ConditionalGroup(idg), additionalIncludePaths(std::move(includePaths)) {
593+ for (const tinyxml2::XMLElement *e1 = idg->FirstChildElement (); e1 ; e1 = e1 ->NextSiblingElement ()) {
594+ const char * name = e1 ->Name ();
595+ if (std::strcmp (name, " ClCompile" ) == 0 ) {
596+ enhancedInstructionSet = " StreamingSIMDExtensions2" ;
597+ for (const tinyxml2::XMLElement *e = e1 ->FirstChildElement (); e; e = e->NextSiblingElement ()) {
598+ const char * const text = e->GetText ();
599+ if (!text)
600+ continue ;
601+ const char * const ename = e->Name ();
602+ if (std::strcmp (ename, " PreprocessorDefinitions" ) == 0 )
603+ preprocessorDefinitions = text;
604+ else if (std::strcmp (ename, " AdditionalIncludeDirectories" ) == 0 ) {
605+ if (!additionalIncludePaths.empty ())
606+ additionalIncludePaths += ' ;' ;
607+ additionalIncludePaths += text;
608+ } else if (std::strcmp (ename, " LanguageStandard" ) == 0 ) {
609+ if (std::strcmp (text, " stdcpp14" ) == 0 )
610+ cppstd = Standards::CPP14;
611+ else if (std::strcmp (text, " stdcpp17" ) == 0 )
612+ cppstd = Standards::CPP17;
613+ else if (std::strcmp (text, " stdcpp20" ) == 0 )
614+ cppstd = Standards::CPP20;
615+ else if (std::strcmp (text, " stdcpplatest" ) == 0 )
616+ cppstd = Standards::CPPLatest;
617+ } else if (std::strcmp (ename, " EnableEnhancedInstructionSet" ) == 0 ) {
618+ enhancedInstructionSet = text;
619+ }
620+ }
621+ }
622+ else if (std::strcmp (name, " Link" ) == 0 ) {
623+ for (const tinyxml2::XMLElement *e = e1 ->FirstChildElement (); e; e = e->NextSiblingElement ()) {
624+ const char * const text = e->GetText ();
625+ if (!text)
626+ continue ;
627+ if (std::strcmp (e->Name (), " EntryPointSymbol" ) == 0 ) {
628+ entryPointSymbol = text;
629+ }
630+ }
631+ }
632+ }
633+ }
634+
627635 std::string enhancedInstructionSet;
628636 std::string preprocessorDefinitions;
629637 std::string additionalIncludePaths;
630638 std::string entryPointSymbol; // TODO: use this
631639 Standards::cppstd_t cppstd = Standards::CPPLatest;
632640 };
641+
642+ struct ConfigutrationPropertyGroup : ConditionalGroup {
643+ explicit ConfigutrationPropertyGroup (const tinyxml2::XMLElement *idg) : ConditionalGroup(idg) {
644+ for (const tinyxml2::XMLElement *e = idg->FirstChildElement (); e; e = e->NextSiblingElement ()) {
645+ if (std::strcmp (e->Name (), " UseOfMfc" ) == 0 ) {
646+ useOfMfc = true ;
647+ } else if (std::strcmp (e->Name (), " CharacterSet" ) == 0 ) {
648+ useUnicode = std::strcmp (e->GetText (), " Unicode" ) == 0 ;
649+ }
650+ }
651+ }
652+
653+ bool useOfMfc = false ;
654+ bool useUnicode = false ;
655+ };
633656}
634657
635658static std::list<std::string> toStringList (const std::string &s)
@@ -648,25 +671,8 @@ static std::list<std::string> toStringList(const std::string &s)
648671 return ret;
649672}
650673
651- static void importPropertyGroup (const tinyxml2::XMLElement *node, std::map<std::string, std::string, cppcheck::stricmp> &variables, std::string &includePath, bool *useOfMfc, bool *useUnicode )
674+ static void importPropertyGroup (const tinyxml2::XMLElement *node, std::map<std::string, std::string, cppcheck::stricmp> &variables, std::string &includePath)
652675{
653- if (useOfMfc) {
654- for (const tinyxml2::XMLElement *e = node->FirstChildElement (); e; e = e->NextSiblingElement ()) {
655- if (std::strcmp (e->Name (), " UseOfMfc" ) == 0 ) {
656- *useOfMfc = true ;
657- break ;
658- }
659- }
660- }
661- if (useUnicode) {
662- for (const tinyxml2::XMLElement *e = node->FirstChildElement (); e; e = e->NextSiblingElement ()) {
663- if (std::strcmp (e->Name (), " CharacterSet" ) == 0 ) {
664- *useUnicode = std::strcmp (e->GetText (), " Unicode" ) == 0 ;
665- break ;
666- }
667- }
668- }
669-
670676 const char * labelAttribute = node->Attribute (" Label" );
671677 if (labelAttribute && std::strcmp (labelAttribute, " UserMacros" ) == 0 ) {
672678 for (const tinyxml2::XMLElement *propertyGroup = node->FirstChildElement (); propertyGroup; propertyGroup = propertyGroup->NextSiblingElement ()) {
@@ -727,32 +733,39 @@ static void loadVisualStudioProperties(const std::string &props, std::map<std::s
727733 }
728734 }
729735 } else if (std::strcmp (name," PropertyGroup" )==0 ) {
730- importPropertyGroup (node, variables, includePath, nullptr , nullptr );
736+ importPropertyGroup (node, variables, includePath);
731737 } else if (std::strcmp (name," ItemDefinitionGroup" )==0 ) {
732738 itemDefinitionGroupList.emplace_back (node, additionalIncludeDirectories);
733739 }
734740 }
735741}
736742
737- 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)
743+ bool ImportProject::importVcxproj (const std::string &filename,
744+ std::map<std::string, std::string, cppcheck::stricmp> &variables,
745+ const std::string &additionalIncludeDirectories,
746+ const std::vector<std::string> &fileFilters,
747+ std::vector<SharedItemsProject> &cache)
748+ {
749+ tinyxml2::XMLDocument doc;
750+ const tinyxml2::XMLError error = doc.LoadFile (filename.c_str ());
751+ if (error != tinyxml2::XML_SUCCESS) {
752+ printError (std::string (" Visual Studio project file is not a valid XML - " ) + tinyxml2::XMLDocument::ErrorIDToName (error));
753+ return false ;
754+ }
755+ return importVcxproj (filename, doc, variables, additionalIncludeDirectories, fileFilters, cache);
756+ }
757+
758+ bool ImportProject::importVcxproj (const std::string &filename, const tinyxml2::XMLDocument &doc, std::map<std::string, std::string, cppcheck::stricmp> &variables, const std::string &additionalIncludeDirectories, const std::vector<std::string> &fileFilters, std::vector<SharedItemsProject> &cache)
738759{
739760 variables[" ProjectDir" ] = Path::simplifyPath (Path::getPathFromFilename (filename));
740761
741762 std::list<ProjectConfiguration> projectConfigurationList;
742763 std::list<std::string> compileList;
743764 std::list<ItemDefinitionGroup> itemDefinitionGroupList;
765+ std::vector<ConfigutrationPropertyGroup> configurationPropertyGroups;
744766 std::string includePath;
745767 std::vector<SharedItemsProject> sharedItemsProjects;
746768
747- bool useOfMfc = false ;
748- bool useUnicode = false ;
749-
750- tinyxml2::XMLDocument doc;
751- const tinyxml2::XMLError error = doc.LoadFile (filename.c_str ());
752- if (error != tinyxml2::XML_SUCCESS) {
753- printError (std::string (" Visual Studio project file is not a valid XML - " ) + tinyxml2::XMLDocument::ErrorIDToName (error));
754- return false ;
755- }
756769 const tinyxml2::XMLElement * const rootnode = doc.FirstChildElement ();
757770 if (rootnode == nullptr ) {
758771 printError (" Visual Studio project file has no XML root node" );
@@ -786,7 +799,12 @@ bool ImportProject::importVcxproj(const std::string &filename, std::map<std::str
786799 } else if (std::strcmp (name, " ItemDefinitionGroup" ) == 0 ) {
787800 itemDefinitionGroupList.emplace_back (node, additionalIncludeDirectories);
788801 } else if (std::strcmp (name, " PropertyGroup" ) == 0 ) {
789- importPropertyGroup (node, variables, includePath, &useOfMfc, &useUnicode);
802+ const char * labelAttribute = node->Attribute (" Label" );
803+ if (labelAttribute && std::strcmp (labelAttribute, " Configuration" ) == 0 ) {
804+ configurationPropertyGroups.emplace_back (node);
805+ } else {
806+ importPropertyGroup (node, variables, includePath);
807+ }
790808 } else if (std::strcmp (name, " ImportGroup" ) == 0 ) {
791809 const char *labelAttribute = node->Attribute (" Label" );
792810 if (labelAttribute && std::strcmp (labelAttribute, " PropertySheets" ) == 0 ) {
@@ -862,7 +880,6 @@ bool ImportProject::importVcxproj(const std::string &filename, std::map<std::str
862880 fs.cfg = p.name ;
863881 // TODO: detect actual MSC version
864882 fs.msc = true ;
865- fs.useMfc = useOfMfc;
866883 fs.defines = " _WIN32=1" ;
867884 if (p.platform == ProjectConfiguration::Win32)
868885 fs.platformType = Platform::Type::Win32W;
@@ -888,8 +905,13 @@ bool ImportProject::importVcxproj(const std::string &filename, std::map<std::str
888905 fs.defines += " ;__AVX512__" ;
889906 additionalIncludePaths += ' ;' + i.additionalIncludePaths ;
890907 }
891- if (useUnicode) {
892- fs.defines += " ;UNICODE=1;_UNICODE=1" ;
908+ for (const ConfigutrationPropertyGroup &c : configurationPropertyGroups) {
909+ if (!c.conditionIsTrue (p))
910+ continue ;
911+ if (c.useUnicode ) {
912+ fs.defines += " ;UNICODE=1;_UNICODE=1" ;
913+ }
914+ fs.useMfc = c.useOfMfc ;
893915 }
894916 fsSetDefines (fs, fs.defines );
895917 fsSetIncludePaths (fs, Path::getPathFromFilename (filename), toStringList (includePath + ' ;' + additionalIncludePaths), variables);
0 commit comments