summaryrefslogtreecommitdiff
path: root/source/slang/slang-emit-dependency-file.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-emit-dependency-file.cpp')
-rw-r--r--source/slang/slang-emit-dependency-file.cpp125
1 files changed, 125 insertions, 0 deletions
diff --git a/source/slang/slang-emit-dependency-file.cpp b/source/slang/slang-emit-dependency-file.cpp
new file mode 100644
index 000000000..a482b08de
--- /dev/null
+++ b/source/slang/slang-emit-dependency-file.cpp
@@ -0,0 +1,125 @@
+// slang-emit-dependency-file.cpp
+#include "slang-emit-dependency-file.h"
+
+#include "slang-compiler.h"
+
+namespace Slang
+{
+
+static void _writeString(Stream& stream, const char* string)
+{
+ stream.write(string, strlen(string));
+}
+
+static void _escapeDependencyString(const char* string, StringBuilder& outBuilder)
+{
+ // make has unusual escaping rules, but we only care about characters that are acceptable in a
+ // path
+ for (const char* p = string; *p; ++p)
+ {
+ char c = *p;
+ switch (c)
+ {
+ case ' ':
+ case ':':
+ case '#':
+ case '[':
+ case ']':
+ case '\\':
+ outBuilder.appendChar('\\');
+ break;
+
+ case '$':
+ outBuilder.appendChar('$');
+ break;
+ }
+
+ outBuilder.appendChar(c);
+ }
+}
+
+// Writes a line to the file stream, formatted like this:
+// <output-file>: <dependency-file> <dependency-file...>
+static void _writeDependencyStatement(
+ Stream& stream,
+ EndToEndCompileRequest* compileRequest,
+ const String& outputPath)
+{
+ if (outputPath.getLength() == 0)
+ return;
+
+ StringBuilder builder;
+ _escapeDependencyString(outputPath.begin(), builder);
+ _writeString(stream, builder.begin());
+ _writeString(stream, ": ");
+
+ int dependencyCount = compileRequest->getDependencyFileCount();
+ for (int dependencyIndex = 0; dependencyIndex < dependencyCount; ++dependencyIndex)
+ {
+ builder.clear();
+ _escapeDependencyString(compileRequest->getDependencyFilePath(dependencyIndex), builder);
+ _writeString(stream, builder.begin());
+ _writeString(stream, (dependencyIndex + 1 < dependencyCount) ? " " : "\n");
+ }
+}
+
+// Writes a file with dependency info, with one line in the output file per compile product.
+SlangResult writeDependencyFile(EndToEndCompileRequest* compileRequest)
+{
+ if (compileRequest->m_dependencyOutputPath.getLength() == 0)
+ return SLANG_OK;
+
+ FileStream stream;
+ SLANG_RETURN_ON_FAIL(stream.init(
+ compileRequest->m_dependencyOutputPath,
+ FileMode::Create,
+ FileAccess::Write,
+ FileShare::ReadWrite));
+
+ auto linkage = compileRequest->getLinkage();
+ auto program = compileRequest->getSpecializedGlobalAndEntryPointsComponentType();
+
+ // Iterate over all the targets and their outputs
+ for (const auto& targetReq : linkage->targets)
+ {
+ if (compileRequest->getTargetOptionSet(targetReq).getBoolOption(
+ CompilerOptionName::GenerateWholeProgram))
+ {
+ RefPtr<EndToEndCompileRequest::TargetInfo> targetInfo;
+ if (compileRequest->m_targetInfos.tryGetValue(targetReq, targetInfo))
+ {
+ _writeDependencyStatement(
+ stream,
+ compileRequest,
+ targetInfo->wholeTargetOutputPath);
+ }
+ }
+ else
+ {
+ Index entryPointCount = program->getEntryPointCount();
+ for (Index entryPointIndex = 0; entryPointIndex < entryPointCount; ++entryPointIndex)
+ {
+ RefPtr<EndToEndCompileRequest::TargetInfo> targetInfo;
+ if (compileRequest->m_targetInfos.tryGetValue(targetReq, targetInfo))
+ {
+ String outputPath;
+ if (targetInfo->entryPointOutputPaths.tryGetValue(entryPointIndex, outputPath))
+ {
+ _writeDependencyStatement(stream, compileRequest, outputPath);
+ }
+ }
+ }
+ }
+ }
+
+ // When the output is a binary module, linkage->targets can be empty. So
+ // we need to do their dependencies separately.
+ if (compileRequest->m_containerFormat == ContainerFormat::SlangModule)
+ {
+ _writeDependencyStatement(stream, compileRequest, compileRequest->m_containerOutputPath);
+ }
+
+ return SLANG_OK;
+}
+
+} // namespace Slang