mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[ScanDependency] Respect working directory set inside invocation
Teach scanner to respect the working directory set in the invocation through scanner C API. Also add test infrastructure to testing scanner from C API. Break up DependencyScan lib into two so the swift-scan-test and remain small without understanding swift AST. rdar://127626011
This commit is contained in:
30
include/swift/DependencyScan/DependencyScanJSON.h
Normal file
30
include/swift/DependencyScan/DependencyScanJSON.h
Normal file
@@ -0,0 +1,30 @@
|
||||
//===-------------- DependencyScanImpl.h - Swift Compiler -----------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implementation details of the dependency scanning C API
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef SWIFT_DEPENDENCY_SCAN_JSON_H
|
||||
#define SWIFT_DEPENDENCY_SCAN_JSON_H
|
||||
|
||||
#include "swift-c/DependencyScan/DependencyScan.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace swift::dependencies {
|
||||
|
||||
void writePrescanJSON(llvm::raw_ostream &out,
|
||||
swiftscan_import_set_t importSet);
|
||||
void writeJSON(llvm::raw_ostream &out,
|
||||
swiftscan_dependency_graph_t fullDependencies);
|
||||
} // namespace swift::dependencies
|
||||
|
||||
#endif // SWIFT_DEPENDENCY_SCAN_JSON_H
|
||||
@@ -87,14 +87,15 @@ public:
|
||||
/// occurred, \c swiftscan_dependency_result_t otherwise.
|
||||
llvm::ErrorOr<swiftscan_dependency_graph_t>
|
||||
getDependencies(ArrayRef<const char *> Command,
|
||||
const llvm::StringSet<> &PlaceholderModules);
|
||||
const llvm::StringSet<> &PlaceholderModules,
|
||||
StringRef WorkingDirectory);
|
||||
|
||||
/// Collect the set of imports for the input module
|
||||
///
|
||||
/// \returns a \c StringError with the diagnostic output if errors
|
||||
/// occurred, \c swiftscan_prescan_result_t otherwise.
|
||||
llvm::ErrorOr<swiftscan_import_set_t>
|
||||
getImports(ArrayRef<const char *> Command);
|
||||
getImports(ArrayRef<const char *> Command, StringRef WorkingDirectory);
|
||||
|
||||
/// Collect the full module dependency graph for the input collection of
|
||||
/// module names (batch inputs) and output them to the
|
||||
@@ -104,7 +105,8 @@ public:
|
||||
std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t>>
|
||||
getDependencies(ArrayRef<const char *> Command,
|
||||
const std::vector<BatchScanInput> &BatchInput,
|
||||
const llvm::StringSet<> &PlaceholderModules);
|
||||
const llvm::StringSet<> &PlaceholderModules,
|
||||
StringRef WorkingDirectory);
|
||||
|
||||
/// Writes the current `SharedCache` instance to a specified FileSystem path.
|
||||
void serializeCache(llvm::StringRef path);
|
||||
@@ -121,13 +123,15 @@ public:
|
||||
/// Using the specified invocation command, instantiate a CompilerInstance
|
||||
/// that will be used for this scan.
|
||||
llvm::ErrorOr<ScanQueryInstance>
|
||||
initCompilerInstanceForScan(ArrayRef<const char *> Command);
|
||||
initCompilerInstanceForScan(ArrayRef<const char *> Command,
|
||||
StringRef WorkingDirectory);
|
||||
|
||||
private:
|
||||
/// Using the specified invocation command, initialize the scanner instance
|
||||
/// for this scan. Returns the `CompilerInstance` that will be used.
|
||||
llvm::ErrorOr<ScanQueryInstance>
|
||||
initScannerForAction(ArrayRef<const char *> Command);
|
||||
initScannerForAction(ArrayRef<const char *> Command,
|
||||
StringRef WorkingDirectory);
|
||||
|
||||
/// Shared cache of module dependencies, re-used by individual full-scan queries
|
||||
/// during the lifetime of this Tool.
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
|
||||
add_swift_host_library(swiftDependencyScanImpl STATIC
|
||||
DependencyScanJSON.cpp
|
||||
StringUtils.cpp)
|
||||
|
||||
add_swift_host_library(swiftDependencyScan STATIC
|
||||
DependencyScanningTool.cpp
|
||||
ModuleDependencyCacheSerialization.cpp
|
||||
ModuleDependencyScanner.cpp
|
||||
ScanDependencies.cpp
|
||||
StringUtils.cpp)
|
||||
ModuleDependencyScanner.cpp
|
||||
ScanDependencies.cpp)
|
||||
|
||||
target_link_libraries(swiftDependencyScan INTERFACE
|
||||
clangBasic)
|
||||
|
||||
target_link_libraries(swiftDependencyScan PRIVATE
|
||||
swiftClangImporter
|
||||
swiftAST
|
||||
swiftSerialization)
|
||||
swiftClangImporter
|
||||
swiftAST
|
||||
swiftSerialization)
|
||||
|
||||
target_link_libraries(swiftDependencyScan PUBLIC
|
||||
swiftDependencyScanImpl)
|
||||
|
||||
555
lib/DependencyScan/DependencyScanJSON.cpp
Normal file
555
lib/DependencyScan/DependencyScanJSON.cpp
Normal file
@@ -0,0 +1,555 @@
|
||||
//===--- DependencyScanJSON.cpp -- JSON output for dependencies -----------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "swift/DependencyScan/DependencyScanJSON.h"
|
||||
#include "swift/Basic/Defer.h"
|
||||
#include "swift/DependencyScan/DependencyScanImpl.h"
|
||||
#include "swift/DependencyScan/StringUtils.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
using namespace swift;
|
||||
using namespace swift::dependencies;
|
||||
using namespace swift::c_string_utils;
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
std::string quote(StringRef unquoted) {
|
||||
llvm::SmallString<128> buffer;
|
||||
llvm::raw_svector_ostream os(buffer);
|
||||
for (const auto ch : unquoted) {
|
||||
if (ch == '\\')
|
||||
os << '\\';
|
||||
if (ch == '"')
|
||||
os << '\\';
|
||||
os << ch;
|
||||
}
|
||||
return buffer.str().str();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/// Write a single JSON field.
|
||||
template <typename T>
|
||||
void writeJSONSingleField(llvm::raw_ostream &out, StringRef fieldName,
|
||||
const T &value, unsigned indentLevel,
|
||||
bool trailingComma, bool nested = false);
|
||||
|
||||
/// Write a string value as JSON.
|
||||
void writeJSONValue(llvm::raw_ostream &out, StringRef value,
|
||||
unsigned indentLevel) {
|
||||
out << "\"";
|
||||
out << quote(value);
|
||||
out << "\"";
|
||||
}
|
||||
|
||||
void writeJSONValue(llvm::raw_ostream &out, swiftscan_string_ref_t value,
|
||||
unsigned indentLevel) {
|
||||
out << "\"";
|
||||
out << quote(get_C_string(value));
|
||||
out << "\"";
|
||||
}
|
||||
|
||||
void writeJSONValue(llvm::raw_ostream &out, swiftscan_string_set_t *value_set,
|
||||
unsigned indentLevel) {
|
||||
out << "[\n";
|
||||
|
||||
for (size_t i = 0; i < value_set->count; ++i) {
|
||||
out.indent((indentLevel + 1) * 2);
|
||||
|
||||
writeJSONValue(out, value_set->strings[i], indentLevel + 1);
|
||||
|
||||
if (i != value_set->count - 1) {
|
||||
out << ",";
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
out.indent(indentLevel * 2);
|
||||
out << "]";
|
||||
}
|
||||
|
||||
void writeEncodedModuleIdJSONValue(llvm::raw_ostream &out,
|
||||
swiftscan_string_ref_t value,
|
||||
unsigned indentLevel) {
|
||||
out << "{\n";
|
||||
static const std::string textualPrefix("swiftTextual");
|
||||
static const std::string binaryPrefix("swiftBinary");
|
||||
static const std::string placeholderPrefix("swiftPlaceholder");
|
||||
static const std::string clangPrefix("clang");
|
||||
std::string valueStr = get_C_string(value);
|
||||
std::string moduleKind;
|
||||
std::string moduleName;
|
||||
if (!valueStr.compare(0, textualPrefix.size(), textualPrefix)) {
|
||||
moduleKind = "swift";
|
||||
moduleName = valueStr.substr(textualPrefix.size() + 1);
|
||||
} else if (!valueStr.compare(0, binaryPrefix.size(), binaryPrefix)) {
|
||||
// FIXME: rename to be consistent in the clients (swift-driver)
|
||||
moduleKind = "swiftPrebuiltExternal";
|
||||
moduleName = valueStr.substr(binaryPrefix.size() + 1);
|
||||
} else if (!valueStr.compare(0, placeholderPrefix.size(),
|
||||
placeholderPrefix)) {
|
||||
moduleKind = "swiftPlaceholder";
|
||||
moduleName = valueStr.substr(placeholderPrefix.size() + 1);
|
||||
} else {
|
||||
moduleKind = "clang";
|
||||
moduleName = valueStr.substr(clangPrefix.size() + 1);
|
||||
}
|
||||
writeJSONSingleField(out, moduleKind, moduleName, indentLevel + 1,
|
||||
/*trailingComma=*/false);
|
||||
out.indent(indentLevel * 2);
|
||||
out << "}";
|
||||
}
|
||||
|
||||
/// Write a boolean value as JSON.
|
||||
void writeJSONValue(llvm::raw_ostream &out, bool value, unsigned indentLevel) {
|
||||
out.write_escaped(value ? "true" : "false");
|
||||
}
|
||||
|
||||
/// Write a JSON array.
|
||||
template <typename T>
|
||||
void writeJSONValue(llvm::raw_ostream &out, ArrayRef<T> values,
|
||||
unsigned indentLevel) {
|
||||
out << "[\n";
|
||||
|
||||
for (const auto &value : values) {
|
||||
|
||||
out.indent((indentLevel + 1) * 2);
|
||||
|
||||
writeJSONValue(out, value, indentLevel + 1);
|
||||
|
||||
if (&value != &values.back()) {
|
||||
out << ",";
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
out.indent(indentLevel * 2);
|
||||
out << "]";
|
||||
}
|
||||
|
||||
/// Write a JSON array.
|
||||
template <typename T>
|
||||
void writeJSONValue(llvm::raw_ostream &out, const std::vector<T> &values,
|
||||
unsigned indentLevel) {
|
||||
writeJSONValue(out, llvm::ArrayRef(values), indentLevel);
|
||||
}
|
||||
|
||||
/// Write a single JSON field.
|
||||
template <typename T>
|
||||
void writeJSONSingleField(llvm::raw_ostream &out, StringRef fieldName,
|
||||
const T &value, unsigned indentLevel,
|
||||
bool trailingComma, bool nested) {
|
||||
out.indent(indentLevel * 2);
|
||||
writeJSONValue(out, fieldName, indentLevel);
|
||||
out << ": ";
|
||||
auto updatedIndentLevel = indentLevel;
|
||||
|
||||
if (nested) {
|
||||
// This is a hack to "fix" a format for a value that should be a nested
|
||||
// set of strings. Currently only capturedPCMArgs (clang) is expected to
|
||||
// in the nested format, which supposedly only contains one set of strings.
|
||||
// Adjust the indentation to account for the nested brackets.
|
||||
updatedIndentLevel += 1;
|
||||
out << "[\n";
|
||||
out.indent(updatedIndentLevel * 2);
|
||||
}
|
||||
|
||||
writeJSONValue(out, value, updatedIndentLevel);
|
||||
|
||||
if (nested) {
|
||||
// If nested, add an extra closing brack with a correct indentation.
|
||||
out << "\n";
|
||||
out.indent(indentLevel * 2);
|
||||
out << "]";
|
||||
}
|
||||
|
||||
if (trailingComma)
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
static void writeDependencies(llvm::raw_ostream &out,
|
||||
const swiftscan_string_set_t *dependencies,
|
||||
std::string dependenciesKind,
|
||||
unsigned indentLevel, bool trailingComma) {
|
||||
out.indent(indentLevel * 2);
|
||||
out << "\"" + dependenciesKind + "\": ";
|
||||
out << "[\n";
|
||||
|
||||
for (size_t i = 0; i < dependencies->count; ++i) {
|
||||
out.indent((indentLevel + 1) * 2);
|
||||
writeEncodedModuleIdJSONValue(out, dependencies->strings[i],
|
||||
indentLevel + 1);
|
||||
if (i != dependencies->count - 1) {
|
||||
out << ",";
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
out.indent(indentLevel * 2);
|
||||
out << "]";
|
||||
|
||||
if (trailingComma)
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
static const swiftscan_swift_textual_details_t *
|
||||
getAsTextualDependencyModule(swiftscan_module_details_t details) {
|
||||
if (details->kind == SWIFTSCAN_DEPENDENCY_INFO_SWIFT_TEXTUAL)
|
||||
return &details->swift_textual_details;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const swiftscan_swift_placeholder_details_t *
|
||||
getAsPlaceholderDependencyModule(swiftscan_module_details_t details) {
|
||||
if (details->kind == SWIFTSCAN_DEPENDENCY_INFO_SWIFT_PLACEHOLDER)
|
||||
return &details->swift_placeholder_details;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const swiftscan_swift_binary_details_t *
|
||||
getAsBinaryDependencyModule(swiftscan_module_details_t details) {
|
||||
if (details->kind == SWIFTSCAN_DEPENDENCY_INFO_SWIFT_BINARY)
|
||||
return &details->swift_binary_details;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const swiftscan_clang_details_t *
|
||||
getAsClangDependencyModule(swiftscan_module_details_t details) {
|
||||
if (details->kind == SWIFTSCAN_DEPENDENCY_INFO_CLANG)
|
||||
return &details->clang_details;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
namespace swift::dependencies {
|
||||
void writePrescanJSON(llvm::raw_ostream &out,
|
||||
swiftscan_import_set_t importSet) {
|
||||
// Write out a JSON containing all main module imports.
|
||||
out << "{\n";
|
||||
SWIFT_DEFER { out << "}\n"; };
|
||||
|
||||
writeJSONSingleField(out, "imports", importSet->imports, 0, false);
|
||||
}
|
||||
|
||||
void writeJSON(llvm::raw_ostream &out,
|
||||
swiftscan_dependency_graph_t fullDependencies) {
|
||||
// Write out a JSON description of all of the dependencies.
|
||||
out << "{\n";
|
||||
SWIFT_DEFER { out << "}\n"; };
|
||||
// Name of the main module.
|
||||
writeJSONSingleField(out, "mainModuleName",
|
||||
fullDependencies->main_module_name,
|
||||
/*indentLevel=*/1, /*trailingComma=*/true);
|
||||
// Write out all of the modules.
|
||||
out << " \"modules\": [\n";
|
||||
SWIFT_DEFER { out << " ]\n"; };
|
||||
const auto module_set = fullDependencies->dependencies;
|
||||
for (size_t mi = 0; mi < module_set->count; ++mi) {
|
||||
const auto &moduleInfo = *module_set->modules[mi];
|
||||
auto &directDependencies = moduleInfo.direct_dependencies;
|
||||
// The module we are describing.
|
||||
out.indent(2 * 2);
|
||||
writeEncodedModuleIdJSONValue(out, moduleInfo.module_name, 2);
|
||||
out << ",\n";
|
||||
out.indent(2 * 2);
|
||||
out << "{\n";
|
||||
auto swiftPlaceholderDeps =
|
||||
getAsPlaceholderDependencyModule(moduleInfo.details);
|
||||
auto swiftTextualDeps = getAsTextualDependencyModule(moduleInfo.details);
|
||||
auto swiftBinaryDeps = getAsBinaryDependencyModule(moduleInfo.details);
|
||||
auto clangDeps = getAsClangDependencyModule(moduleInfo.details);
|
||||
|
||||
// Module path.
|
||||
const char *modulePathSuffix = clangDeps ? ".pcm" : ".swiftmodule";
|
||||
|
||||
std::string modulePath;
|
||||
std::string moduleKindAndName =
|
||||
std::string(get_C_string(moduleInfo.module_name));
|
||||
std::string moduleName =
|
||||
moduleKindAndName.substr(moduleKindAndName.find(":") + 1);
|
||||
if (swiftPlaceholderDeps)
|
||||
modulePath = get_C_string(swiftPlaceholderDeps->compiled_module_path);
|
||||
else if (swiftBinaryDeps)
|
||||
modulePath = get_C_string(swiftBinaryDeps->compiled_module_path);
|
||||
else if (clangDeps || swiftTextualDeps)
|
||||
modulePath = get_C_string(moduleInfo.module_path);
|
||||
else
|
||||
modulePath = moduleName + modulePathSuffix;
|
||||
|
||||
writeJSONSingleField(out, "modulePath", modulePath, /*indentLevel=*/3,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Source files.
|
||||
if (swiftTextualDeps || clangDeps) {
|
||||
writeJSONSingleField(out, "sourceFiles", moduleInfo.source_files, 3,
|
||||
/*trailingComma=*/true);
|
||||
}
|
||||
|
||||
// Direct dependencies.
|
||||
if (swiftTextualDeps || swiftBinaryDeps || clangDeps)
|
||||
writeDependencies(out, directDependencies,
|
||||
"directDependencies", 3,
|
||||
/*trailingComma=*/true);
|
||||
// Swift and Clang-specific details.
|
||||
out.indent(3 * 2);
|
||||
out << "\"details\": {\n";
|
||||
out.indent(4 * 2);
|
||||
if (swiftTextualDeps) {
|
||||
out << "\"swift\": {\n";
|
||||
/// Swift interface file, if there is one. The main module, for
|
||||
/// example, will not have an interface file.
|
||||
std::string moduleInterfacePath =
|
||||
swiftTextualDeps->module_interface_path.data
|
||||
? get_C_string(swiftTextualDeps->module_interface_path)
|
||||
: "";
|
||||
if (!moduleInterfacePath.empty()) {
|
||||
writeJSONSingleField(out, "moduleInterfacePath", moduleInterfacePath, 5,
|
||||
/*trailingComma=*/true);
|
||||
out.indent(5 * 2);
|
||||
out << "\"compiledModuleCandidates\": [\n";
|
||||
for (int i = 0,
|
||||
count = swiftTextualDeps->compiled_module_candidates->count;
|
||||
i < count; ++i) {
|
||||
const auto &candidate = get_C_string(
|
||||
swiftTextualDeps->compiled_module_candidates->strings[i]);
|
||||
out.indent(6 * 2);
|
||||
out << "\"" << quote(candidate) << "\"";
|
||||
if (i != count - 1)
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
out.indent(5 * 2);
|
||||
out << "],\n";
|
||||
}
|
||||
out.indent(5 * 2);
|
||||
out << "\"commandLine\": [\n";
|
||||
for (int i = 0, count = swiftTextualDeps->command_line->count; i < count;
|
||||
++i) {
|
||||
const auto &arg =
|
||||
get_C_string(swiftTextualDeps->command_line->strings[i]);
|
||||
out.indent(6 * 2);
|
||||
out << "\"" << quote(arg) << "\"";
|
||||
if (i != count - 1)
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
out.indent(5 * 2);
|
||||
out << "],\n";
|
||||
writeJSONSingleField(out, "contextHash", swiftTextualDeps->context_hash,
|
||||
5,
|
||||
/*trailingComma=*/true);
|
||||
bool hasBridgingHeaderPath =
|
||||
swiftTextualDeps->bridging_header_path.data &&
|
||||
get_C_string(swiftTextualDeps->bridging_header_path)[0] != '\0';
|
||||
bool hasOverlayDependencies =
|
||||
swiftTextualDeps->swift_overlay_module_dependencies &&
|
||||
swiftTextualDeps->swift_overlay_module_dependencies->count > 0;
|
||||
bool commaAfterBridgingHeaderPath = hasOverlayDependencies;
|
||||
bool commaAfterExtraPcmArgs =
|
||||
hasBridgingHeaderPath || commaAfterBridgingHeaderPath;
|
||||
bool commaAfterFramework =
|
||||
swiftTextualDeps->extra_pcm_args->count != 0 || commaAfterExtraPcmArgs;
|
||||
|
||||
if (swiftTextualDeps->cas_fs_root_id.length != 0) {
|
||||
writeJSONSingleField(out, "casFSRootID",
|
||||
swiftTextualDeps->cas_fs_root_id, 5,
|
||||
/*trailingComma=*/true);
|
||||
}
|
||||
if (swiftTextualDeps->module_cache_key.length != 0) {
|
||||
writeJSONSingleField(out, "moduleCacheKey",
|
||||
swiftTextualDeps->module_cache_key, 5,
|
||||
/*trailingComma=*/true);
|
||||
}
|
||||
writeJSONSingleField(out, "isFramework", swiftTextualDeps->is_framework,
|
||||
5, commaAfterFramework);
|
||||
if (swiftTextualDeps->extra_pcm_args->count != 0) {
|
||||
out.indent(5 * 2);
|
||||
out << "\"extraPcmArgs\": [\n";
|
||||
for (int i = 0, count = swiftTextualDeps->extra_pcm_args->count;
|
||||
i < count; ++i) {
|
||||
const auto &arg =
|
||||
get_C_string(swiftTextualDeps->extra_pcm_args->strings[i]);
|
||||
out.indent(6 * 2);
|
||||
out << "\"" << quote(arg) << "\"";
|
||||
if (i != count - 1)
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
out.indent(5 * 2);
|
||||
out << (commaAfterExtraPcmArgs ? "],\n" : "]\n");
|
||||
}
|
||||
/// Bridging header and its source file dependencies, if any.
|
||||
if (hasBridgingHeaderPath) {
|
||||
out.indent(5 * 2);
|
||||
out << "\"bridgingHeader\": {\n";
|
||||
writeJSONSingleField(out, "path",
|
||||
swiftTextualDeps->bridging_header_path, 6,
|
||||
/*trailingComma=*/true);
|
||||
writeJSONSingleField(out, "sourceFiles",
|
||||
swiftTextualDeps->bridging_source_files, 6,
|
||||
/*trailingComma=*/true);
|
||||
if (swiftTextualDeps->bridging_header_include_tree.length != 0) {
|
||||
writeJSONSingleField(out, "includeTree",
|
||||
swiftTextualDeps->bridging_header_include_tree,
|
||||
6, /*trailingComma=*/true);
|
||||
}
|
||||
writeJSONSingleField(out, "moduleDependencies",
|
||||
swiftTextualDeps->bridging_module_dependencies, 6,
|
||||
/*trailingComma=*/true);
|
||||
out.indent(6 * 2);
|
||||
out << "\"commandLine\": [\n";
|
||||
for (int i = 0,
|
||||
count = swiftTextualDeps->bridging_pch_command_line->count;
|
||||
i < count; ++i) {
|
||||
const auto &arg = get_C_string(
|
||||
swiftTextualDeps->bridging_pch_command_line->strings[i]);
|
||||
out.indent(7 * 2);
|
||||
out << "\"" << quote(arg) << "\"";
|
||||
if (i != count - 1)
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
out.indent(6 * 2);
|
||||
out << "]\n";
|
||||
out.indent(5 * 2);
|
||||
out << (commaAfterBridgingHeaderPath ? "},\n" : "}\n");
|
||||
}
|
||||
if (hasOverlayDependencies) {
|
||||
writeDependencies(out, swiftTextualDeps->swift_overlay_module_dependencies,
|
||||
"swiftOverlayDependencies", 5,
|
||||
/*trailingComma=*/false);
|
||||
}
|
||||
} else if (swiftPlaceholderDeps) {
|
||||
out << "\"swiftPlaceholder\": {\n";
|
||||
|
||||
// Module doc file
|
||||
if (swiftPlaceholderDeps->module_doc_path.data &&
|
||||
get_C_string(swiftPlaceholderDeps->module_doc_path)[0] != '\0')
|
||||
writeJSONSingleField(out, "moduleDocPath",
|
||||
swiftPlaceholderDeps->module_doc_path,
|
||||
/*indentLevel=*/5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Module Source Info file
|
||||
if (swiftPlaceholderDeps->module_source_info_path.data &&
|
||||
get_C_string(swiftPlaceholderDeps->module_source_info_path)[0] !=
|
||||
'\0')
|
||||
writeJSONSingleField(out, "moduleSourceInfoPath",
|
||||
swiftPlaceholderDeps->module_source_info_path,
|
||||
/*indentLevel=*/5,
|
||||
/*trailingComma=*/false);
|
||||
} else if (swiftBinaryDeps) {
|
||||
bool hasOverlayDependencies =
|
||||
swiftBinaryDeps->swift_overlay_module_dependencies &&
|
||||
swiftBinaryDeps->swift_overlay_module_dependencies->count > 0;
|
||||
|
||||
out << "\"swiftPrebuiltExternal\": {\n";
|
||||
assert(swiftBinaryDeps->compiled_module_path.data &&
|
||||
get_C_string(swiftBinaryDeps->compiled_module_path)[0] != '\0' &&
|
||||
"Expected .swiftmodule for a Binary Swift Module Dependency.");
|
||||
|
||||
writeJSONSingleField(out, "compiledModulePath",
|
||||
swiftBinaryDeps->compiled_module_path,
|
||||
/*indentLevel=*/5,
|
||||
/*trailingComma=*/true);
|
||||
// Module doc file
|
||||
if (swiftBinaryDeps->module_doc_path.data &&
|
||||
get_C_string(swiftBinaryDeps->module_doc_path)[0] != '\0')
|
||||
writeJSONSingleField(out, "moduleDocPath",
|
||||
swiftBinaryDeps->module_doc_path,
|
||||
/*indentLevel=*/5,
|
||||
/*trailingComma=*/true);
|
||||
// Module Source Info file
|
||||
if (swiftBinaryDeps->module_source_info_path.data &&
|
||||
get_C_string(swiftBinaryDeps->module_source_info_path)[0] != '\0')
|
||||
writeJSONSingleField(out, "moduleSourceInfoPath",
|
||||
swiftBinaryDeps->module_source_info_path,
|
||||
/*indentLevel=*/5,
|
||||
/*trailingComma=*/true);
|
||||
if (swiftBinaryDeps->module_cache_key.length != 0) {
|
||||
writeJSONSingleField(out, "moduleCacheKey",
|
||||
swiftBinaryDeps->module_cache_key, 5,
|
||||
/*trailingComma=*/true);
|
||||
}
|
||||
|
||||
// Module Header Dependencies
|
||||
if (swiftBinaryDeps->header_dependency.length != 0)
|
||||
writeJSONSingleField(out, "headerDependency",
|
||||
swiftBinaryDeps->header_dependency, 5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Module Header Module Dependencies
|
||||
if (swiftBinaryDeps->header_dependencies_module_dependnecies->count != 0)
|
||||
writeJSONSingleField(out, "headerModuleDependencies",
|
||||
swiftBinaryDeps->header_dependencies_module_dependnecies, 5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Module Header Source Files
|
||||
if (swiftBinaryDeps->header_dependencies_source_files->count != 0)
|
||||
writeJSONSingleField(out, "headerDependenciesSourceFiles",
|
||||
swiftBinaryDeps->header_dependencies_source_files, 5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
if (hasOverlayDependencies) {
|
||||
writeDependencies(out, swiftBinaryDeps->swift_overlay_module_dependencies,
|
||||
"swiftOverlayDependencies", 5,
|
||||
/*trailingComma=*/true);
|
||||
}
|
||||
|
||||
writeJSONSingleField(out, "isFramework", swiftBinaryDeps->is_framework,
|
||||
5, /*trailingComma=*/false);
|
||||
} else {
|
||||
out << "\"clang\": {\n";
|
||||
|
||||
// Module map file.
|
||||
writeJSONSingleField(out, "moduleMapPath", clangDeps->module_map_path, 5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Context hash.
|
||||
writeJSONSingleField(out, "contextHash", clangDeps->context_hash, 5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Command line.
|
||||
writeJSONSingleField(out, "commandLine", clangDeps->command_line, 5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
if (clangDeps->cas_fs_root_id.length != 0)
|
||||
writeJSONSingleField(out, "casFSRootID", clangDeps->cas_fs_root_id, 5,
|
||||
/*trailingComma=*/true);
|
||||
if (clangDeps->clang_include_tree.length != 0)
|
||||
writeJSONSingleField(out, "clangIncludeTree",
|
||||
clangDeps->clang_include_tree, 5,
|
||||
/*trailingComma=*/true);
|
||||
if (clangDeps->module_cache_key.length != 0)
|
||||
writeJSONSingleField(out, "moduleCacheKey", clangDeps->module_cache_key,
|
||||
5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Captured PCM arguments.
|
||||
writeJSONSingleField(out, "capturedPCMArgs", clangDeps->captured_pcm_args, 5,
|
||||
/*trailingComma=*/false, /*nested=*/true);
|
||||
|
||||
}
|
||||
|
||||
out.indent(4 * 2);
|
||||
out << "}\n";
|
||||
out.indent(3 * 2);
|
||||
out << "}\n";
|
||||
out.indent(2 * 2);
|
||||
out << "}";
|
||||
|
||||
if (mi != module_set->count - 1)
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
} // namespace swift::dependencies
|
||||
@@ -148,10 +148,10 @@ DependencyScanningTool::DependencyScanningTool()
|
||||
|
||||
llvm::ErrorOr<swiftscan_dependency_graph_t>
|
||||
DependencyScanningTool::getDependencies(
|
||||
ArrayRef<const char *> Command,
|
||||
const llvm::StringSet<> &PlaceholderModules) {
|
||||
ArrayRef<const char *> Command, const llvm::StringSet<> &PlaceholderModules,
|
||||
StringRef WorkingDirectory) {
|
||||
// The primary instance used to scan the query Swift source-code
|
||||
auto QueryContextOrErr = initScannerForAction(Command);
|
||||
auto QueryContextOrErr = initScannerForAction(Command, WorkingDirectory);
|
||||
if (std::error_code EC = QueryContextOrErr.getError())
|
||||
return EC;
|
||||
auto QueryContext = std::move(*QueryContextOrErr);
|
||||
@@ -173,9 +173,10 @@ DependencyScanningTool::getDependencies(
|
||||
}
|
||||
|
||||
llvm::ErrorOr<swiftscan_import_set_t>
|
||||
DependencyScanningTool::getImports(ArrayRef<const char *> Command) {
|
||||
DependencyScanningTool::getImports(ArrayRef<const char *> Command,
|
||||
StringRef WorkingDirectory) {
|
||||
// The primary instance used to scan the query Swift source-code
|
||||
auto QueryContextOrErr = initScannerForAction(Command);
|
||||
auto QueryContextOrErr = initScannerForAction(Command, WorkingDirectory);
|
||||
if (std::error_code EC = QueryContextOrErr.getError())
|
||||
return EC;
|
||||
auto QueryContext = std::move(*QueryContextOrErr);
|
||||
@@ -199,9 +200,9 @@ std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t>>
|
||||
DependencyScanningTool::getDependencies(
|
||||
ArrayRef<const char *> Command,
|
||||
const std::vector<BatchScanInput> &BatchInput,
|
||||
const llvm::StringSet<> &PlaceholderModules) {
|
||||
const llvm::StringSet<> &PlaceholderModules, StringRef WorkingDirectory) {
|
||||
// The primary instance used to scan Swift modules
|
||||
auto QueryContextOrErr = initScannerForAction(Command);
|
||||
auto QueryContextOrErr = initScannerForAction(Command, WorkingDirectory);
|
||||
if (std::error_code EC = QueryContextOrErr.getError())
|
||||
return std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t>>(
|
||||
BatchInput.size(), std::make_error_code(std::errc::invalid_argument));
|
||||
@@ -264,17 +265,17 @@ void DependencyScanningTool::resetDiagnostics() {
|
||||
|
||||
llvm::ErrorOr<ScanQueryInstance>
|
||||
DependencyScanningTool::initScannerForAction(
|
||||
ArrayRef<const char *> Command) {
|
||||
ArrayRef<const char *> Command, StringRef WorkingDirectory) {
|
||||
// The remainder of this method operates on shared state in the
|
||||
// scanning service and global LLVM state with:
|
||||
// llvm::cl::ResetAllOptionOccurrences
|
||||
llvm::sys::SmartScopedLock<true> Lock(DependencyScanningToolStateLock);
|
||||
return initCompilerInstanceForScan(Command);
|
||||
return initCompilerInstanceForScan(Command, WorkingDirectory);
|
||||
}
|
||||
|
||||
llvm::ErrorOr<ScanQueryInstance>
|
||||
DependencyScanningTool::initCompilerInstanceForScan(
|
||||
ArrayRef<const char *> CommandArgs) {
|
||||
ArrayRef<const char *> CommandArgs, StringRef WorkingDir) {
|
||||
// State unique to an individual scan
|
||||
auto Instance = std::make_unique<CompilerInstance>();
|
||||
auto ScanDiagnosticConsumer = std::make_unique<DependencyScanDiagnosticCollector>();
|
||||
@@ -291,8 +292,9 @@ DependencyScanningTool::initCompilerInstanceForScan(
|
||||
}
|
||||
|
||||
CompilerInvocation Invocation;
|
||||
SmallString<128> WorkingDirectory;
|
||||
llvm::sys::fs::current_path(WorkingDirectory);
|
||||
SmallString<128> WorkingDirectory(WorkingDir);
|
||||
if (WorkingDirectory.empty())
|
||||
llvm::sys::fs::current_path(WorkingDirectory);
|
||||
|
||||
// We must reset option occurrences because we are handling an unrelated
|
||||
// command-line to those possibly parsed before using the same tool.
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "swift/Basic/STLExtras.h"
|
||||
#include "swift/ClangImporter/ClangImporter.h"
|
||||
#include "swift/DependencyScan/DependencyScanImpl.h"
|
||||
#include "swift/DependencyScan/DependencyScanJSON.h"
|
||||
#include "swift/DependencyScan/DependencyScanningTool.h"
|
||||
#include "swift/DependencyScan/ModuleDependencyScanner.h"
|
||||
#include "swift/DependencyScan/ScanDependencies.h"
|
||||
@@ -531,541 +532,10 @@ pruneUnusedVFSOverlays(ModuleDependencyID moduleID,
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::string quote(StringRef unquoted) {
|
||||
llvm::SmallString<128> buffer;
|
||||
llvm::raw_svector_ostream os(buffer);
|
||||
for (const auto ch : unquoted) {
|
||||
if (ch == '\\')
|
||||
os << '\\';
|
||||
if (ch == '"')
|
||||
os << '\\';
|
||||
os << ch;
|
||||
}
|
||||
return buffer.str().str();
|
||||
}
|
||||
}
|
||||
|
||||
/// Write a single JSON field.
|
||||
template <typename T>
|
||||
void writeJSONSingleField(llvm::raw_ostream &out, StringRef fieldName,
|
||||
const T &value, unsigned indentLevel,
|
||||
bool trailingComma, bool nested = false);
|
||||
|
||||
/// Write a string value as JSON.
|
||||
void writeJSONValue(llvm::raw_ostream &out, StringRef value,
|
||||
unsigned indentLevel) {
|
||||
out << "\"";
|
||||
out << quote(value);
|
||||
out << "\"";
|
||||
}
|
||||
|
||||
void writeJSONValue(llvm::raw_ostream &out, swiftscan_string_ref_t value,
|
||||
unsigned indentLevel) {
|
||||
out << "\"";
|
||||
out << quote(get_C_string(value));
|
||||
out << "\"";
|
||||
}
|
||||
|
||||
void writeJSONValue(llvm::raw_ostream &out, swiftscan_string_set_t *value_set,
|
||||
unsigned indentLevel) {
|
||||
out << "[\n";
|
||||
|
||||
for (size_t i = 0; i < value_set->count; ++i) {
|
||||
out.indent((indentLevel + 1) * 2);
|
||||
|
||||
writeJSONValue(out, value_set->strings[i], indentLevel + 1);
|
||||
|
||||
if (i != value_set->count - 1) {
|
||||
out << ",";
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
out.indent(indentLevel * 2);
|
||||
out << "]";
|
||||
}
|
||||
|
||||
void writeEncodedModuleIdJSONValue(llvm::raw_ostream &out,
|
||||
swiftscan_string_ref_t value,
|
||||
unsigned indentLevel) {
|
||||
out << "{\n";
|
||||
static const std::string textualPrefix("swiftTextual");
|
||||
static const std::string binaryPrefix("swiftBinary");
|
||||
static const std::string placeholderPrefix("swiftPlaceholder");
|
||||
static const std::string clangPrefix("clang");
|
||||
std::string valueStr = get_C_string(value);
|
||||
std::string moduleKind;
|
||||
std::string moduleName;
|
||||
if (!valueStr.compare(0, textualPrefix.size(), textualPrefix)) {
|
||||
moduleKind = "swift";
|
||||
moduleName = valueStr.substr(textualPrefix.size() + 1);
|
||||
} else if (!valueStr.compare(0, binaryPrefix.size(), binaryPrefix)) {
|
||||
// FIXME: rename to be consistent in the clients (swift-driver)
|
||||
moduleKind = "swiftPrebuiltExternal";
|
||||
moduleName = valueStr.substr(binaryPrefix.size() + 1);
|
||||
} else if (!valueStr.compare(0, placeholderPrefix.size(),
|
||||
placeholderPrefix)) {
|
||||
moduleKind = "swiftPlaceholder";
|
||||
moduleName = valueStr.substr(placeholderPrefix.size() + 1);
|
||||
} else {
|
||||
moduleKind = "clang";
|
||||
moduleName = valueStr.substr(clangPrefix.size() + 1);
|
||||
}
|
||||
writeJSONSingleField(out, moduleKind, moduleName, indentLevel + 1,
|
||||
/*trailingComma=*/false);
|
||||
out.indent(indentLevel * 2);
|
||||
out << "}";
|
||||
}
|
||||
|
||||
/// Write a boolean value as JSON.
|
||||
void writeJSONValue(llvm::raw_ostream &out, bool value, unsigned indentLevel) {
|
||||
out.write_escaped(value ? "true" : "false");
|
||||
}
|
||||
|
||||
/// Write a JSON array.
|
||||
template <typename T>
|
||||
void writeJSONValue(llvm::raw_ostream &out, ArrayRef<T> values,
|
||||
unsigned indentLevel) {
|
||||
out << "[\n";
|
||||
|
||||
for (const auto &value : values) {
|
||||
|
||||
out.indent((indentLevel + 1) * 2);
|
||||
|
||||
writeJSONValue(out, value, indentLevel + 1);
|
||||
|
||||
if (&value != &values.back()) {
|
||||
out << ",";
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
out.indent(indentLevel * 2);
|
||||
out << "]";
|
||||
}
|
||||
|
||||
/// Write a JSON array.
|
||||
template <typename T>
|
||||
void writeJSONValue(llvm::raw_ostream &out, const std::vector<T> &values,
|
||||
unsigned indentLevel) {
|
||||
writeJSONValue(out, llvm::ArrayRef(values), indentLevel);
|
||||
}
|
||||
|
||||
/// Write a single JSON field.
|
||||
template <typename T>
|
||||
void writeJSONSingleField(llvm::raw_ostream &out, StringRef fieldName,
|
||||
const T &value, unsigned indentLevel,
|
||||
bool trailingComma, bool nested) {
|
||||
out.indent(indentLevel * 2);
|
||||
writeJSONValue(out, fieldName, indentLevel);
|
||||
out << ": ";
|
||||
auto updatedIndentLevel = indentLevel;
|
||||
|
||||
if (nested) {
|
||||
// This is a hack to "fix" a format for a value that should be a nested
|
||||
// set of strings. Currently only capturedPCMArgs (clang) is expected to
|
||||
// in the nested format, which supposedly only contains one set of strings.
|
||||
// Adjust the indentation to account for the nested brackets.
|
||||
updatedIndentLevel += 1;
|
||||
out << "[\n";
|
||||
out.indent(updatedIndentLevel * 2);
|
||||
}
|
||||
|
||||
writeJSONValue(out, value, updatedIndentLevel);
|
||||
|
||||
if (nested) {
|
||||
// If nested, add an extra closing brack with a correct indentation.
|
||||
out << "\n";
|
||||
out.indent(indentLevel * 2);
|
||||
out << "]";
|
||||
}
|
||||
|
||||
if (trailingComma)
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
void writeDependencies(llvm::raw_ostream &out,
|
||||
const swiftscan_string_set_t *dependencies,
|
||||
std::string dependenciesKind,
|
||||
unsigned indentLevel, bool trailingComma) {
|
||||
out.indent(indentLevel * 2);
|
||||
out << "\"" + dependenciesKind + "\": ";
|
||||
out << "[\n";
|
||||
|
||||
for (size_t i = 0; i < dependencies->count; ++i) {
|
||||
out.indent((indentLevel + 1) * 2);
|
||||
writeEncodedModuleIdJSONValue(out, dependencies->strings[i],
|
||||
indentLevel + 1);
|
||||
if (i != dependencies->count - 1) {
|
||||
out << ",";
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
out.indent(indentLevel * 2);
|
||||
out << "]";
|
||||
|
||||
if (trailingComma)
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
static const swiftscan_swift_textual_details_t *
|
||||
getAsTextualDependencyModule(swiftscan_module_details_t details) {
|
||||
if (details->kind == SWIFTSCAN_DEPENDENCY_INFO_SWIFT_TEXTUAL)
|
||||
return &details->swift_textual_details;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const swiftscan_swift_placeholder_details_t *
|
||||
getAsPlaceholderDependencyModule(swiftscan_module_details_t details) {
|
||||
if (details->kind == SWIFTSCAN_DEPENDENCY_INFO_SWIFT_PLACEHOLDER)
|
||||
return &details->swift_placeholder_details;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const swiftscan_swift_binary_details_t *
|
||||
getAsBinaryDependencyModule(swiftscan_module_details_t details) {
|
||||
if (details->kind == SWIFTSCAN_DEPENDENCY_INFO_SWIFT_BINARY)
|
||||
return &details->swift_binary_details;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const swiftscan_clang_details_t *
|
||||
getAsClangDependencyModule(swiftscan_module_details_t details) {
|
||||
if (details->kind == SWIFTSCAN_DEPENDENCY_INFO_CLANG)
|
||||
return &details->clang_details;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void writePrescanJSON(llvm::raw_ostream &out,
|
||||
const swiftscan_import_set_t importSet) {
|
||||
// Write out a JSON containing all main module imports.
|
||||
out << "{\n";
|
||||
SWIFT_DEFER { out << "}\n"; };
|
||||
|
||||
writeJSONSingleField(out, "imports", importSet->imports, 0, false);
|
||||
}
|
||||
|
||||
static void writeJSON(llvm::raw_ostream &out,
|
||||
const swiftscan_dependency_graph_t fullDependencies) {
|
||||
// Write out a JSON description of all of the dependencies.
|
||||
out << "{\n";
|
||||
SWIFT_DEFER { out << "}\n"; };
|
||||
// Name of the main module.
|
||||
writeJSONSingleField(out, "mainModuleName",
|
||||
fullDependencies->main_module_name,
|
||||
/*indentLevel=*/1, /*trailingComma=*/true);
|
||||
// Write out all of the modules.
|
||||
out << " \"modules\": [\n";
|
||||
SWIFT_DEFER { out << " ]\n"; };
|
||||
const auto module_set = fullDependencies->dependencies;
|
||||
for (size_t mi = 0; mi < module_set->count; ++mi) {
|
||||
const auto &moduleInfo = *module_set->modules[mi];
|
||||
auto &directDependencies = moduleInfo.direct_dependencies;
|
||||
// The module we are describing.
|
||||
out.indent(2 * 2);
|
||||
writeEncodedModuleIdJSONValue(out, moduleInfo.module_name, 2);
|
||||
out << ",\n";
|
||||
out.indent(2 * 2);
|
||||
out << "{\n";
|
||||
auto swiftPlaceholderDeps =
|
||||
getAsPlaceholderDependencyModule(moduleInfo.details);
|
||||
auto swiftTextualDeps = getAsTextualDependencyModule(moduleInfo.details);
|
||||
auto swiftBinaryDeps = getAsBinaryDependencyModule(moduleInfo.details);
|
||||
auto clangDeps = getAsClangDependencyModule(moduleInfo.details);
|
||||
|
||||
// Module path.
|
||||
const char *modulePathSuffix = clangDeps ? ".pcm" : ".swiftmodule";
|
||||
|
||||
std::string modulePath;
|
||||
std::string moduleKindAndName =
|
||||
std::string(get_C_string(moduleInfo.module_name));
|
||||
std::string moduleName =
|
||||
moduleKindAndName.substr(moduleKindAndName.find(":") + 1);
|
||||
if (swiftPlaceholderDeps)
|
||||
modulePath = get_C_string(swiftPlaceholderDeps->compiled_module_path);
|
||||
else if (swiftBinaryDeps)
|
||||
modulePath = get_C_string(swiftBinaryDeps->compiled_module_path);
|
||||
else if (clangDeps || swiftTextualDeps)
|
||||
modulePath = get_C_string(moduleInfo.module_path);
|
||||
else
|
||||
modulePath = moduleName + modulePathSuffix;
|
||||
|
||||
writeJSONSingleField(out, "modulePath", modulePath, /*indentLevel=*/3,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Source files.
|
||||
if (swiftTextualDeps || clangDeps) {
|
||||
writeJSONSingleField(out, "sourceFiles", moduleInfo.source_files, 3,
|
||||
/*trailingComma=*/true);
|
||||
}
|
||||
|
||||
// Direct dependencies.
|
||||
if (swiftTextualDeps || swiftBinaryDeps || clangDeps)
|
||||
writeDependencies(out, directDependencies,
|
||||
"directDependencies", 3,
|
||||
/*trailingComma=*/true);
|
||||
// Swift and Clang-specific details.
|
||||
out.indent(3 * 2);
|
||||
out << "\"details\": {\n";
|
||||
out.indent(4 * 2);
|
||||
if (swiftTextualDeps) {
|
||||
out << "\"swift\": {\n";
|
||||
/// Swift interface file, if there is one. The main module, for
|
||||
/// example, will not have an interface file.
|
||||
std::string moduleInterfacePath =
|
||||
swiftTextualDeps->module_interface_path.data
|
||||
? get_C_string(swiftTextualDeps->module_interface_path)
|
||||
: "";
|
||||
if (!moduleInterfacePath.empty()) {
|
||||
writeJSONSingleField(out, "moduleInterfacePath", moduleInterfacePath, 5,
|
||||
/*trailingComma=*/true);
|
||||
out.indent(5 * 2);
|
||||
out << "\"compiledModuleCandidates\": [\n";
|
||||
for (int i = 0,
|
||||
count = swiftTextualDeps->compiled_module_candidates->count;
|
||||
i < count; ++i) {
|
||||
const auto &candidate = get_C_string(
|
||||
swiftTextualDeps->compiled_module_candidates->strings[i]);
|
||||
out.indent(6 * 2);
|
||||
out << "\"" << quote(candidate) << "\"";
|
||||
if (i != count - 1)
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
out.indent(5 * 2);
|
||||
out << "],\n";
|
||||
}
|
||||
out.indent(5 * 2);
|
||||
out << "\"commandLine\": [\n";
|
||||
for (int i = 0, count = swiftTextualDeps->command_line->count; i < count;
|
||||
++i) {
|
||||
const auto &arg =
|
||||
get_C_string(swiftTextualDeps->command_line->strings[i]);
|
||||
out.indent(6 * 2);
|
||||
out << "\"" << quote(arg) << "\"";
|
||||
if (i != count - 1)
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
out.indent(5 * 2);
|
||||
out << "],\n";
|
||||
writeJSONSingleField(out, "contextHash", swiftTextualDeps->context_hash,
|
||||
5,
|
||||
/*trailingComma=*/true);
|
||||
bool hasBridgingHeaderPath =
|
||||
swiftTextualDeps->bridging_header_path.data &&
|
||||
get_C_string(swiftTextualDeps->bridging_header_path)[0] != '\0';
|
||||
bool hasOverlayDependencies =
|
||||
swiftTextualDeps->swift_overlay_module_dependencies &&
|
||||
swiftTextualDeps->swift_overlay_module_dependencies->count > 0;
|
||||
bool commaAfterBridgingHeaderPath = hasOverlayDependencies;
|
||||
bool commaAfterExtraPcmArgs =
|
||||
hasBridgingHeaderPath || commaAfterBridgingHeaderPath;
|
||||
bool commaAfterFramework =
|
||||
swiftTextualDeps->extra_pcm_args->count != 0 || commaAfterExtraPcmArgs;
|
||||
|
||||
if (swiftTextualDeps->cas_fs_root_id.length != 0) {
|
||||
writeJSONSingleField(out, "casFSRootID",
|
||||
swiftTextualDeps->cas_fs_root_id, 5,
|
||||
/*trailingComma=*/true);
|
||||
}
|
||||
if (swiftTextualDeps->module_cache_key.length != 0) {
|
||||
writeJSONSingleField(out, "moduleCacheKey",
|
||||
swiftTextualDeps->module_cache_key, 5,
|
||||
/*trailingComma=*/true);
|
||||
}
|
||||
writeJSONSingleField(out, "isFramework", swiftTextualDeps->is_framework,
|
||||
5, commaAfterFramework);
|
||||
if (swiftTextualDeps->extra_pcm_args->count != 0) {
|
||||
out.indent(5 * 2);
|
||||
out << "\"extraPcmArgs\": [\n";
|
||||
for (int i = 0, count = swiftTextualDeps->extra_pcm_args->count;
|
||||
i < count; ++i) {
|
||||
const auto &arg =
|
||||
get_C_string(swiftTextualDeps->extra_pcm_args->strings[i]);
|
||||
out.indent(6 * 2);
|
||||
out << "\"" << quote(arg) << "\"";
|
||||
if (i != count - 1)
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
out.indent(5 * 2);
|
||||
out << (commaAfterExtraPcmArgs ? "],\n" : "]\n");
|
||||
}
|
||||
/// Bridging header and its source file dependencies, if any.
|
||||
if (hasBridgingHeaderPath) {
|
||||
out.indent(5 * 2);
|
||||
out << "\"bridgingHeader\": {\n";
|
||||
writeJSONSingleField(out, "path",
|
||||
swiftTextualDeps->bridging_header_path, 6,
|
||||
/*trailingComma=*/true);
|
||||
writeJSONSingleField(out, "sourceFiles",
|
||||
swiftTextualDeps->bridging_source_files, 6,
|
||||
/*trailingComma=*/true);
|
||||
if (swiftTextualDeps->bridging_header_include_tree.length != 0) {
|
||||
writeJSONSingleField(out, "includeTree",
|
||||
swiftTextualDeps->bridging_header_include_tree,
|
||||
6, /*trailingComma=*/true);
|
||||
}
|
||||
writeJSONSingleField(out, "moduleDependencies",
|
||||
swiftTextualDeps->bridging_module_dependencies, 6,
|
||||
/*trailingComma=*/true);
|
||||
out.indent(6 * 2);
|
||||
out << "\"commandLine\": [\n";
|
||||
for (int i = 0,
|
||||
count = swiftTextualDeps->bridging_pch_command_line->count;
|
||||
i < count; ++i) {
|
||||
const auto &arg = get_C_string(
|
||||
swiftTextualDeps->bridging_pch_command_line->strings[i]);
|
||||
out.indent(7 * 2);
|
||||
out << "\"" << quote(arg) << "\"";
|
||||
if (i != count - 1)
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
out.indent(6 * 2);
|
||||
out << "]\n";
|
||||
out.indent(5 * 2);
|
||||
out << (commaAfterBridgingHeaderPath ? "},\n" : "}\n");
|
||||
}
|
||||
if (hasOverlayDependencies) {
|
||||
writeDependencies(out, swiftTextualDeps->swift_overlay_module_dependencies,
|
||||
"swiftOverlayDependencies", 5,
|
||||
/*trailingComma=*/false);
|
||||
}
|
||||
} else if (swiftPlaceholderDeps) {
|
||||
out << "\"swiftPlaceholder\": {\n";
|
||||
|
||||
// Module doc file
|
||||
if (swiftPlaceholderDeps->module_doc_path.data &&
|
||||
get_C_string(swiftPlaceholderDeps->module_doc_path)[0] != '\0')
|
||||
writeJSONSingleField(out, "moduleDocPath",
|
||||
swiftPlaceholderDeps->module_doc_path,
|
||||
/*indentLevel=*/5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Module Source Info file
|
||||
if (swiftPlaceholderDeps->module_source_info_path.data &&
|
||||
get_C_string(swiftPlaceholderDeps->module_source_info_path)[0] !=
|
||||
'\0')
|
||||
writeJSONSingleField(out, "moduleSourceInfoPath",
|
||||
swiftPlaceholderDeps->module_source_info_path,
|
||||
/*indentLevel=*/5,
|
||||
/*trailingComma=*/false);
|
||||
} else if (swiftBinaryDeps) {
|
||||
bool hasOverlayDependencies =
|
||||
swiftBinaryDeps->swift_overlay_module_dependencies &&
|
||||
swiftBinaryDeps->swift_overlay_module_dependencies->count > 0;
|
||||
|
||||
out << "\"swiftPrebuiltExternal\": {\n";
|
||||
assert(swiftBinaryDeps->compiled_module_path.data &&
|
||||
get_C_string(swiftBinaryDeps->compiled_module_path)[0] != '\0' &&
|
||||
"Expected .swiftmodule for a Binary Swift Module Dependency.");
|
||||
|
||||
writeJSONSingleField(out, "compiledModulePath",
|
||||
swiftBinaryDeps->compiled_module_path,
|
||||
/*indentLevel=*/5,
|
||||
/*trailingComma=*/true);
|
||||
// Module doc file
|
||||
if (swiftBinaryDeps->module_doc_path.data &&
|
||||
get_C_string(swiftBinaryDeps->module_doc_path)[0] != '\0')
|
||||
writeJSONSingleField(out, "moduleDocPath",
|
||||
swiftBinaryDeps->module_doc_path,
|
||||
/*indentLevel=*/5,
|
||||
/*trailingComma=*/true);
|
||||
// Module Source Info file
|
||||
if (swiftBinaryDeps->module_source_info_path.data &&
|
||||
get_C_string(swiftBinaryDeps->module_source_info_path)[0] != '\0')
|
||||
writeJSONSingleField(out, "moduleSourceInfoPath",
|
||||
swiftBinaryDeps->module_source_info_path,
|
||||
/*indentLevel=*/5,
|
||||
/*trailingComma=*/true);
|
||||
if (swiftBinaryDeps->module_cache_key.length != 0) {
|
||||
writeJSONSingleField(out, "moduleCacheKey",
|
||||
swiftBinaryDeps->module_cache_key, 5,
|
||||
/*trailingComma=*/true);
|
||||
}
|
||||
|
||||
// Module Header Dependencies
|
||||
if (swiftBinaryDeps->header_dependency.length != 0)
|
||||
writeJSONSingleField(out, "headerDependency",
|
||||
swiftBinaryDeps->header_dependency, 5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Module Header Module Dependencies
|
||||
if (swiftBinaryDeps->header_dependencies_module_dependnecies->count != 0)
|
||||
writeJSONSingleField(out, "headerModuleDependencies",
|
||||
swiftBinaryDeps->header_dependencies_module_dependnecies, 5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Module Header Source Files
|
||||
if (swiftBinaryDeps->header_dependencies_source_files->count != 0)
|
||||
writeJSONSingleField(out, "headerDependenciesSourceFiles",
|
||||
swiftBinaryDeps->header_dependencies_source_files, 5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
if (hasOverlayDependencies) {
|
||||
writeDependencies(out, swiftBinaryDeps->swift_overlay_module_dependencies,
|
||||
"swiftOverlayDependencies", 5,
|
||||
/*trailingComma=*/true);
|
||||
}
|
||||
|
||||
writeJSONSingleField(out, "isFramework", swiftBinaryDeps->is_framework,
|
||||
5, /*trailingComma=*/false);
|
||||
} else {
|
||||
out << "\"clang\": {\n";
|
||||
|
||||
// Module map file.
|
||||
writeJSONSingleField(out, "moduleMapPath", clangDeps->module_map_path, 5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Context hash.
|
||||
writeJSONSingleField(out, "contextHash", clangDeps->context_hash, 5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Command line.
|
||||
writeJSONSingleField(out, "commandLine", clangDeps->command_line, 5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
if (clangDeps->cas_fs_root_id.length != 0)
|
||||
writeJSONSingleField(out, "casFSRootID", clangDeps->cas_fs_root_id, 5,
|
||||
/*trailingComma=*/true);
|
||||
if (clangDeps->clang_include_tree.length != 0)
|
||||
writeJSONSingleField(out, "clangIncludeTree",
|
||||
clangDeps->clang_include_tree, 5,
|
||||
/*trailingComma=*/true);
|
||||
if (clangDeps->module_cache_key.length != 0)
|
||||
writeJSONSingleField(out, "moduleCacheKey", clangDeps->module_cache_key,
|
||||
5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Captured PCM arguments.
|
||||
writeJSONSingleField(out, "capturedPCMArgs", clangDeps->captured_pcm_args, 5,
|
||||
/*trailingComma=*/false, /*nested=*/true);
|
||||
|
||||
}
|
||||
|
||||
out.indent(4 * 2);
|
||||
out << "}\n";
|
||||
out.indent(3 * 2);
|
||||
out << "}\n";
|
||||
out.indent(2 * 2);
|
||||
out << "}";
|
||||
|
||||
if (mi != module_set->count - 1)
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
static bool writePrescanJSONToOutput(DiagnosticEngine &diags,
|
||||
llvm::vfs::OutputBackend &backend,
|
||||
StringRef path,
|
||||
const swiftscan_import_set_t importSet) {
|
||||
swiftscan_import_set_t importSet) {
|
||||
return withOutputPath(diags, backend, path, [&](llvm::raw_pwrite_stream &os) {
|
||||
writePrescanJSON(os, importSet);
|
||||
return false;
|
||||
@@ -1074,7 +544,7 @@ static bool writePrescanJSONToOutput(DiagnosticEngine &diags,
|
||||
|
||||
static bool writeJSONToOutput(DiagnosticEngine &diags,
|
||||
llvm::vfs::OutputBackend &backend, StringRef path,
|
||||
const swiftscan_dependency_graph_t dependencies) {
|
||||
swiftscan_dependency_graph_t dependencies) {
|
||||
return withOutputPath(diags, backend, path, [&](llvm::raw_pwrite_stream &os) {
|
||||
writeJSON(os, dependencies);
|
||||
return false;
|
||||
|
||||
24
test/ScanDependencies/scanner_api_working_dir.swift
Normal file
24
test/ScanDependencies/scanner_api_working_dir.swift
Normal file
@@ -0,0 +1,24 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
|
||||
// RUN: %target-swift-frontend -emit-module -module-name A -o %t/include/A.swiftmodule -swift-version 5 \
|
||||
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \
|
||||
// RUN: -emit-module-interface-path %t/include/A.swiftinterface -enable-library-evolution -I %t/internal -enable-testing \
|
||||
// RUN: %t/A.swift
|
||||
|
||||
// RUN: %swift-scan-test -action scan_dependency -cwd %t -- %target-swift-frontend -emit-module -module-name Test \
|
||||
// RUN: -swift-version 5 -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \
|
||||
// RUN: -I include %t/test.swift | %FileCheck %s
|
||||
|
||||
// CHECK: "mainModuleName": "Test"
|
||||
|
||||
// RUN: cd %t
|
||||
// RUN: %swift-scan-test -action scan_dependency -- %target-swift-frontend -emit-module -module-name Test \
|
||||
// RUN: -swift-version 5 -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \
|
||||
// RUN: -I include %t/test.swift | %FileCheck %s
|
||||
|
||||
//--- test.swift
|
||||
import A
|
||||
|
||||
//--- A.swift
|
||||
public func a() {}
|
||||
@@ -154,7 +154,9 @@ swiftscan_dependency_graph_create(swiftscan_scanner_t scanner,
|
||||
Compilation.push_back(swift::c_string_utils::get_C_string(invocation->argv->strings[i]));
|
||||
|
||||
// Execute the scan and bridge the result
|
||||
auto ScanResult = ScanningTool->getDependencies(Compilation, {});
|
||||
auto ScanResult = ScanningTool->getDependencies(
|
||||
Compilation, {},
|
||||
swift::c_string_utils::get_C_string(invocation->working_directory));
|
||||
if (ScanResult.getError())
|
||||
return nullptr;
|
||||
auto DependencyGraph = std::move(*ScanResult);
|
||||
@@ -180,8 +182,9 @@ swiftscan_batch_scan_result_create(swiftscan_scanner_t scanner,
|
||||
}
|
||||
|
||||
// Execute the scan and bridge the result
|
||||
auto BatchScanResult =
|
||||
ScanningTool->getDependencies(Compilation, BatchInput, {});
|
||||
auto BatchScanResult = ScanningTool->getDependencies(
|
||||
Compilation, BatchInput, {},
|
||||
swift::c_string_utils::get_C_string(invocation->working_directory));
|
||||
swiftscan_batch_scan_result_t *Result = new swiftscan_batch_scan_result_t;
|
||||
auto ResultGraphs = new swiftscan_dependency_graph_t[BatchScanResult.size()];
|
||||
for (size_t i = 0; i < BatchScanResult.size(); ++i) {
|
||||
@@ -209,7 +212,9 @@ swiftscan_import_set_create(swiftscan_scanner_t scanner,
|
||||
Compilation.push_back(swift::c_string_utils::get_C_string(invocation->argv->strings[i]));
|
||||
|
||||
// Execute the scan and bridge the result
|
||||
auto PreScanResult = ScanningTool->getImports(Compilation);
|
||||
auto PreScanResult = ScanningTool->getImports(
|
||||
Compilation,
|
||||
swift::c_string_utils::get_C_string(invocation->working_directory));
|
||||
if (PreScanResult.getError())
|
||||
return nullptr;
|
||||
auto ImportSet = std::move(*PreScanResult);
|
||||
|
||||
@@ -9,4 +9,5 @@ add_swift_host_tool(swift-scan-test
|
||||
target_link_libraries(swift-scan-test
|
||||
PRIVATE
|
||||
swiftBasic
|
||||
swiftDependencyScanImpl
|
||||
libSwiftScan)
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include "swift-c/DependencyScan/DependencyScan.h"
|
||||
#include "swift/Basic/Defer.h"
|
||||
#include "swift/Basic/FileTypes.h"
|
||||
#include "swift/DependencyScan/DependencyScanJSON.h"
|
||||
#include "swift/DependencyScan/StringUtils.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
@@ -31,6 +33,7 @@ enum Actions {
|
||||
compute_cache_key_from_index,
|
||||
cache_query,
|
||||
replay_result,
|
||||
scan_dependency,
|
||||
};
|
||||
|
||||
llvm::cl::OptionCategory Category("swift-scan-test Options");
|
||||
@@ -43,13 +46,16 @@ llvm::cl::opt<std::string> Input("input", llvm::cl::desc("<file|index>"),
|
||||
llvm::cl::opt<unsigned> Threads("threads",
|
||||
llvm::cl::desc("<number of threads>"),
|
||||
llvm::cl::cat(Category), cl::init(1));
|
||||
llvm::cl::opt<std::string> WorkingDirectory("cwd", llvm::cl::desc("<path>"),
|
||||
llvm::cl::cat(Category));
|
||||
llvm::cl::opt<Actions>
|
||||
Action("action", llvm::cl::desc("<action>"),
|
||||
llvm::cl::values(clEnumVal(compute_cache_key, "compute cache key"),
|
||||
clEnumVal(compute_cache_key_from_index,
|
||||
"compute cache key from index"),
|
||||
clEnumVal(cache_query, "cache query"),
|
||||
clEnumVal(replay_result, "replay result")),
|
||||
clEnumVal(replay_result, "replay result"),
|
||||
clEnumVal(scan_dependency, "scan dependency")),
|
||||
llvm::cl::cat(Category));
|
||||
llvm::cl::list<std::string>
|
||||
SwiftCommands(llvm::cl::Positional, llvm::cl::desc("<swift-frontend args>"),
|
||||
@@ -185,13 +191,65 @@ static int action_replay_result(swiftscan_cas_t cas, const char *key,
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static std::vector<const char *> createArgs(ArrayRef<std::string> Cmd,
|
||||
StringSaver &Saver) {
|
||||
static int action_scan_dependency(std::vector<const char *> &Args,
|
||||
StringRef WorkingDirectory) {
|
||||
auto scanner = swiftscan_scanner_create();
|
||||
auto invocation = swiftscan_scan_invocation_create();
|
||||
auto error = [&](StringRef msg) {
|
||||
llvm::errs() << msg << "\n";
|
||||
swiftscan_scan_invocation_dispose(invocation);
|
||||
swiftscan_scanner_dispose(scanner);
|
||||
return EXIT_FAILURE;
|
||||
};
|
||||
|
||||
swiftscan_scan_invocation_set_working_directory(
|
||||
invocation, WorkingDirectory.str().c_str());
|
||||
swiftscan_scan_invocation_set_argv(invocation, Args.size(), Args.data());
|
||||
|
||||
auto graph = swiftscan_dependency_graph_create(scanner, invocation);
|
||||
if (!graph)
|
||||
return error("dependency scanning failed");
|
||||
|
||||
auto diags = swiftscan_dependency_graph_get_diagnostics(graph);
|
||||
for (unsigned i = 0; i < diags->count; ++i) {
|
||||
auto msg = swiftscan_diagnostic_get_message(diags->diagnostics[i]);
|
||||
switch (swiftscan_diagnostic_get_severity(diags->diagnostics[i])) {
|
||||
case SWIFTSCAN_DIAGNOSTIC_SEVERITY_ERROR:
|
||||
llvm::errs() << "error: ";
|
||||
break;
|
||||
case SWIFTSCAN_DIAGNOSTIC_SEVERITY_WARNING:
|
||||
llvm::errs() << "warning: ";
|
||||
break;
|
||||
case SWIFTSCAN_DIAGNOSTIC_SEVERITY_NOTE:
|
||||
llvm::errs() << "note: ";
|
||||
break;
|
||||
case SWIFTSCAN_DIAGNOSTIC_SEVERITY_REMARK:
|
||||
llvm::errs() << "remark: ";
|
||||
break;
|
||||
}
|
||||
llvm::errs() << swift::c_string_utils::get_C_string(msg) << "\n";
|
||||
}
|
||||
|
||||
swift::dependencies::writeJSON(llvm::outs(), graph);
|
||||
|
||||
swiftscan_scan_invocation_dispose(invocation);
|
||||
swiftscan_scanner_dispose(scanner);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static std::vector<const char *>
|
||||
createArgs(ArrayRef<std::string> Cmd, StringSaver &Saver, Actions Action) {
|
||||
if (!Cmd.empty() && StringRef(Cmd.front()).ends_with("swift-frontend"))
|
||||
Cmd = Cmd.drop_front();
|
||||
|
||||
// Quote all the arguments before passing to scanner. The scanner is currently
|
||||
// tokenize the command-line again before parsing.
|
||||
bool Quoted = Action == Actions::scan_dependency;
|
||||
|
||||
std::vector<const char *> Args;
|
||||
for (auto A : Cmd) {
|
||||
if (Quoted)
|
||||
A = std::string("\"") + A + "\"";
|
||||
StringRef Arg = Saver.save(A);
|
||||
Args.push_back(Arg.data());
|
||||
}
|
||||
@@ -218,7 +276,7 @@ int main(int argc, char *argv[]) {
|
||||
// Convert commands.
|
||||
llvm::BumpPtrAllocator Alloc;
|
||||
llvm::StringSaver Saver(Alloc);
|
||||
auto Args = createArgs(SwiftCommands, Saver);
|
||||
auto Args = createArgs(SwiftCommands, Saver, Action);
|
||||
|
||||
std::atomic<int> Ret = 0;
|
||||
llvm::ThreadPool Pool(llvm::hardware_concurrency(Threads));
|
||||
@@ -237,6 +295,8 @@ int main(int argc, char *argv[]) {
|
||||
case replay_result:
|
||||
Ret += action_replay_result(cas, CASID.c_str(), Args);
|
||||
break;
|
||||
case scan_dependency:
|
||||
Ret += action_scan_dependency(Args, WorkingDirectory);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ export *\n\
|
||||
for (auto &command : CommandStrArr) {
|
||||
Command.push_back(command.c_str());
|
||||
}
|
||||
auto DependenciesOrErr = ScannerTool.getDependencies(Command, {});
|
||||
auto DependenciesOrErr = ScannerTool.getDependencies(Command, {}, {});
|
||||
ASSERT_FALSE(DependenciesOrErr.getError());
|
||||
auto Dependencies = DependenciesOrErr.get();
|
||||
// TODO: Output/verify dependency graph correctness
|
||||
@@ -243,8 +243,8 @@ public func overlayFuncA() { }\n"));
|
||||
CommandB.push_back(command.c_str());
|
||||
}
|
||||
|
||||
auto instanceA = ScannerTool.initCompilerInstanceForScan(CommandA);
|
||||
auto instanceB = ScannerTool.initCompilerInstanceForScan(CommandB);
|
||||
auto instanceA = ScannerTool.initCompilerInstanceForScan(CommandA, {});
|
||||
auto instanceB = ScannerTool.initCompilerInstanceForScan(CommandB, {});
|
||||
// Ensure that scans that only differ in module name have distinct scanning context hashes
|
||||
ASSERT_NE(instanceA->ScanInstance.get()->getInvocation().getModuleScanningHash(),
|
||||
instanceB->ScanInstance.get()->getInvocation().getModuleScanningHash());
|
||||
|
||||
Reference in New Issue
Block a user