mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
This is an attribute that gets put on an import in library FooKit to keep it from being a requirement to import FooKit. It's not checked at all, meaning that in this form it is up to the author of FooKit to make sure nothing in its API or ABI depends on the implementation-only dependency. There's also no debugging support here (debugging FooKit /should/ import the implementation-only dependency if it's present). The goal is to get to a point where it /can/ be checked, i.e. FooKit developers are prevented from writing code that would rely on FooKit's implementation-only dependency being present when compiling clients of FooKit. But right now it's not. rdar://problem/48985979
121 lines
3.9 KiB
C++
121 lines
3.9 KiB
C++
//===--- ImportedModules.cpp -- generates the list of imported modules ----===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 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 "ImportedModules.h"
|
|
#include "swift/AST/ASTContext.h"
|
|
#include "swift/AST/Decl.h"
|
|
#include "swift/AST/DiagnosticEngine.h"
|
|
#include "swift/AST/DiagnosticsFrontend.h"
|
|
#include "swift/AST/Module.h"
|
|
#include "swift/Basic/LLVM.h"
|
|
#include "swift/Basic/STLExtras.h"
|
|
#include "swift/ClangImporter/ClangImporter.h"
|
|
#include "swift/Frontend/FrontendOptions.h"
|
|
#include "clang/Basic/Module.h"
|
|
#include "llvm/ADT/SetVector.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/Support/FileSystem.h"
|
|
|
|
using namespace swift;
|
|
|
|
static StringRef getTopLevelName(const clang::Module *module) {
|
|
return module->getTopLevelModule()->Name;
|
|
}
|
|
|
|
static void findAllClangImports(const clang::Module *module,
|
|
llvm::SetVector<StringRef> &modules) {
|
|
for (auto imported : module->Imports) {
|
|
modules.insert(getTopLevelName(imported));
|
|
}
|
|
|
|
for (auto sub :
|
|
makeIteratorRange(module->submodule_begin(), module->submodule_end())) {
|
|
findAllClangImports(sub, modules);
|
|
}
|
|
}
|
|
|
|
bool swift::emitImportedModules(ASTContext &Context, ModuleDecl *mainModule,
|
|
const FrontendOptions &opts) {
|
|
|
|
std::string path = opts.InputsAndOutputs.getSingleOutputFilename();
|
|
std::error_code EC;
|
|
llvm::raw_fd_ostream out(path, EC, llvm::sys::fs::F_None);
|
|
|
|
if (out.has_error() || EC) {
|
|
Context.Diags.diagnose(SourceLoc(), diag::error_opening_output, path,
|
|
EC.message());
|
|
out.clear_error();
|
|
return true;
|
|
}
|
|
|
|
llvm::SetVector<StringRef> Modules;
|
|
|
|
// Find the imports in the main Swift code.
|
|
llvm::SmallVector<Decl *, 32> Decls;
|
|
mainModule->getDisplayDecls(Decls);
|
|
for (auto D : Decls) {
|
|
auto ID = dyn_cast<ImportDecl>(D);
|
|
if (!ID)
|
|
continue;
|
|
|
|
auto accessPath = ID->getModulePath();
|
|
// only the top-level name is needed (i.e. A in A.B.C)
|
|
Modules.insert(accessPath[0].first.str());
|
|
}
|
|
|
|
// And now look in the C code we're possibly using.
|
|
auto clangImporter =
|
|
static_cast<ClangImporter *>(Context.getClangModuleLoader());
|
|
|
|
StringRef implicitHeaderPath = opts.ImplicitObjCHeaderPath;
|
|
if (!implicitHeaderPath.empty()) {
|
|
if (!clangImporter->importBridgingHeader(implicitHeaderPath, mainModule)) {
|
|
ModuleDecl::ImportFilter importFilter;
|
|
importFilter |= ModuleDecl::ImportFilterKind::Public;
|
|
importFilter |= ModuleDecl::ImportFilterKind::Private;
|
|
importFilter |= ModuleDecl::ImportFilterKind::ImplementationOnly;
|
|
|
|
SmallVector<ModuleDecl::ImportedModule, 16> imported;
|
|
clangImporter->getImportedHeaderModule()->getImportedModules(
|
|
imported, importFilter);
|
|
|
|
for (auto IM : imported) {
|
|
if (auto clangModule = IM.second->findUnderlyingClangModule())
|
|
Modules.insert(getTopLevelName(clangModule));
|
|
else
|
|
assert(IM.second->isStdlibModule() &&
|
|
"unexpected non-stdlib swift module");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (opts.ImportUnderlyingModule) {
|
|
auto underlyingModule = clangImporter->loadModule(
|
|
SourceLoc(), std::make_pair(mainModule->getName(), SourceLoc()));
|
|
if (!underlyingModule) {
|
|
Context.Diags.diagnose(SourceLoc(),
|
|
diag::error_underlying_module_not_found,
|
|
mainModule->getName());
|
|
return true;
|
|
}
|
|
auto clangModule = underlyingModule->findUnderlyingClangModule();
|
|
|
|
findAllClangImports(clangModule, Modules);
|
|
}
|
|
|
|
for (auto name : Modules) {
|
|
out << name << "\n";
|
|
}
|
|
|
|
return false;
|
|
}
|