summaryrefslogtreecommitdiff
path: root/source/slang/slang-compiler.cpp
diff options
context:
space:
mode:
authorAlexey Panteleev <alpanteleev@nvidia.com>2022-03-16 08:28:01 -0700
committerGitHub <noreply@github.com>2022-03-16 08:28:01 -0700
commit42ca6758046e11451b0788092f9c95fc7f788da6 (patch)
treea377c6b9c7081230ac0385ad14b778b7f700a077 /source/slang/slang-compiler.cpp
parent8533dd2344d8be040a992a86f23e7cf696d59c4a (diff)
Add -depfile option to save dependency info (#2161)
Diffstat (limited to 'source/slang/slang-compiler.cpp')
-rw-r--r--source/slang/slang-compiler.cpp99
1 files changed, 99 insertions, 0 deletions
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp
index 65a18104e..39d558c01 100644
--- a/source/slang/slang-compiler.cpp
+++ b/source/slang/slang-compiler.cpp
@@ -2177,6 +2177,103 @@ namespace Slang
return SLANG_OK;
}
+ 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.
+ static 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 (targetReq->isWholeProgramRequest())
+ {
+ 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);
+ }
+ }
+ }
+ }
+ }
+
+ return SLANG_OK;
+ }
+
static void _generateOutput(
BackEndCompileRequest* compileRequest,
@@ -2265,6 +2362,8 @@ namespace Slang
compileRequest->maybeCreateContainer();
compileRequest->maybeWriteContainer(compileRequest->m_containerOutputPath);
+
+ _writeDependencyFile(compileRequest);
}
}