mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Separate dependency tracking from Make-style .d file generation.
This refactoring is groundwork for saving the cross-module dependencies in the swiftdeps files as well, so that we know to rebuild files if an outside file changes (such as a bridging header, another framework's headers, or another framework's swiftmodule). Part of rdar://problem/19270920 Swift SVN r24258
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include "swift/AST/Identifier.h"
|
||||
#include "swift/Basic/LLVM.h"
|
||||
#include "swift/Basic/SourceLoc.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/TinyPtrVector.h"
|
||||
|
||||
namespace swift {
|
||||
@@ -31,13 +32,28 @@ class NominalTypeDecl;
|
||||
|
||||
enum class KnownProtocolKind : uint8_t;
|
||||
|
||||
/// Records dependencies on files outside of the current module.
|
||||
class DependencyTracker {
|
||||
virtual void anchor();
|
||||
protected:
|
||||
DependencyTracker() = default;
|
||||
llvm::SetVector<std::string, std::vector<std::string>> paths;
|
||||
|
||||
public:
|
||||
virtual ~DependencyTracker() = default;
|
||||
virtual void addDependency(StringRef file) {}
|
||||
/// Adds a file as a dependency.
|
||||
///
|
||||
/// The contents of \p file are taken literally, and should be appropriate
|
||||
/// for appearing in a list of dependencies suitable for tooling like Make.
|
||||
/// No path canonicalization is done.
|
||||
void addDependency(StringRef file) {
|
||||
paths.insert(file);
|
||||
}
|
||||
|
||||
/// Fetches the list of dependencies.
|
||||
ArrayRef<std::string> getDependencies() const {
|
||||
if (paths.empty())
|
||||
return None;
|
||||
assert((&paths[0]) + (paths.size() - 1) == &paths.back() &&
|
||||
"elements not stored contiguously");
|
||||
return llvm::makeArrayRef(&paths[0], paths.size());
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Abstract interface that loads named modules into the AST.
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
//===- DependencyFileGenerator.h - .d file generation -----------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_FRONTEND_DEPENDENCYFILEGENERATOR_H
|
||||
#define SWIFT_FRONTEND_DEPENDENCYFILEGENERATOR_H
|
||||
|
||||
#include "swift/AST/ModuleLoader.h"
|
||||
#include "swift/Basic/LLVM.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include <vector>
|
||||
|
||||
namespace swift {
|
||||
class DependencyFileGenerator : public DependencyTracker {
|
||||
std::vector<std::string> targets;
|
||||
llvm::SetVector<std::string, std::vector<std::string>> paths;
|
||||
public:
|
||||
virtual void addDependency(StringRef file) override;
|
||||
|
||||
void addTarget(StringRef targetName);
|
||||
void writeToStream(llvm::raw_ostream &os) const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -39,7 +39,6 @@ using namespace swift;
|
||||
|
||||
LazyResolver::~LazyResolver() = default;
|
||||
void ModuleLoader::anchor() {}
|
||||
void DependencyTracker::anchor() {}
|
||||
|
||||
llvm::StringRef swift::getProtocolName(KnownProtocolKind kind) {
|
||||
switch (kind) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
add_swift_library(swiftFrontend
|
||||
CompilerInvocation.cpp
|
||||
DependencyFileGenerator.cpp
|
||||
DiagnosticVerifier.cpp
|
||||
Frontend.cpp
|
||||
FrontendOptions.cpp
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
//===- DependencyFileGenerator.cpp - .d file generation -------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Frontend/DependencyFileGenerator.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace swift;
|
||||
|
||||
void DependencyFileGenerator::addDependency(StringRef file) {
|
||||
paths.insert(file);
|
||||
}
|
||||
|
||||
void DependencyFileGenerator::addTarget(StringRef targetName) {
|
||||
if (!targetName.empty())
|
||||
targets.push_back(targetName);
|
||||
}
|
||||
|
||||
void DependencyFileGenerator::writeToStream(llvm::raw_ostream &os) const {
|
||||
// Declare a helper for escaping file names for use in Makefiles.
|
||||
llvm::SmallString<256> pathBuf;
|
||||
auto escape = [&](StringRef raw) -> StringRef {
|
||||
pathBuf.clear();
|
||||
|
||||
static const char badChars[] = " $#:\n";
|
||||
size_t prev = 0;
|
||||
for (auto index = raw.find_first_of(badChars); index != StringRef::npos;
|
||||
index = raw.find_first_of(badChars, index+1)) {
|
||||
pathBuf.append(raw.slice(prev, index));
|
||||
if (raw[index] == '$')
|
||||
pathBuf.push_back('$');
|
||||
else
|
||||
pathBuf.push_back('\\');
|
||||
prev = index;
|
||||
}
|
||||
pathBuf.append(raw.substr(prev));
|
||||
return pathBuf;
|
||||
};
|
||||
|
||||
// FIXME: Xcode can't currently handle multiple targets in a single
|
||||
// dependency line.
|
||||
for (StringRef targetName : targets) {
|
||||
os << targetName << " :";
|
||||
for (StringRef path : paths)
|
||||
os << ' ' << escape(path);
|
||||
os << '\n';
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "swift/AST/ReferencedNameTracker.h"
|
||||
#include "swift/Basic/Fallthrough.h"
|
||||
#include "swift/Basic/SourceManager.h"
|
||||
#include "swift/Frontend/DependencyFileGenerator.h"
|
||||
#include "swift/Frontend/DiagnosticVerifier.h"
|
||||
#include "swift/Frontend/Frontend.h"
|
||||
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
|
||||
@@ -57,23 +56,54 @@ static std::string displayName(StringRef MainExecutablePath) {
|
||||
}
|
||||
|
||||
/// Emits a Make-style dependencies file.
|
||||
static bool emitMakeDependencies(DiagnosticEngine &Diags,
|
||||
DependencyFileGenerator &DFG,
|
||||
static bool emitMakeDependencies(DiagnosticEngine &diags,
|
||||
DependencyTracker &depTracker,
|
||||
const FrontendOptions &opts) {
|
||||
opts.forAllOutputPaths([&DFG](StringRef target) { DFG.addTarget(target); });
|
||||
|
||||
std::error_code EC;
|
||||
llvm::raw_fd_ostream out(opts.DependenciesFilePath, EC,
|
||||
llvm::sys::fs::F_None);
|
||||
|
||||
if (out.has_error() || EC) {
|
||||
Diags.diagnose(SourceLoc(), diag::error_opening_output,
|
||||
diags.diagnose(SourceLoc(), diag::error_opening_output,
|
||||
opts.DependenciesFilePath, EC.message());
|
||||
out.clear_error();
|
||||
return true;
|
||||
}
|
||||
|
||||
DFG.writeToStream(out);
|
||||
// Declare a helper for escaping file names for use in Makefiles.
|
||||
llvm::SmallString<256> pathBuf;
|
||||
auto escape = [&](StringRef raw) -> StringRef {
|
||||
pathBuf.clear();
|
||||
|
||||
static const char badChars[] = " $#:\n";
|
||||
size_t prev = 0;
|
||||
for (auto index = raw.find_first_of(badChars); index != StringRef::npos;
|
||||
index = raw.find_first_of(badChars, index+1)) {
|
||||
pathBuf.append(raw.slice(prev, index));
|
||||
if (raw[index] == '$')
|
||||
pathBuf.push_back('$');
|
||||
else
|
||||
pathBuf.push_back('\\');
|
||||
prev = index;
|
||||
}
|
||||
pathBuf.append(raw.substr(prev));
|
||||
return pathBuf;
|
||||
};
|
||||
|
||||
// FIXME: Xcode can't currently handle multiple targets in a single
|
||||
// dependency line.
|
||||
opts.forAllOutputPaths([&](StringRef targetName) {
|
||||
out << targetName << " :";
|
||||
// Print dependencies we've picked up during compilation.
|
||||
for (StringRef path : depTracker.getDependencies())
|
||||
out << ' ' << escape(path);
|
||||
// Also include all other files in the module. Make-style dependencies
|
||||
// need to be conservative!
|
||||
for (StringRef path : opts.InputFilenames)
|
||||
out << ' ' << escape(path);
|
||||
out << '\n';
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -342,10 +372,8 @@ static bool performCompile(CompilerInstance &Instance,
|
||||
if (opts.PrintClangStats && Context.getClangModuleLoader())
|
||||
Context.getClangModuleLoader()->printStatistics();
|
||||
|
||||
if (DependencyTracker *DT = Instance.getDependencyTracker()) {
|
||||
auto &DFG = *static_cast<DependencyFileGenerator*>(DT);
|
||||
(void)emitMakeDependencies(Context.Diags, DFG, opts);
|
||||
}
|
||||
if (DependencyTracker *DT = Instance.getDependencyTracker())
|
||||
(void)emitMakeDependencies(Context.Diags, *DT, opts);
|
||||
|
||||
if (shouldTrackReferences)
|
||||
emitReferenceDependencies(Context.Diags, Instance.getPrimarySourceFile(),
|
||||
@@ -594,9 +622,9 @@ int frontend_main(ArrayRef<const char *>Args,
|
||||
enableDiagnosticVerifier(Instance.getSourceMgr());
|
||||
}
|
||||
|
||||
DependencyFileGenerator DFG;
|
||||
DependencyTracker depTracker;
|
||||
if (!Invocation.getFrontendOptions().DependenciesFilePath.empty())
|
||||
Instance.setDependencyTracker(&DFG);
|
||||
Instance.setDependencyTracker(&depTracker);
|
||||
|
||||
if (Instance.setup(Invocation)) {
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user