mirror of
https://github.com/apple/swift.git
synced 2026-06-20 15:42:51 +02:00
34d52cfe1a
Compute and propagate the library level (api/spi/ipi) of each module dependency through the dependency scanner so that the compiler can correctly enforce private module import diagnostics in CAS mode, where path-based SPI detection fails because CAS abstracts file paths to content IDs. Swift modules: - Detect library level from the module interface path using libraryLevelFromPath() during scanning, for both textual (.swiftinterface) and binary (.swiftmodule) Swift modules. Clang modules: - Expose ModuleMapIsPrivate from clang::Module in ModuleDeps via the dependency scanning infrastructure. - Set library level for clang modules in bridgeClangModuleDependency() using ModuleMapIsPrivate (catches module.private.modulemap in any SDK location) and libraryLevelFromPath() on the module map file (catches modules under PrivateFrameworks directories). The library level is: - Stored in ModuleDependencyInfo and serialized in the module dependency cache (format version bumped to v8). - Exposed through the swiftscan C API via a new swiftscan_module_info_get_library_level() function (API minor version bumped to 3). - Emitted in the dependency scanner JSON output as "libraryLevel" for all module kinds (Swift textual, Swift binary, Clang, and main module). - Parsed from the explicit module map JSON by ExplicitModuleMapParser for both Swift (ExplicitSwiftModuleInputInfo) and Clang (ExplicitClangModuleInputInfo) modules. - Looked up in ModuleLibraryLevelRequest via ASTContext::getExplicitModuleLibraryLevel(name, isClang), which consults the appropriate map (Swift or Clang) based on module kind. rdar://172693314 Assisted-By: Claude
709 lines
25 KiB
C++
709 lines
25 KiB
C++
//===--- 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/Assertions.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 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 << "]";
|
|
}
|
|
|
|
/// Write a boolean value as JSON.
|
|
void writeJSONValue(llvm::raw_ostream &out, bool value, unsigned indentLevel) {
|
|
out.write_escaped(value ? "true" : "false");
|
|
}
|
|
|
|
/// Write a boolean value as JSON.
|
|
void writeJSONValue(llvm::raw_ostream &out, uint32_t value, unsigned indentLevel) {
|
|
out.write_escaped(std::to_string(value));
|
|
}
|
|
|
|
/// 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) {
|
|
out.indent(indentLevel * 2);
|
|
writeJSONValue(out, fieldName, indentLevel);
|
|
out << ": ";
|
|
auto updatedIndentLevel = indentLevel;
|
|
|
|
writeJSONValue(out, value, updatedIndentLevel);
|
|
|
|
if (trailingComma)
|
|
out << ",";
|
|
out << "\n";
|
|
}
|
|
|
|
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 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 {
|
|
moduleKind = "clang";
|
|
moduleName = valueStr.substr(clangPrefix.size() + 1);
|
|
}
|
|
writeJSONSingleField(out, moduleKind, moduleName, indentLevel + 1,
|
|
/*trailingComma=*/false);
|
|
out.indent(indentLevel * 2);
|
|
out << "}";
|
|
}
|
|
|
|
|
|
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";
|
|
}
|
|
|
|
void writeLinkLibraries(llvm::raw_ostream &out,
|
|
const swiftscan_link_library_set_t *link_libraries,
|
|
unsigned indentLevel, bool trailingComma) {
|
|
out.indent(indentLevel * 2);
|
|
out << "\"linkLibraries\": ";
|
|
out << "[\n";
|
|
|
|
for (size_t i = 0; i < link_libraries->count; ++i) {
|
|
const auto &llInfo = *link_libraries->link_libraries[i];
|
|
out.indent((indentLevel + 1) * 2);
|
|
out << "{\n";
|
|
auto entryIndentLevel = ((indentLevel + 2) * 2);
|
|
out.indent(entryIndentLevel);
|
|
out << "\"linkName\": ";
|
|
writeJSONValue(out, llInfo.name, indentLevel);
|
|
out << ",\n";
|
|
out.indent(entryIndentLevel);
|
|
out << "\"isStatic\": ";
|
|
writeJSONValue(out, llInfo.isStatic, entryIndentLevel);
|
|
out << ",\n";
|
|
out.indent(entryIndentLevel);
|
|
out << "\"isFramework\": ";
|
|
writeJSONValue(out, llInfo.isFramework, entryIndentLevel);
|
|
out << ",\n";
|
|
out.indent(entryIndentLevel);
|
|
out << "\"shouldForceLoad\": ";
|
|
writeJSONValue(out, llInfo.forceLoad, entryIndentLevel);
|
|
out << "\n";
|
|
out.indent((indentLevel + 1) * 2);
|
|
out << "}";
|
|
if (i != link_libraries->count - 1) {
|
|
out << ",";
|
|
}
|
|
out << "\n";
|
|
}
|
|
|
|
out.indent(indentLevel * 2);
|
|
out << "]";
|
|
|
|
if (trailingComma)
|
|
out << ",";
|
|
out << "\n";
|
|
}
|
|
|
|
void writeImportInfos(llvm::raw_ostream &out,
|
|
const swiftscan_import_info_set_t *imports,
|
|
bool optional, unsigned indentLevel,
|
|
bool trailingComma) {
|
|
out.indent(indentLevel * 2);
|
|
if (optional)
|
|
out << "\"optionalImports\": ";
|
|
else
|
|
out << "\"imports\": ";
|
|
out << "[\n";
|
|
|
|
for (size_t i = 0; i < imports->count; ++i) {
|
|
const auto &iInfo = *imports->imports[i];
|
|
out.indent((indentLevel + 1) * 2);
|
|
out << "{\n";
|
|
auto entryIndentLevel = ((indentLevel + 2) * 2);
|
|
out.indent(entryIndentLevel);
|
|
out << "\"identifier\": ";
|
|
writeJSONValue(out, iInfo.import_identifier, indentLevel);
|
|
out << ",\n";
|
|
out.indent(entryIndentLevel);
|
|
out << "\"accessLevel\": ";
|
|
switch (iInfo.access_level) {
|
|
case SWIFTSCAN_ACCESS_LEVEL_PRIVATE:
|
|
writeJSONValue(out, StringRef("private"), entryIndentLevel);
|
|
break;
|
|
case SWIFTSCAN_ACCESS_LEVEL_FILEPRIVATE:
|
|
writeJSONValue(out, StringRef("fileprivate"), entryIndentLevel);
|
|
break;
|
|
case SWIFTSCAN_ACCESS_LEVEL_INTERNAL:
|
|
writeJSONValue(out, StringRef("internal"), entryIndentLevel);
|
|
break;
|
|
case SWIFTSCAN_ACCESS_LEVEL_PACKAGE:
|
|
writeJSONValue(out, StringRef("package"), entryIndentLevel);
|
|
break;
|
|
case SWIFTSCAN_ACCESS_LEVEL_PUBLIC:
|
|
writeJSONValue(out, StringRef("public"), entryIndentLevel);
|
|
break;
|
|
}
|
|
|
|
if (iInfo.source_locations->count) {
|
|
out << ",\n";
|
|
out.indent(entryIndentLevel);
|
|
out << "\"importLocations\": ";
|
|
out << "[\n";
|
|
auto slIndentLevel = ((entryIndentLevel + 4));
|
|
for (size_t i = 0; i < iInfo.source_locations->count; ++i) {
|
|
out.indent(entryIndentLevel + 2);
|
|
out << "{\n";
|
|
const auto &sl = *iInfo.source_locations->source_locations[i];
|
|
out.indent(slIndentLevel);
|
|
out << "\"bufferIdentifier\": ";
|
|
writeJSONValue(out, sl.buffer_identifier, indentLevel);
|
|
out << ",\n";
|
|
out.indent(slIndentLevel);
|
|
out << "\"linuNumber\": ";
|
|
writeJSONValue(out, sl.line_number, indentLevel);
|
|
out << ",\n";
|
|
out.indent(slIndentLevel);
|
|
out << "\"columnNumber\": ";
|
|
writeJSONValue(out, sl.column_number, indentLevel);
|
|
out << "\n";
|
|
out.indent(entryIndentLevel + 2);
|
|
out << "}";
|
|
if (i != iInfo.source_locations->count - 1)
|
|
out << ",";
|
|
out << "\n";
|
|
}
|
|
out.indent(entryIndentLevel);
|
|
out << "]\n";
|
|
} else {
|
|
out << "\n";
|
|
}
|
|
out.indent((indentLevel + 1) * 2);
|
|
out << "}";
|
|
if (i != imports->count - 1)
|
|
out << ",";
|
|
out << "\n";
|
|
}
|
|
|
|
out.indent(indentLevel * 2);
|
|
out << "]";
|
|
|
|
if (trailingComma)
|
|
out << ",";
|
|
out << "\n";
|
|
}
|
|
|
|
static void
|
|
writeMacroDependencies(llvm::raw_ostream &out,
|
|
const swiftscan_macro_dependency_set_t *macro_deps,
|
|
unsigned indentLevel, bool trailingComma) {
|
|
if (!macro_deps)
|
|
return;
|
|
|
|
out.indent(indentLevel * 2);
|
|
out << "\"macroDependencies\": ";
|
|
out << "[\n";
|
|
for (size_t i = 0; i < macro_deps->count; ++i) {
|
|
const auto ¯oInfo = *macro_deps->macro_dependencies[i];
|
|
out.indent((indentLevel + 1) * 2);
|
|
out << "{\n";
|
|
auto entryIndentLevel = ((indentLevel + 2) * 2);
|
|
out.indent(entryIndentLevel);
|
|
out << "\"moduleName\": ";
|
|
writeJSONValue(out, macroInfo.module_name, indentLevel);
|
|
out << ",\n";
|
|
out.indent(entryIndentLevel);
|
|
out << "\"libraryPath\": ";
|
|
writeJSONValue(out, macroInfo.library_path, entryIndentLevel);
|
|
out << ",\n";
|
|
out.indent(entryIndentLevel);
|
|
out << "\"executablePath\": ";
|
|
writeJSONValue(out, macroInfo.executable_path, entryIndentLevel);
|
|
out << "\n";
|
|
out.indent((indentLevel + 1) * 2);
|
|
out << "}";
|
|
if (i != macro_deps->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_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 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 (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);
|
|
|
|
// Library level.
|
|
{
|
|
StringRef levelStr;
|
|
switch (moduleInfo.library_level) {
|
|
case SWIFTSCAN_LIBRARY_LEVEL_OTHER:
|
|
levelStr = "other";
|
|
break;
|
|
case SWIFTSCAN_LIBRARY_LEVEL_IPI:
|
|
levelStr = "ipi";
|
|
break;
|
|
case SWIFTSCAN_LIBRARY_LEVEL_SPI:
|
|
levelStr = "spi";
|
|
break;
|
|
case SWIFTSCAN_LIBRARY_LEVEL_API:
|
|
levelStr = "api";
|
|
break;
|
|
}
|
|
writeJSONSingleField(out, "libraryLevel", levelStr, /*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);
|
|
writeLinkLibraries(out, moduleInfo.link_libraries,
|
|
3, /*trailingComma=*/true);
|
|
writeImportInfos(out, moduleInfo.imports, /*optional*/ false,
|
|
3, /*trailingComma=*/true);
|
|
writeImportInfos(out, moduleInfo.optional_imports, /*optional*/ true,
|
|
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 hasBridgingHeader =
|
|
(swiftTextualDeps->bridging_header_path.data &&
|
|
get_C_string(swiftTextualDeps->bridging_header_path)[0] != '\0') ||
|
|
swiftTextualDeps->bridging_pch_command_line->count != 0;
|
|
bool hasOverlayDependencies =
|
|
swiftTextualDeps->swift_overlay_module_dependencies &&
|
|
swiftTextualDeps->swift_overlay_module_dependencies->count > 0;
|
|
bool hasSourceImportedDependencies =
|
|
swiftTextualDeps->source_import_module_dependencies &&
|
|
swiftTextualDeps->source_import_module_dependencies->count > 0;
|
|
bool commaAfterBridgingHeaderPath = hasOverlayDependencies;
|
|
bool commaAfterFramework =
|
|
hasBridgingHeader || commaAfterBridgingHeaderPath;
|
|
|
|
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);
|
|
}
|
|
if (swiftTextualDeps->chained_bridging_header_path.length != 0) {
|
|
writeJSONSingleField(out, "chainedBridgingHeaderPath",
|
|
swiftTextualDeps->chained_bridging_header_path, 5,
|
|
/*trailingComma=*/true);
|
|
}
|
|
writeJSONSingleField(out, "userModuleVersion",
|
|
swiftTextualDeps->user_module_version, 5,
|
|
/*trailingComma=*/true);
|
|
writeMacroDependencies(out, swiftTextualDeps->macro_dependencies, 5,
|
|
/*trailingComma=*/true);
|
|
if (hasSourceImportedDependencies) {
|
|
writeDependencies(out, swiftTextualDeps->source_import_module_dependencies,
|
|
"sourceImportedDependencies", 5,
|
|
/*trailingComma=*/true);
|
|
}
|
|
writeJSONSingleField(out, "isFramework", swiftTextualDeps->is_framework,
|
|
5, commaAfterFramework);
|
|
/// Bridging header and its source file dependencies, if any.
|
|
if (hasBridgingHeader) {
|
|
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 (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);
|
|
writeJSONSingleField(out, "userModuleVersion",
|
|
swiftBinaryDeps->user_module_version,
|
|
/*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);
|
|
}
|
|
|
|
writeMacroDependencies(out, swiftBinaryDeps->macro_dependencies, 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,
|
|
clangDeps->clang_include_tree.length != 0 ||
|
|
clangDeps->module_cache_key.length != 0);
|
|
|
|
if (clangDeps->clang_include_tree.length != 0)
|
|
writeJSONSingleField(out, "clangIncludeTree",
|
|
clangDeps->clang_include_tree, 5,
|
|
clangDeps->module_cache_key.length != 0);
|
|
if (clangDeps->module_cache_key.length != 0)
|
|
writeJSONSingleField(out, "moduleCacheKey", clangDeps->module_cache_key,
|
|
5,
|
|
/*trailingComma=*/false);
|
|
}
|
|
|
|
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
|