mirror of
https://github.com/scummvm/scummvm.git
synced 2026-05-21 05:40:43 +00:00
DEVTOOLS: Add precompiled header support to MSBuild/MSVC.
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
*.dwp
|
||||
lib*.a
|
||||
.deps
|
||||
*_pch.cpp
|
||||
|
||||
/config.log
|
||||
/scummvm
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user