summaryrefslogtreecommitdiffstats
path: root/source
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
parent8533dd2344d8be040a992a86f23e7cf696d59c4a (diff)
Add -depfile option to save dependency info (#2161)
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-compiler.cpp99
-rwxr-xr-xsource/slang/slang-compiler.h2
-rw-r--r--source/slang/slang-diagnostic-defs.h1
-rw-r--r--source/slang/slang-options.cpp17
4 files changed, 119 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);
}
}
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index d73a03b42..5f14fb4f6 100755
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -2369,6 +2369,8 @@ namespace Slang
String wholeTargetOutputPath;
};
Dictionary<TargetRequest*, RefPtr<TargetInfo>> m_targetInfos;
+
+ String m_dependencyOutputPath;
/// Writes the modules in a container to the stream
SlangResult writeContainerToStream(Stream* stream);
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index f26410633..b2575b255 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -108,6 +108,7 @@ DIAGNOSTIC( 70, Error, cannotMatchOutputFileToEntryPoint, "the output path '$
DIAGNOSTIC( 80, Error, duplicateOutputPathsForEntryPointAndTarget, "multiple output paths have been specified entry point '$0' on target '$1'")
DIAGNOSTIC( 81, Error, duplicateOutputPathsForTarget, "multiple output paths have been specified for target '$0'")
+DIAGNOSTIC( 82, Error, duplicateDependencyOutputPaths, "the -dep argument can only be specified once")
DIAGNOSTIC( 82, Error, unableToWriteReproFile, "unable to write repro file '%0'")
DIAGNOSTIC( 83, Error, unableToWriteModuleContainer, "unable to write module container '%0'")
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index 5d8d52a09..b40dedc99 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -501,6 +501,7 @@ struct OptionsParser
"General options:\n"
"\n"
" -D<name>[=<value>], -D <name>[=<value>]: Insert a preprocessor macro.\n"
+ " -depfile <path>: Save the source file dependency list in a file.\n"
" -entry <name>: Specify the name of an entry-point function.\n"
" Multiple -entry options may be used in a single invocation.\n"
" If no -entry options are given, compiler will use [shader(...)]\n"
@@ -1259,6 +1260,22 @@ struct OptionsParser
addOutputPath(outputPath.value.getBuffer());
}
+ // A -depfile option is used to specify the file name where the dependency lists will be written
+ else if (argValue == "-depfile")
+ {
+ CommandLineArg dependencyPath;
+ SLANG_RETURN_ON_FAIL(reader.expectArg(dependencyPath));
+
+ if (requestImpl->m_dependencyOutputPath.getLength() == 0)
+ {
+ requestImpl->m_dependencyOutputPath = dependencyPath.value;
+ }
+ else
+ {
+ sink->diagnose(dependencyPath.loc, Diagnostics::duplicateDependencyOutputPaths);
+ return SLANG_FAIL;
+ }
+ }
else if(argValue == "-matrix-layout-row-major")
{
defaultMatrixLayoutMode = kMatrixLayoutMode_RowMajor;