Skip to content

[Dependency Scanner] Use Clang scanner's module name query API instead of creating a dummy file #60807

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 12, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 10 additions & 65 deletions lib/ClangImporter/ClangModuleDependencyScanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,6 @@ using namespace clang::tooling;
using namespace clang::tooling::dependencies;

class swift::ClangModuleDependenciesCacheImpl {
/// Cache the names of the files used for the "import hack" to compute module
/// dependencies.
/// FIXME: This should go away once Clang's dependency scanning library
/// can scan by module name.
llvm::StringMap<std::string> importHackFileCache;

public:
/// Set containing all of the Clang modules that have already been seen.
llvm::StringSet<> alreadySeen;
Expand All @@ -44,44 +38,11 @@ class swift::ClangModuleDependenciesCacheImpl {
DependencyScanningTool tool;

ClangModuleDependenciesCacheImpl()
: importHackFileCache(), service(ScanningMode::DependencyDirectivesScan,
ScanningOutputFormat::Full,
clang::CASOptions(), nullptr, nullptr),
: service(ScanningMode::DependencyDirectivesScan,
ScanningOutputFormat::Full, clang::CASOptions(), nullptr, nullptr),
tool(service) {}
~ClangModuleDependenciesCacheImpl();

/// Retrieve the name of the file used for the "import hack" that is
/// used to scan the dependencies of a Clang module.
llvm::ErrorOr<StringRef> getImportHackFile(StringRef moduleName);
};

ClangModuleDependenciesCacheImpl::~ClangModuleDependenciesCacheImpl() {
if (!importHackFileCache.empty()) {
for (auto& it: importHackFileCache) {
llvm::sys::fs::remove(it.second);
}
}
}

llvm::ErrorOr<StringRef> ClangModuleDependenciesCacheImpl::getImportHackFile(StringRef moduleName) {
auto cacheIt = importHackFileCache.find(moduleName.str());
if (cacheIt != importHackFileCache.end())
return cacheIt->second;

// Create a temporary file.
int resultFD;
SmallString<128> resultPath;
if (auto error = llvm::sys::fs::createTemporaryFile(
"import-hack-" + moduleName.str(), "c", resultFD, resultPath))
return error;

llvm::raw_fd_ostream out(resultFD, /*shouldClose=*/true);
out << "#pragma clang module import " << moduleName.str() << ";\n";
llvm::sys::RemoveFileOnSignal(resultPath);
importHackFileCache.insert(std::make_pair(moduleName, resultPath.str().str()));
return importHackFileCache[moduleName];
}

// Add search paths.
// Note: This is handled differently for the Clang importer itself, which
// adds search paths to Clang's data structures rather than to its
Expand All @@ -103,7 +64,7 @@ static void addSearchPathInvocationArguments(
/// Create the command line for Clang dependency scanning.
static std::vector<std::string> getClangDepScanningInvocationArguments(
ASTContext &ctx,
StringRef sourceFileName) {
Optional<StringRef> sourceFileName = None) {
std::vector<std::string> commandLineArgs;

// Form the basic command line.
Expand All @@ -116,7 +77,10 @@ static std::vector<std::string> getClangDepScanningInvocationArguments(
commandLineArgs.begin(), commandLineArgs.end(),
"<swift-imported-modules>");
assert(sourceFilePos != commandLineArgs.end());
*sourceFilePos = sourceFileName.str();
if (sourceFileName.hasValue())
*sourceFilePos = sourceFileName->str();
else
commandLineArgs.erase(sourceFilePos);

// HACK! Drop the -fmodule-format= argument and the one that
// precedes it.
Expand All @@ -140,18 +104,6 @@ static std::vector<std::string> getClangDepScanningInvocationArguments(
*syntaxOnlyPos = "-c";
}

// HACK: Stolen from ClangScanDeps.cpp
commandLineArgs.push_back("-o");
commandLineArgs.push_back("/dev/null");
commandLineArgs.push_back("-M");
commandLineArgs.push_back("-MT");
commandLineArgs.push_back("import-hack.o");
commandLineArgs.push_back("-Xclang");
commandLineArgs.push_back("-Eonly");
commandLineArgs.push_back("-Xclang");
commandLineArgs.push_back("-sys-header-deps");
commandLineArgs.push_back("-Wno-error");

return commandLineArgs;
}

Expand Down Expand Up @@ -323,16 +275,9 @@ Optional<ModuleDependencies> ClangImporter::getModuleDependencies(
// Retrieve or create the shared state.
auto clangImpl = getOrCreateClangImpl(cache);

// HACK! Replace the module import buffer name with the source file hack.
auto importHackFile = clangImpl->getImportHackFile(moduleName);
if (!importHackFile) {
// FIXME: Emit a diagnostic here.
return None;
}

// Determine the command-line arguments for dependency scanning.
std::vector<std::string> commandLineArgs =
getClangDepScanningInvocationArguments(ctx, *importHackFile);
getClangDepScanningInvocationArguments(ctx);
// The Swift compiler does not have a concept of a working directory.
// It is instead handled by the Swift driver by resolving relative paths
// according to the driver's notion of a working directory. On the other hand,
Expand All @@ -354,7 +299,7 @@ Optional<ModuleDependencies> ClangImporter::getModuleDependencies(
}

auto clangDependencies = clangImpl->tool.getFullDependencies(
commandLineArgs, workingDir, clangImpl->alreadySeen);
commandLineArgs, workingDir, clangImpl->alreadySeen, moduleName);
if (!clangDependencies) {
auto errorStr = toString(clangDependencies.takeError());
// We ignore the "module 'foo' not found" error, the Swift dependency
Expand Down Expand Up @@ -407,7 +352,7 @@ bool ClangImporter::addBridgingHeaderDependencies(

// Determine the command-line arguments for dependency scanning.
std::vector<std::string> commandLineArgs =
getClangDepScanningInvocationArguments(ctx, bridgingHeader);
getClangDepScanningInvocationArguments(ctx, StringRef(bridgingHeader));
std::string workingDir =
ctx.SourceMgr.getFileSystem()->getCurrentWorkingDirectory().get();

Expand Down