diff options
| author | Alexey Panteleev <alpanteleev@nvidia.com> | 2022-03-16 08:28:01 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-03-16 08:28:01 -0700 |
| commit | 42ca6758046e11451b0788092f9c95fc7f788da6 (patch) | |
| tree | a377c6b9c7081230ac0385ad14b778b7f700a077 /source | |
| parent | 8533dd2344d8be040a992a86f23e7cf696d59c4a (diff) | |
Add -depfile option to save dependency info (#2161)
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang-compiler.cpp | 99 | ||||
| -rwxr-xr-x | source/slang/slang-compiler.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-options.cpp | 17 |
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; |
