Visual Studio Solutions / Multiple project : How to effectively propagate project properties amongst several C++ projects

后端 未结 5 1363
南旧
南旧 2020-12-04 08:38

I am working with a Visual Studio 2005 C++ solution that includes multiple projects (about 30). Based upon my experience, it often becomes annoying to maintain all the prop

5条回答
  •  無奈伤痛
    2020-12-04 09:04

    I often need to do something similar since I link to the static runtime libraries. I wrote a program to do it for me. It basically scans all of the subdirectories of whatever path you give it and ids any .vcproj files it finds. Then one by one, it opens them modifies them and saves them. Since I only use it rarely, the path is hard coded it, but I think you'll be able to adjust it how you like.

    Another approach is to realize that Visual Studio Project files are simply XML files and can be manipulated with your favorite XML class. I've done something using C#'s XmlDocument for updating the include directories when there were A LOT of include directories that I didn't want to type in. :)

    I'm including both examples. You will need to modify them to your own needs, but these should get you started.

    This is the C++ version:

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    using boost::regex;
    using boost::filesystem::path;
    using namespace std;
    
    vector GetFileList(path dir, bool recursive, regex matchExp);
    void FixProjectFile(path file);
    string ReadFile( path &file );
    void ReplaceRuntimeLibraries( string& contents );
    void WriteFile(path file, string contents);
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        boost::timer stopwatch;
        boost::filesystem::path::default_name_check(boost::filesystem::native);
        regex projFileRegex("(.*)\\.vcproj");
        path rootPath("D:\\Programming\\Projects\\IPP_Decoder");
    
        vector targetFiles = GetFileList(rootPath, true, projFileRegex);
        double listTimeTaken = stopwatch.elapsed();
    
        std::for_each(targetFiles.begin(), targetFiles.end(), FixProjectFile);
    
        double totalTimeTaken = stopwatch.elapsed();
        return 0;
    }
    
    void FixProjectFile(path file) {
        string contents = ReadFile(file);
        ReplaceRuntimeLibraries(contents);
        WriteFile(file, contents);
    }
    
    vector GetFileList(path dir, bool recursive, regex matchExp) {
        vector paths;
        try {
            boost::filesystem::directory_iterator di(dir);
            boost::filesystem::directory_iterator end_iter;
            while (di != end_iter) {
                try {
                    if (is_directory(*di)) {
                        if (recursive) {
                            vector tempPaths = GetFileList(*di, recursive, matchExp);
                            paths.insert(paths.end(), tempPaths.begin(), tempPaths.end());
                        }
                    } else {
                        if (regex_match(di->string(), matchExp)) {
                            paths.push_back(*di);
                        }
                    }
                }
                catch (std::exception& e) {
                    string str = e.what();
                    cout << str << endl;
                    int breakpoint = 0;
                }
                ++di;
            }
        }
        catch (std::exception& e) {
            string str = e.what();
            cout << str << endl;
            int breakpoint = 0;
        }
        return paths;
    }
    
    string ReadFile( path &file ) {
    //  cout << "Reading file: " << file.native_file_string() << "\n";
        ifstream infile (file.native_file_string().c_str(), ios::in | ios::ate);
        assert (infile.is_open());
    
        streampos sz = infile.tellg();
        infile.seekg(0, ios::beg);
    
        vector v(sz);
        infile.read(&v[0], sz);
    
        string str (v.empty() ? string() : string (v.begin(), v.end()).c_str());
    
        return str;
    }
    
    void ReplaceRuntimeLibraries( string& contents ) {
        regex releaseRegex("RuntimeLibrary=\"2\"");
        regex debugRegex("RuntimeLibrary=\"3\"");
        string releaseReplacement("RuntimeLibrary=\"0\"");
        string debugReplacement("RuntimeLibrary=\"1\"");
        contents = boost::regex_replace(contents, releaseRegex, releaseReplacement);
        contents = boost::regex_replace(contents, debugRegex, debugReplacement);
    }
    
    void WriteFile(path file, string contents) {
        ofstream out(file.native_file_string().c_str() ,ios::out|ios::binary|ios::trunc); 
        out.write(contents.c_str(), contents.length());
    }
    

    This is the C# version. Enjoy...

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Xml;
    using System.IO;
    
    namespace ProjectUpdater
    {
        class Program
        {
            static public String rootPath = "D:\\dev\\src\\co\\UMC6\\";
            static void Main(string[] args)
            {
                String path = "D:/dev/src/co/UMC6/UMC.vcproj";
                FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                XmlDocument xmldoc = new XmlDocument();
                xmldoc.Load(fs);
                XmlNodeList oldFiles = xmldoc.GetElementsByTagName("Files");
                XmlNode rootNode = oldFiles[0].ParentNode;
                rootNode.RemoveChild(oldFiles[0]);
    
                XmlNodeList priorNode = xmldoc.GetElementsByTagName("References");
                XmlElement filesNode = xmldoc.CreateElement("Files");
                rootNode.InsertAfter(filesNode, priorNode[0]);
    
                DirectoryInfo di = new DirectoryInfo(rootPath);
                foreach (DirectoryInfo thisDir in di.GetDirectories())
                {
                    AddAllFiles(xmldoc, filesNode, thisDir.FullName);
                }
    
    
                List allDirectories = GetAllDirectories(rootPath);
                for (int i = 0; i < allDirectories.Count; ++i)
                {
                    allDirectories[i] = allDirectories[i].Replace(rootPath, "$(ProjectDir)");
                }
                String includeDirectories = "\"D:\\dev\\lib\\inc\\ipp\\\"";
                foreach (String dir in allDirectories) 
                {
                    includeDirectories += ";\"" + dir + "\"";
                }
    
                XmlNodeList toolNodes = xmldoc.GetElementsByTagName("Tool");
                foreach (XmlNode node in toolNodes)
                {
                    if (node.Attributes["Name"].Value == "VCCLCompilerTool") {
                        try
                        {
                            node.Attributes["AdditionalIncludeDirectories"].Value = includeDirectories;
                        }
                        catch (System.Exception e)
                        {
                            XmlAttribute newAttr = xmldoc.CreateAttribute("AdditionalIncludeDirectories");
                            newAttr.Value = includeDirectories;
                            node.Attributes.InsertBefore(newAttr, node.Attributes["PreprocessorDefinitions"]);
                        }
    
                    }
                }
                String pathOut = "D:/dev/src/co/UMC6/UMC.xml";
                FileStream fsOut = new FileStream(pathOut, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
                xmldoc.Save(fsOut);
    
            }
            static void AddAllFiles(XmlDocument doc, XmlElement parent, String path) {
                DirectoryInfo di = new DirectoryInfo(path);
                XmlElement thisElement = doc.CreateElement("Filter");
                thisElement.SetAttribute("Name", di.Name);
                foreach (FileInfo fi in di.GetFiles())
                {
                    XmlElement thisFile = doc.CreateElement("File");
                    String relPath = fi.FullName.Replace(rootPath, ".\\");
                    thisFile.SetAttribute("RelativePath", relPath);
                    thisElement.AppendChild(thisFile);
                }
                foreach (DirectoryInfo thisDir in di.GetDirectories())
                {
                    AddAllFiles(doc, thisElement, thisDir.FullName);
                }
                parent.AppendChild(thisElement);
            }
            static List GetAllDirectories(String dir)
            {
                DirectoryInfo di = new DirectoryInfo(dir);
                Console.WriteLine(dir);
    
                List files = new List();
                foreach (DirectoryInfo subDir in di.GetDirectories())
                {
                    List newList = GetAllDirectories(subDir.FullName);
                    files.Add(subDir.FullName);
                    files.AddRange(newList);
                }
                return files;
            }
            static List GetAllFiles(String dir)
            {
                DirectoryInfo di = new DirectoryInfo(dir);
                Console.WriteLine(dir);
    
                List files = new List();
                foreach (DirectoryInfo subDir in di.GetDirectories())
                {
                    List newList = GetAllFiles(subDir.FullName);
                    files.AddRange(newList);
                }
                foreach (FileInfo fi in di.GetFiles())
                {
                    files.Add(fi.FullName);
                }
                return files;
            }
        }
    }
    

提交回复
热议问题