[Scummvm-git-logs] scummvm master -> 667cb638234b554eb293c54a350ecf721c0a1da7
SupSuper
noreply at scummvm.org
Fri Sep 29 20:37:14 UTC 2023
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
667cb63823 DEVTOOLS: Add precompiled header support to MSBuild/MSVC.
Commit: 667cb638234b554eb293c54a350ecf721c0a1da7
https://github.com/scummvm/scummvm/commit/667cb638234b554eb293c54a350ecf721c0a1da7
Author: elasota (ejlasota at gmail.com)
Date: 2023-09-29T21:37:10+01:00
Commit Message:
DEVTOOLS: Add precompiled header support to MSBuild/MSVC.
Changed paths:
.gitignore
devtools/create_project/cmake.cpp
devtools/create_project/cmake.h
devtools/create_project/codeblocks.cpp
devtools/create_project/codeblocks.h
devtools/create_project/create_project.cpp
devtools/create_project/create_project.h
devtools/create_project/msbuild.cpp
devtools/create_project/msbuild.h
devtools/create_project/xcode.cpp
devtools/create_project/xcode.h
diff --git a/.gitignore b/.gitignore
index 1dadcfd7e5b..b998a66e579 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@
*.dwp
lib*.a
.deps
+*_pch.cpp
/config.log
/scummvm
diff --git a/devtools/create_project/cmake.cpp b/devtools/create_project/cmake.cpp
index dfaf53b4d00..9929d1fc80d 100644
--- a/devtools/create_project/cmake.cpp
+++ b/devtools/create_project/cmake.cpp
@@ -270,7 +270,7 @@ static std::string filePrefix(const BuildSetup &setup, const std::string &module
}
void CMakeProvider::createProjectFile(const std::string &name, const std::string &, const BuildSetup &setup, const std::string &moduleDir,
- const StringList &includeList, const StringList &excludeList) {
+ const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) {
const std::string projectFile = setup.outputDir + "/CMakeLists.txt";
std::ofstream project(projectFile.c_str(), std::ofstream::out | std::ofstream::app);
@@ -284,12 +284,12 @@ void CMakeProvider::createProjectFile(const std::string &name, const std::string
project << "add_library(" << name << "\n";
} else {
enginesStr << "add_engine(" << name << "\n";
- addFilesToProject(moduleDir, enginesStr, includeList, excludeList, filePrefix(setup, moduleDir));
+ addFilesToProject(moduleDir, enginesStr, includeList, excludeList, pchIncludeRoot, pchDirs, pchExclude, filePrefix(setup, moduleDir));
enginesStr << ")\n\n";
return;
}
- addFilesToProject(moduleDir, project, includeList, excludeList, filePrefix(setup, moduleDir));
+ addFilesToProject(moduleDir, project, includeList, excludeList, pchIncludeRoot, pchDirs, pchExclude, filePrefix(setup, moduleDir));
project << ")\n";
project << "\n";
@@ -356,12 +356,13 @@ void CMakeProvider::writeDefines(const BuildSetup &setup, std::ofstream &output)
}
void CMakeProvider::writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int indentation,
- const std::string &objPrefix, const std::string &filePrefix) {
+ const std::string &objPrefix, const std::string &filePrefix,
+ const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) {
std::string lastName;
for (const FileNode *node : dir.children) {
if (!node->children.empty()) {
- writeFileListToProject(*node, projectFile, indentation + 1, objPrefix + node->name + '_', filePrefix + node->name + '/');
+ writeFileListToProject(*node, projectFile, indentation + 1, objPrefix + node->name + '_', filePrefix + node->name + '/', pchIncludeRoot, pchDirs, pchExclude);
} else {
std::string name, ext;
splitFilename(node->name, name, ext);
diff --git a/devtools/create_project/cmake.h b/devtools/create_project/cmake.h
index 9020d2a7394..7bb38bf0b1b 100644
--- a/devtools/create_project/cmake.h
+++ b/devtools/create_project/cmake.h
@@ -45,10 +45,11 @@ protected:
void addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) final {}
void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
- const StringList &includeList, const StringList &excludeList) final;
+ const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) final;
void writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int indentation,
- const std::string &objPrefix, const std::string &filePrefix) final;
+ const std::string &objPrefix, const std::string &filePrefix,
+ const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) final;
const char *getProjectExtension() final;
diff --git a/devtools/create_project/codeblocks.cpp b/devtools/create_project/codeblocks.cpp
index bc72ba332cb..a5e88d6b364 100644
--- a/devtools/create_project/codeblocks.cpp
+++ b/devtools/create_project/codeblocks.cpp
@@ -97,7 +97,7 @@ StringList getFeatureLibraries(const BuildSetup &setup) {
}
void CodeBlocksProvider::createProjectFile(const std::string &name, const std::string &, const BuildSetup &setup, const std::string &moduleDir,
- const StringList &includeList, const StringList &excludeList) {
+ const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) {
const std::string projectFile = setup.outputDir + '/' + name + getProjectExtension();
std::ofstream project(projectFile.c_str());
@@ -210,9 +210,9 @@ void CodeBlocksProvider::createProjectFile(const std::string &name, const std::s
}
if (!modulePath.empty())
- addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix + '/' + modulePath);
+ addFilesToProject(moduleDir, project, includeList, excludeList, pchIncludeRoot, pchDirs, pchExclude, setup.filePrefix + '/' + modulePath);
else
- addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix);
+ addFilesToProject(moduleDir, project, includeList, excludeList, pchIncludeRoot, pchDirs, pchExclude, setup.filePrefix);
project << "\t\t<Extensions>\n"
@@ -249,13 +249,14 @@ void CodeBlocksProvider::writeDefines(const StringList &defines, std::ofstream &
}
void CodeBlocksProvider::writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int indentation,
- const std::string &objPrefix, const std::string &filePrefix) {
+ const std::string &objPrefix, const std::string &filePrefix,
+ const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) {
for (FileNode::NodeList::const_iterator i = dir.children.begin(); i != dir.children.end(); ++i) {
const FileNode *node = *i;
if (!node->children.empty()) {
- writeFileListToProject(*node, projectFile, indentation + 1, objPrefix + node->name + '_', filePrefix + node->name + '/');
+ writeFileListToProject(*node, projectFile, indentation + 1, objPrefix + node->name + '_', filePrefix + node->name + '/', pchIncludeRoot, pchDirs, pchExclude);
} else {
std::string name, ext;
splitFilename(node->name, name, ext);
diff --git a/devtools/create_project/codeblocks.h b/devtools/create_project/codeblocks.h
index 9ef68e63ccc..8718d47041a 100644
--- a/devtools/create_project/codeblocks.h
+++ b/devtools/create_project/codeblocks.h
@@ -39,10 +39,11 @@ protected:
void addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) final;
void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
- const StringList &includeList, const StringList &excludeList) final;
+ const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) final;
void writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int indentation,
- const std::string &objPrefix, const std::string &filePrefix) final;
+ const std::string &objPrefix, const std::string &filePrefix,
+ const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) final;
void writeReferences(const BuildSetup &setup, std::ofstream &output) final;
diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp
index b64cef443cb..39310293b0d 100644
--- a/devtools/create_project/create_project.cpp
+++ b/devtools/create_project/create_project.cpp
@@ -1319,6 +1319,55 @@ void splitPath(const std::string &path, std::string &dir, std::string &file) {
file = (sep == std::string::npos) ? std::string() : path.substr(sep + 1);
}
+bool calculatePchPaths(const std::string &sourceFilePath, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude, char separator, std::string &outPchIncludePath, std::string &outPchFilePath, std::string &outPchFileName) {
+ std::string compareName, extensionName;
+ splitFilename(sourceFilePath, compareName, extensionName);
+
+ // Is this file excluded?
+ if (std::find(pchExclude.begin(), pchExclude.end(), compareName) != pchExclude.end())
+ return false;
+
+ size_t lastDelimiter = sourceFilePath.find_last_of(separator);
+ if (lastDelimiter == std::string::npos)
+ lastDelimiter = 0;
+
+ std::string pchDirectory = sourceFilePath.substr(0, lastDelimiter);
+
+ if (std::find(pchDirs.begin(), pchDirs.end(), pchDirectory) == pchDirs.end())
+ return false;
+
+ // This file uses a PCH
+ if (pchDirectory.size() < pchIncludeRoot.size() || pchDirectory.substr(0, pchIncludeRoot.size()) != pchIncludeRoot) {
+ error("PCH prefix for file '" + sourceFilePath + "' wasn't located under PCH include root '" + pchIncludeRoot + "'");
+ }
+
+ size_t pchDirNamePos = pchDirectory.find_last_of(separator);
+ if (pchDirNamePos == std::string::npos)
+ pchDirNamePos = 0;
+ else
+ pchDirNamePos++;
+
+ std::string pchFileName = pchDirectory.substr(pchDirNamePos) + "_pch.h";
+
+ std::string pchPath = (pchDirectory + separator + pchFileName);
+
+ // Convert to the local file prefix
+ std::string includePath = pchPath.substr(pchIncludeRoot.size());
+
+ if (separator != '/') {
+ for (std::string::iterator ch = includePath.begin(), chEnd = includePath.end(); ch != chEnd; ++ch) {
+ if (*ch == separator)
+ *ch = '/';
+ }
+ }
+
+ outPchIncludePath = includePath;
+ outPchFilePath = pchPath;
+ outPchFileName = pchFileName;
+
+ return true;
+}
+
std::string basename(const std::string &fileName) {
const std::string::size_type slash = fileName.find_last_of('/');
if (slash == std::string::npos)
@@ -1586,7 +1635,7 @@ void ProjectProvider::createProject(BuildSetup &setup) {
createWorkspace(setup);
- StringList in, ex;
+ StringList in, ex, pchDirs, pchEx;
// Create project files
for (UUIDMap::const_iterator i = _engineUuidMap.begin(); i != _engineUuidMap.end(); ++i) {
@@ -1595,11 +1644,13 @@ void ProjectProvider::createProject(BuildSetup &setup) {
// Retain the files between engines if we're creating a single project
in.clear();
ex.clear();
+ pchDirs.clear();
+ pchEx.clear();
const std::string moduleDir = setup.srcDir + targetFolder + i->first;
- createModuleList(moduleDir, setup.defines, setup.testDirs, in, ex);
- createProjectFile(i->first, i->second, setup, moduleDir, in, ex);
+ createModuleList(moduleDir, setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
+ createProjectFile(i->first, i->second, setup, moduleDir, in, ex, setup.srcDir + targetFolder, pchDirs, pchEx);
}
// Create engine-detection submodules.
@@ -1623,37 +1674,40 @@ void ProjectProvider::createProject(BuildSetup &setup) {
}
for (std::vector<std::string>::const_iterator i = detectionModuleDirs.begin(), end = detectionModuleDirs.end(); i != end; ++i) {
- createModuleList(*i, setup.defines, setup.testDirs, in, ex, true);
+ StringList tempPchDirs, tempSchEx; // No PCH for detection
+ createModuleList(*i, setup.defines, setup.testDirs, in, ex, tempPchDirs, tempSchEx, true);
}
- createProjectFile(detProject, detUUID, setup, setup.srcDir + "/engines", in, ex);
+ createProjectFile(detProject, detUUID, setup, setup.srcDir + "/engines", in, ex, "", StringList(), StringList());
}
if (!setup.devTools) {
// Last but not least create the main project file.
in.clear();
ex.clear();
+ pchDirs.clear();
+ pchEx.clear();
// File list for the Project file
- createModuleList(setup.srcDir + "/backends", setup.defines, setup.testDirs, in, ex);
- createModuleList(setup.srcDir + "/backends/platform/sdl", setup.defines, setup.testDirs, in, ex);
- createModuleList(setup.srcDir + "/base", setup.defines, setup.testDirs, in, ex);
- createModuleList(setup.srcDir + "/common", setup.defines, setup.testDirs, in, ex);
- createModuleList(setup.srcDir + "/common/compression", setup.defines, setup.testDirs, in, ex);
- createModuleList(setup.srcDir + "/common/formats", setup.defines, setup.testDirs, in, ex);
- createModuleList(setup.srcDir + "/common/lua", setup.defines, setup.testDirs, in, ex);
- createModuleList(setup.srcDir + "/engines", setup.defines, setup.testDirs, in, ex);
- createModuleList(setup.srcDir + "/graphics", setup.defines, setup.testDirs, in, ex);
- createModuleList(setup.srcDir + "/gui", setup.defines, setup.testDirs, in, ex);
- createModuleList(setup.srcDir + "/audio", setup.defines, setup.testDirs, in, ex);
- createModuleList(setup.srcDir + "/video", setup.defines, setup.testDirs, in, ex);
- createModuleList(setup.srcDir + "/image", setup.defines, setup.testDirs, in, ex);
- createModuleList(setup.srcDir + "/math", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/backends", setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
+ createModuleList(setup.srcDir + "/backends/platform/sdl", setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
+ createModuleList(setup.srcDir + "/base", setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
+ createModuleList(setup.srcDir + "/common", setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
+ createModuleList(setup.srcDir + "/common/compression", setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
+ createModuleList(setup.srcDir + "/common/formats", setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
+ createModuleList(setup.srcDir + "/common/lua", setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
+ createModuleList(setup.srcDir + "/engines", setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
+ createModuleList(setup.srcDir + "/graphics", setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
+ createModuleList(setup.srcDir + "/gui", setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
+ createModuleList(setup.srcDir + "/audio", setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
+ createModuleList(setup.srcDir + "/video", setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
+ createModuleList(setup.srcDir + "/image", setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
+ createModuleList(setup.srcDir + "/math", setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
if (getFeatureBuildState("mt32emu", setup.features))
- createModuleList(setup.srcDir + "/audio/softsynth/mt32", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/audio/softsynth/mt32", setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
if (setup.tests) {
- createModuleList(setup.srcDir + "/test", setup.defines, setup.testDirs, in, ex);
+ createModuleList(setup.srcDir + "/test", setup.defines, setup.testDirs, in, ex, pchDirs, pchEx);
} else {
// Resource files
addResourceFiles(setup, in, ex);
@@ -1678,7 +1732,7 @@ void ProjectProvider::createProject(BuildSetup &setup) {
}
// Create the main project file.
- createProjectFile(setup.projectName, svmUUID, setup, setup.srcDir, in, ex);
+ createProjectFile(setup.projectName, svmUUID, setup, setup.srcDir, in, ex, setup.srcDir + '/', pchDirs, pchEx);
}
// Create other misc. build files
@@ -1827,15 +1881,16 @@ std::string ProjectProvider::getLastPathComponent(const std::string &path) {
void ProjectProvider::addFilesToProject(const std::string &dir, std::ostream &projectFile,
const StringList &includeList, const StringList &excludeList,
+ const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude,
const std::string &filePrefix) {
FileNode *files = scanFiles(dir, includeList, excludeList);
- writeFileListToProject(*files, projectFile, 0, std::string(), filePrefix + '/');
+ writeFileListToProject(*files, projectFile, 0, std::string(), filePrefix + '/', pchIncludeRoot, pchDirs, pchExclude);
delete files;
}
-void ProjectProvider::createModuleList(const std::string &moduleDir, const StringList &defines, StringList &testDirs, StringList &includeList, StringList &excludeList, bool forDetection) const {
+void ProjectProvider::createModuleList(const std::string &moduleDir, const StringList &defines, StringList &testDirs, StringList &includeList, StringList &excludeList, StringList &pchDirs, StringList &pchExclude, bool forDetection) const {
const std::string moduleMkFile = moduleDir + "/module.mk";
std::ifstream moduleMk(moduleMkFile.c_str());
if (!moduleMk)
@@ -1948,6 +2003,68 @@ void ProjectProvider::createModuleList(const std::string &moduleDir, const Strin
++i;
}
}
+ } else if (*i == "MODULE_PCH_DIRS") {
+ if (tokens.size() < 3)
+ error("Malformed MODULE_PCH_DIRS definition in " + moduleMkFile);
+ ++i;
+
+ // This is not exactly correct, for example an ":=" would usually overwrite
+ // all already added files, but since we do only save the files inside
+ // includeList or excludeList currently, we couldn't handle such a case easily.
+ // (includeList and excludeList should always preserve their entries, not added
+ // by this function, thus we can't just clear them on ":=" or "=").
+ // But hopefully our module.mk files will never do such things anyway.
+ if (*i != ":=" && *i != "+=" && *i != "=")
+ error("Malformed MODULE_PCH_DIRS definition in " + moduleMkFile);
+
+ ++i;
+
+ while (i != tokens.end()) {
+ if (*i == "\\") {
+ std::getline(moduleMk, line);
+ tokens = tokenize(line);
+ i = tokens.begin();
+ } else {
+ std::string filename = moduleDir;
+ if ((*i) != ".")
+ filename += "/" + unifyPath(*i);
+
+ if (shouldInclude.top())
+ pchDirs.push_back(filename);
+
+ ++i;
+ }
+ }
+ } else if (*i == "MODULE_PCH_EXCLUDE") {
+ if (tokens.size() < 3)
+ error("Malformed MODULE_PCH_EXCLUDE definition in " + moduleMkFile);
+ ++i;
+
+ // This is not exactly correct, for example an ":=" would usually overwrite
+ // all already added files, but since we do only save the files inside
+ // includeList or excludeList currently, we couldn't handle such a case easily.
+ // (includeList and excludeList should always preserve their entries, not added
+ // by this function, thus we can't just clear them on ":=" or "=").
+ // But hopefully our module.mk files will never do such things anyway.
+ if (*i != ":=" && *i != "+=" && *i != "=")
+ error("Malformed MODULE_PCH_EXCLUDE definition in " + moduleMkFile);
+
+ ++i;
+
+ while (i != tokens.end()) {
+ if (*i == "\\") {
+ std::getline(moduleMk, line);
+ tokens = tokenize(line);
+ i = tokens.begin();
+ } else {
+ const std::string filename = moduleDir + "/" + unifyPath(*i);
+
+ if (shouldInclude.top())
+ pchExclude.push_back(filename);
+
+ ++i;
+ }
+ }
} else if (*i == "KYRARPG_COMMON_OBJ") {
// HACK to fix EOB/LOL compilation in the kyra engine: add the
// files defined in the KYRARPG_COMMON_OBJ variable in a list
diff --git a/devtools/create_project/create_project.h b/devtools/create_project/create_project.h
index 8c263b5695d..ce08bdf9053 100644
--- a/devtools/create_project/create_project.h
+++ b/devtools/create_project/create_project.h
@@ -409,6 +409,21 @@ void splitFilename(const std::string &fileName, std::string &name, std::string &
*/
void splitPath(const std::string &path, std::string &dir, std::string &file);
+/**
+ * Calculates the include path and PCH file path (without the base directory).
+ *
+ * @param filePath Path to the source file.
+ * @param pchIncludeRoot Path to the PCH inclusion root directory (ending with separator).
+ * @param pchDirs List of PCH directories.
+ * @param pchExclude List of PCH exclusions.
+ * @param separator Path separator
+ * @param outPchIncludePath Output path to be used by #include directives.
+ * @param outPchFilePath Output file path.
+ * @param outPchFileName Output file name.
+ * @return True if the file path uses PCH, false if not.
+ */
+bool calculatePchPaths(const std::string &sourceFilePath, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude, char separator, std::string &outPchIncludePath, std::string &outPchFilePath, std::string &outPchFileName);
+
/**
* Returns the basename of a path.
* examples:
@@ -551,7 +566,7 @@ protected:
* @param excludeList Files to exclude (must have "moduleDir" as prefix).
*/
virtual void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
- const StringList &includeList, const StringList &excludeList) = 0;
+ const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) = 0;
/**
* Writes file entries for the specified directory node into
@@ -564,7 +579,8 @@ protected:
* @param filePrefix Generic prefix to all files of the node.
*/
virtual void writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int indentation,
- const std::string &objPrefix, const std::string &filePrefix) = 0;
+ const std::string &objPrefix, const std::string &filePrefix,
+ const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) = 0;
/**
* Output a list of project references to the file stream
@@ -588,7 +604,8 @@ protected:
* @param filePrefix Prefix to use for relative path arguments.
*/
void addFilesToProject(const std::string &dir, std::ostream &projectFile,
- const StringList &includeList, const StringList &excludeList,
+ const StringList &includeList, const StringList &excludeList,
+ const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude,
const std::string &filePrefix);
/**
@@ -602,7 +619,7 @@ protected:
* @param includeList Reference to a list, where included files should be added.
* @param excludeList Reference to a list, where excluded files should be added.
*/
- void createModuleList(const std::string &moduleDir, const StringList &defines, StringList &testDirs, StringList &includeList, StringList &excludeList, bool forDetection = false) const;
+ void createModuleList(const std::string &moduleDir, const StringList &defines, StringList &testDirs, StringList &includeList, StringList &excludeList, StringList &pchDirs, StringList &pchExclude, bool forDetection = false) const;
/**
* Creates an UUID for every enabled engine of the
diff --git a/devtools/create_project/msbuild.cpp b/devtools/create_project/msbuild.cpp
index 44fdce9ae10..07a165554e0 100644
--- a/devtools/create_project/msbuild.cpp
+++ b/devtools/create_project/msbuild.cpp
@@ -81,7 +81,7 @@ inline void outputProperties(const BuildSetup &setup, std::ostream &project, con
} // End of anonymous namespace
void MSBuildProvider::createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
- const StringList &includeList, const StringList &excludeList) {
+ const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) {
const std::string projectFile = setup.outputDir + '/' + name + getProjectExtension();
std::ofstream project(projectFile.c_str());
if (!project || !project.is_open()) {
@@ -156,9 +156,9 @@ void MSBuildProvider::createProjectFile(const std::string &name, const std::stri
}
if (!modulePath.empty())
- addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix + '/' + modulePath);
+ addFilesToProject(moduleDir, project, includeList, excludeList, pchIncludeRoot, pchDirs, pchExclude, setup.filePrefix + '/' + modulePath);
else
- addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix);
+ addFilesToProject(moduleDir, project, includeList, excludeList, pchIncludeRoot, pchDirs, pchExclude, setup.filePrefix);
// Output references for the main project
if (name == setup.projectName)
@@ -529,8 +529,52 @@ void MSBuildProvider::outputNasmCommand(std::ostream &projectFile, const std::st
}
}
+void MSBuildProvider::insertPathIntoDirectory(FileNode &dir, const std::string &path) {
+ size_t separatorLoc = path.find('\\');
+ if (separatorLoc != std::string::npos) {
+ // Inside of a subdirectory
+
+ std::string subdirName = path.substr(0, separatorLoc);
+
+ FileNode::NodeList::iterator dirIt = dir.children.begin();
+ FileNode::NodeList::iterator dirItEnd = dir.children.end();
+ while (dirIt != dirItEnd) {
+ if ((*dirIt)->name == subdirName)
+ break;
+
+ ++dirIt;
+ }
+
+ FileNode *dirNode = nullptr;
+ if (dirIt == dirItEnd) {
+ dirNode = new FileNode(subdirName);
+ dir.children.push_back(dirNode);
+ } else {
+ dirNode = *dirIt;
+ }
+
+ insertPathIntoDirectory(*dirNode, path.substr(separatorLoc + 1));
+ } else {
+ FileNode *fileNode = new FileNode(path);
+ dir.children.push_back(fileNode);
+ }
+}
+
+void MSBuildProvider::createFileNodesFromPCHList(FileNode &dir, const std::string &pathBase, const StringList &pchCompileFiles) {
+ for (StringList::const_iterator it = pchCompileFiles.begin(), itEnd = pchCompileFiles.end(); it != itEnd; ++it) {
+ const std::string &pchPath = *it;
+
+ if (pchPath.size() > pathBase.size() && pchPath.substr(0, pathBase.size()) == pathBase) {
+ std::string internalPath = pchPath.substr(pathBase.size());
+
+ insertPathIntoDirectory(dir, internalPath);
+ }
+ }
+}
+
void MSBuildProvider::writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int,
- const std::string &objPrefix, const std::string &filePrefix) {
+ const std::string &objPrefix, const std::string &filePrefix,
+ const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) {
// Reset lists
_filters.clear();
_compileFiles.clear();
@@ -544,12 +588,33 @@ void MSBuildProvider::writeFileListToProject(const FileNode &dir, std::ostream &
computeFileList(dir, objPrefix, filePrefix);
_filters.pop_back(); // remove last empty filter
+ StringList pchCompileFiles;
+
// Output compile, include, other and resource files
- outputFiles(projectFile, _compileFiles, "ClCompile");
+ outputCompileFiles(projectFile, pchIncludeRoot, pchDirs, pchExclude, pchCompileFiles);
outputFiles(projectFile, _includeFiles, "ClInclude");
outputFiles(projectFile, _otherFiles, "None");
outputFiles(projectFile, _resourceFiles, "ResourceCompile");
+ if (pchCompileFiles.size() > 0) {
+ // Generate filters and additional compile files for PCH files
+ FileNode pchDir(dir.name);
+ createFileNodesFromPCHList(pchDir, convertPathToWin(dir.name) + '\\', pchCompileFiles);
+
+ StringList backupFilters = _filters;
+ _filters.clear();
+
+ _filters.push_back(""); // init filters
+ computeFileList(pchDir, objPrefix, filePrefix);
+ _filters.pop_back(); // remove last empty filter
+
+ // Combine lists, removing duplicates
+ for (StringList::const_iterator it = backupFilters.begin(), itEnd = backupFilters.end(); it != itEnd; ++it) {
+ if (std::find(_filters.begin(), _filters.end(), *it) != _filters.end())
+ _filters.push_back(*it);
+ }
+ }
+
// Output asm files
if (!_asmFiles.empty()) {
projectFile << "\t<ItemGroup>\n";
@@ -579,6 +644,126 @@ void MSBuildProvider::outputFiles(std::ostream &projectFile, const FileEntries &
}
}
+void MSBuildProvider::outputCompileFiles(std::ostream &projectFile, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude, StringList &outPCHFiles) {
+ const FileEntries &files = _compileFiles;
+
+ const bool hasPCH = (pchDirs.size() > 0);
+
+ std::string pchIncludeRootWin;
+ StringList pchDirsWin;
+ StringList pchExcludeWin;
+
+ if (hasPCH) {
+ pchIncludeRootWin = convertPathToWin(pchIncludeRoot);
+
+ // Convert PCH paths to Win
+ for (StringList::const_iterator entry = pchDirs.begin(), end = pchDirs.end(); entry != end; ++entry) {
+ std::string convertedPath = convertPathToWin(*entry);
+ if (convertedPath.size() < pchIncludeRootWin.size() || convertedPath.substr(0, pchIncludeRootWin.size()) != pchIncludeRootWin) {
+ error("PCH path '" + convertedPath + "' wasn't located under PCH include root '" + pchIncludeRootWin + "'");
+ }
+
+ pchDirsWin.push_back(convertPathToWin(*entry));
+ }
+ for (StringList::const_iterator entry = pchExclude.begin(), end = pchExclude.end(); entry != end; ++entry) {
+ const std::string path = *entry;
+
+ if (path.size() >= 2 && path[path.size() - 1] == 'o' && path[path.size() - 2] == '.')
+ pchExcludeWin.push_back(convertPathToWin(path.substr(0, path.size() - 2)));
+ }
+ }
+
+ std::map<std::string, PCHInfo> pchMap;
+
+ if (!files.empty()) {
+ projectFile << "\t<ItemGroup>\n";
+ for (FileEntries::const_iterator entry = files.begin(), end = files.end(); entry != end; ++entry) {
+ std::string pchIncludePath, pchFilePath, pchFileName;
+
+ bool fileHasPCH = false;
+ if (hasPCH)
+ fileHasPCH = calculatePchPaths(entry->path, pchIncludeRootWin, pchDirsWin, pchExcludeWin, '\\', pchIncludePath, pchFilePath, pchFileName);
+
+ if (fileHasPCH) {
+ std::string pchOutputFileName = "$(IntDir)dists\\msvc\\%(RelativeDir)" + pchFileName.substr(0, pchFileName.size() - 2) + ".pch";
+
+ PCHInfo &pchInfo = pchMap[pchFilePath];
+ pchInfo.file = pchIncludePath;
+ pchInfo.outputFile = pchOutputFileName;
+
+ projectFile << "\t\t<ClCompile Include=\"" << (*entry).path << "\">\n";
+ projectFile << "\t\t\t<PrecompiledHeader>Use</PrecompiledHeader>\n";
+ projectFile << "\t\t\t<PrecompiledHeaderFile>" << pchIncludePath << "</PrecompiledHeaderFile>\n";
+ projectFile << "\t\t\t<PrecompiledHeaderOutputFile>" << pchOutputFileName << "</PrecompiledHeaderOutputFile>\n";
+ projectFile << "\t\t</ClCompile>\n";
+ } else {
+ projectFile << "\t\t<ClCompile Include=\"" << (*entry).path << "\" />\n";
+ }
+ }
+
+ // Flush PCH files
+ for (std::map<std::string, PCHInfo>::const_iterator pchIt = pchMap.begin(), pchItEnd = pchMap.end(); pchIt != pchItEnd; ++pchIt) {
+ const PCHInfo &pchInfo = pchIt->second;
+
+ const std::string &filePath = pchIt->first;
+ assert(filePath.size() >= 2 && filePath.substr(filePath.size() - 2) == ".h");
+
+ std::string cppFilePath = filePath.substr(0, filePath.size() - 2) + ".cpp";
+
+ std::string expectedContents = "/* This file is automatically generated by create_project */\n"
+ "/* DO NOT EDIT MANUALLY */\n"
+ "#include \"" + pchInfo.file + "\"\n";
+
+ // Try to avoid touching the generated .cpp if it's identical to the expected output.
+ // If we touch the file, then every file that includes PCH needs to be recompiled.
+ std::ifstream pchInputFile(cppFilePath.c_str());
+ bool needToEmit = true;
+ if (pchInputFile && pchInputFile.is_open()) {
+ std::string fileContents;
+ for (;;) {
+ char buffer[1024];
+ size_t numRead = sizeof(buffer) - 1;
+ pchInputFile.read(buffer, numRead);
+
+ buffer[pchInputFile.gcount()] = '\0';
+
+ fileContents += buffer;
+
+ if (pchInputFile.eof() || pchInputFile.fail())
+ break;
+
+ if (fileContents.size() > expectedContents.size())
+ break;
+ }
+
+ needToEmit = (fileContents != expectedContents);
+ pchInputFile.close();
+ }
+
+ if (needToEmit) {
+ std::ofstream pchOutputFile(cppFilePath.c_str());
+ if (!pchOutputFile || !pchOutputFile.is_open()) {
+ error("Could not open \"" + cppFilePath + "\" for writing");
+ return;
+ }
+
+ pchOutputFile << expectedContents;
+ pchOutputFile.close();
+ }
+
+ projectFile << "\t\t<ClCompile Include=\"" << cppFilePath << "\">\n";
+ projectFile << "\t\t\t<PrecompiledHeader>Create</PrecompiledHeader>\n";
+ projectFile << "\t\t\t<PrecompiledHeaderFile>" << pchInfo.file << "</PrecompiledHeaderFile>\n";
+ projectFile << "\t\t\t<PrecompiledHeaderOutputFile>" << pchInfo.outputFile << "</PrecompiledHeaderOutputFile>\n";
+ projectFile << "\t\t</ClCompile>\n";
+
+ outPCHFiles.push_back(cppFilePath);
+ }
+
+ projectFile << "\t</ItemGroup>\n";
+ }
+}
+
void MSBuildProvider::computeFileList(const FileNode &dir, const std::string &objPrefix, const std::string &filePrefix) {
for (FileNode::NodeList::const_iterator i = dir.children.begin(); i != dir.children.end(); ++i) {
const FileNode *node = *i;
diff --git a/devtools/create_project/msbuild.h b/devtools/create_project/msbuild.h
index d5d25de2240..254ffef0592 100644
--- a/devtools/create_project/msbuild.h
+++ b/devtools/create_project/msbuild.h
@@ -32,12 +32,13 @@ public:
protected:
void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
- const StringList &includeList, const StringList &excludeList) override;
+ const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) override;
void outputProjectSettings(std::ofstream &project, const std::string &name, const BuildSetup &setup, bool isRelease, MSVC_Architecture arch, const std::string &configuration);
void writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int indentation,
- const std::string &objPrefix, const std::string &filePrefix) override;
+ const std::string &objPrefix, const std::string &filePrefix,
+ const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) override;
void writeReferences(const BuildSetup &setup, std::ofstream &output) override;
@@ -61,6 +62,11 @@ private:
};
typedef std::list<FileEntry> FileEntries;
+ struct PCHInfo {
+ std::string file;
+ std::string outputFile;
+ };
+
std::list<std::string> _filters; // list of filters (we need to create a GUID for each filter id)
FileEntries _compileFiles;
FileEntries _includeFiles;
@@ -73,8 +79,12 @@ private:
void outputFilter(std::ostream &filters, const FileEntries &files, const std::string &action);
void outputFiles(std::ostream &projectFile, const FileEntries &files, const std::string &action);
+ void outputCompileFiles(std::ostream &projectFile, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude, StringList &outPCHFiles);
void outputNasmCommand(std::ostream &projectFile, const std::string &config, const std::string &prefix);
+
+ static void createFileNodesFromPCHList(FileNode &dir, const std::string &pathBase, const StringList &pchCompileFiles);
+ static void insertPathIntoDirectory(FileNode &dir, const std::string &path);
};
} // namespace CreateProjectTool
diff --git a/devtools/create_project/xcode.cpp b/devtools/create_project/xcode.cpp
index 8232aec5dd1..32375d627d9 100644
--- a/devtools/create_project/xcode.cpp
+++ b/devtools/create_project/xcode.cpp
@@ -307,8 +307,10 @@ void XcodeProvider::addResourceFiles(const BuildSetup &setup, StringList &includ
includeList.push_back(setup.srcDir + "/" + *it);
}
+ StringList pchDirs, pchEx;
+
StringList td;
- createModuleList(setup.srcDir + "/backends/platform/ios7", setup.defines, td, includeList, excludeList);
+ createModuleList(setup.srcDir + "/backends/platform/ios7", setup.defines, td, includeList, excludeList, pchDirs, pchEx);
}
void XcodeProvider::createWorkspace(const BuildSetup &setup) {
@@ -343,7 +345,7 @@ void XcodeProvider::createOtherBuildFiles(const BuildSetup &setup) {
// Store information about a project here, for use at the end
void XcodeProvider::createProjectFile(const std::string &, const std::string &, const BuildSetup &setup, const std::string &moduleDir,
- const StringList &includeList, const StringList &excludeList) {
+ const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) {
std::string modulePath;
if (!moduleDir.compare(0, setup.srcDir.size(), setup.srcDir)) {
modulePath = moduleDir.substr(setup.srcDir.size());
@@ -353,9 +355,9 @@ void XcodeProvider::createProjectFile(const std::string &, const std::string &,
std::ofstream project;
if (!modulePath.empty())
- addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix + '/' + modulePath);
+ addFilesToProject(moduleDir, project, includeList, excludeList, pchIncludeRoot, pchDirs, pchExclude, setup.filePrefix + '/' + modulePath);
else
- addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix);
+ addFilesToProject(moduleDir, project, includeList, excludeList, pchIncludeRoot, pchDirs, pchExclude, setup.filePrefix);
}
//////////////////////////////////////////////////////////////////////////
@@ -402,7 +404,8 @@ void XcodeProvider::outputMainProjectFile(const BuildSetup &setup) {
// Files
//////////////////////////////////////////////////////////////////////////
void XcodeProvider::writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int indentation,
- const std::string &objPrefix, const std::string &filePrefix) {
+ const std::string &objPrefix, const std::string &filePrefix,
+ const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) {
// Ensure that top-level groups are generated for i.e. engines/
Group *group = touchGroupsForPath(filePrefix);
@@ -416,7 +419,7 @@ void XcodeProvider::writeFileListToProject(const FileNode &dir, std::ostream &pr
}
// Process child nodes
if (!node->children.empty())
- writeFileListToProject(*node, projectFile, indentation + 1, objPrefix + node->name + '_', filePrefix + node->name + '/');
+ writeFileListToProject(*node, projectFile, indentation + 1, objPrefix + node->name + '_', filePrefix + node->name + '/', pchIncludeRoot, pchDirs, pchExclude);
}
}
diff --git a/devtools/create_project/xcode.h b/devtools/create_project/xcode.h
index 939c14c831e..b4dfa6cd37f 100644
--- a/devtools/create_project/xcode.h
+++ b/devtools/create_project/xcode.h
@@ -42,10 +42,12 @@ protected:
void addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) final;
void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
- const StringList &includeList, const StringList &excludeList) final;
+ const StringList &includeList, const StringList &excludeList, const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) final;
void writeFileListToProject(const FileNode &dir, std::ostream &projectFile, const int indentation,
- const std::string &objPrefix, const std::string &filePrefix) final;
+ const std::string &objPrefix, const std::string &filePrefix,
+ const std::string &pchIncludeRoot, const StringList &pchDirs, const StringList &pchExclude) final;
+
private:
enum {
kSettingsAsList = 0x01,
More information about the Scummvm-git-logs
mailing list