mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge remote-tracking branch 'origin/master' into master-next
This commit is contained in:
@@ -424,6 +424,14 @@ struct PrintOptions {
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Retrieve the set of options suitable for stable textual interfaces.
|
||||
///
|
||||
/// This is a format that will be parsed again later, so the output must be
|
||||
/// consistent and well-formed.
|
||||
///
|
||||
/// \see swift::emitModuleInterface
|
||||
static PrintOptions printTextualInterfaceFile();
|
||||
|
||||
static PrintOptions printModuleInterface();
|
||||
static PrintOptions printTypeInterface(Type T);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
// Copyright (c) 2014 - 2018 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
|
||||
@@ -13,10 +13,16 @@
|
||||
#ifndef SWIFT_BASIC_FILESYSTEM_H
|
||||
#define SWIFT_BASIC_FILESYSTEM_H
|
||||
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include <system_error>
|
||||
|
||||
namespace llvm {
|
||||
class raw_pwrite_stream;
|
||||
class Twine;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
namespace vfs {
|
||||
class FileSystem;
|
||||
@@ -24,6 +30,24 @@ namespace clang {
|
||||
}
|
||||
|
||||
namespace swift {
|
||||
/// Invokes \p action with a raw_ostream that refers to a temporary file,
|
||||
/// which is then renamed into place as \p outputPath when the action
|
||||
/// completes.
|
||||
///
|
||||
/// If a temporary file cannot be created for whatever reason, \p action will
|
||||
/// be invoked with a stream directly opened at \p outputPath. Otherwise, if
|
||||
/// there is already a file at \p outputPath, it will not be overwritten if
|
||||
/// the new contents are identical.
|
||||
///
|
||||
/// If the process is interrupted with a signal, any temporary file will be
|
||||
/// removed.
|
||||
///
|
||||
/// As a special case, an output path of "-" is treated as referring to
|
||||
/// stdout.
|
||||
std::error_code atomicallyWritingToFile(
|
||||
llvm::StringRef outputPath, bool binaryMode,
|
||||
llvm::function_ref<void(llvm::raw_pwrite_stream &)> action);
|
||||
|
||||
/// Moves a file from \p source to \p destination, unless there is already
|
||||
/// a file at \p destination that contains the same data as \p source.
|
||||
///
|
||||
@@ -38,6 +62,7 @@ namespace swift {
|
||||
const llvm::Twine &Name, int64_t FileSize = -1,
|
||||
bool RequiresNullTerminator = true, bool IsVolatile = false);
|
||||
} // end namespace vfs
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif // SWIFT_BASIC_FILESYSTEM_H
|
||||
|
||||
@@ -121,7 +121,7 @@ struct SupplementaryOutputPaths {
|
||||
///
|
||||
/// Currently only makes sense when the compiler has whole-module knowledge.
|
||||
///
|
||||
/// \sa ModuleOutputPath
|
||||
/// \sa swift::emitModuleInterface
|
||||
std::string ModuleInterfaceOutputPath;
|
||||
|
||||
SupplementaryOutputPaths() = default;
|
||||
|
||||
@@ -64,6 +64,21 @@ void PrintOptions::clearSynthesizedExtension() {
|
||||
TransformContext.reset();
|
||||
}
|
||||
|
||||
PrintOptions PrintOptions::printTextualInterfaceFile() {
|
||||
PrintOptions result;
|
||||
result.PrintLongAttrsOnSeparateLines = true;
|
||||
result.TypeDefinitions = true;
|
||||
result.PrintIfConfig = false;
|
||||
result.FullyQualifiedTypes = true;
|
||||
result.SkipImports = true;
|
||||
result.AccessFilter = AccessLevel::Public;
|
||||
|
||||
// FIXME: We'll need the actual default parameter expression.
|
||||
result.PrintDefaultParameterPlaceholder = false;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
TypeTransformContext::TypeTransformContext(Type T)
|
||||
: BaseType(T.getPointer()) {
|
||||
assert(T->mayHaveMembers());
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
// Copyright (c) 2014 - 2018 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
|
||||
@@ -11,9 +11,15 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Basic/FileSystem.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Process.h"
|
||||
|
||||
#include "swift/Basic/LLVM.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/Process.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
|
||||
using namespace swift;
|
||||
|
||||
@@ -30,6 +36,137 @@ namespace {
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
/// Does some simple checking to see if a temporary file can be written next to
|
||||
/// \p outputPath and then renamed into place.
|
||||
///
|
||||
/// Helper for swift::atomicallyWritingToFile.
|
||||
///
|
||||
/// If the result is an error, the write won't succeed at all, and the calling
|
||||
/// operation should bail out early.
|
||||
static llvm::ErrorOr<bool>
|
||||
canUseTemporaryForWrite(const StringRef outputPath) {
|
||||
namespace fs = llvm::sys::fs;
|
||||
|
||||
if (outputPath == "-") {
|
||||
// Special case: "-" represents stdout, and LLVM's output stream APIs are
|
||||
// aware of this. It doesn't make sense to use a temporary in this case.
|
||||
return false;
|
||||
}
|
||||
|
||||
fs::file_status status;
|
||||
(void)fs::status(outputPath, status);
|
||||
if (!fs::exists(status)) {
|
||||
// Assume we'll be able to write to both a temporary file and to the final
|
||||
// destination if the final destination doesn't exist yet.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fail early if we can't write to the final destination.
|
||||
if (!fs::can_write(outputPath))
|
||||
return llvm::make_error_code(llvm::errc::operation_not_permitted);
|
||||
|
||||
// Only use a temporary if the output is a regular file. This handles
|
||||
// things like '-o /dev/null'
|
||||
return fs::is_regular_file(status);
|
||||
}
|
||||
|
||||
/// Attempts to open a temporary file next to \p outputPath, with the intent
|
||||
/// that once the file has been written it will be renamed into place.
|
||||
///
|
||||
/// Helper for swift::atomicallyWritingToFile.
|
||||
///
|
||||
/// \param[out] openedStream On success, a stream opened for writing to the
|
||||
/// temporary file that was just created.
|
||||
/// \param outputPath The path to the final output file, which is used to decide
|
||||
/// where to put the temporary.
|
||||
/// \param openFlags Controls how the output stream will be opened.
|
||||
///
|
||||
/// \returns The path to the temporary file that was opened, or \c None if the
|
||||
/// file couldn't be created.
|
||||
static Optional<std::string>
|
||||
tryToOpenTemporaryFile(Optional<llvm::raw_fd_ostream> &openedStream,
|
||||
const StringRef outputPath,
|
||||
const llvm::sys::fs::OpenFlags openFlags) {
|
||||
namespace fs = llvm::sys::fs;
|
||||
|
||||
// Create a temporary file path.
|
||||
// Insert a placeholder for a random suffix before the extension (if any).
|
||||
// Then because some tools glob for build artifacts (such as clang's own
|
||||
// GlobalModuleIndex.cpp), also append .tmp.
|
||||
SmallString<128> tempPath;
|
||||
const StringRef outputExtension = llvm::sys::path::extension(outputPath);
|
||||
tempPath = outputPath.drop_back(outputExtension.size());
|
||||
tempPath += "-%%%%%%%%";
|
||||
tempPath += outputExtension;
|
||||
tempPath += ".tmp";
|
||||
|
||||
int fd;
|
||||
const unsigned perms = fs::all_read | fs::all_write;
|
||||
std::error_code EC = fs::createUniqueFile(tempPath, fd, tempPath, perms,
|
||||
openFlags);
|
||||
|
||||
if (EC) {
|
||||
// Ignore the specific error; the caller has to fall back to not using a
|
||||
// temporary anyway.
|
||||
return None;
|
||||
}
|
||||
|
||||
openedStream.emplace(fd, /*shouldClose=*/true);
|
||||
// Make sure the temporary file gets removed if we crash.
|
||||
llvm::sys::RemoveFileOnSignal(tempPath);
|
||||
return tempPath.str().str();
|
||||
}
|
||||
|
||||
std::error_code swift::atomicallyWritingToFile(
|
||||
const StringRef outputPath, const bool binaryMode,
|
||||
const llvm::function_ref<void(llvm::raw_pwrite_stream &)> action) {
|
||||
namespace fs = llvm::sys::fs;
|
||||
|
||||
// FIXME: This is mostly a simplified version of
|
||||
// clang::CompilerInstance::createOutputFile. It would be great to share the
|
||||
// implementation.
|
||||
assert(!outputPath.empty());
|
||||
|
||||
llvm::ErrorOr<bool> canUseTemporary = canUseTemporaryForWrite(outputPath);
|
||||
if (std::error_code error = canUseTemporary.getError())
|
||||
return error;
|
||||
|
||||
Optional<std::string> temporaryPath;
|
||||
{
|
||||
const fs::OpenFlags openFlags = (binaryMode ? fs::F_None : fs::F_Text);
|
||||
|
||||
Optional<llvm::raw_fd_ostream> OS;
|
||||
if (canUseTemporary.get()) {
|
||||
temporaryPath = tryToOpenTemporaryFile(OS, outputPath, openFlags);
|
||||
|
||||
if (!temporaryPath) {
|
||||
assert(!OS.hasValue());
|
||||
// If we failed to create the temporary, fall back to writing to the
|
||||
// file directly. This handles the corner case where we cannot write to
|
||||
// the directory, but can write to the file.
|
||||
}
|
||||
}
|
||||
|
||||
if (!OS.hasValue()) {
|
||||
std::error_code error;
|
||||
OS.emplace(outputPath, error, openFlags);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
action(OS.getValue());
|
||||
// In addition to scoping the use of 'OS', ending the scope here also
|
||||
// ensures that it's been flushed (by destroying it).
|
||||
}
|
||||
|
||||
if (!temporaryPath.hasValue()) {
|
||||
// If we didn't use a temporary, we're done!
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
return swift::moveFileIfDifferent(temporaryPath.getValue(), outputPath);
|
||||
}
|
||||
|
||||
std::error_code swift::moveFileIfDifferent(const llvm::Twine &source,
|
||||
const llvm::Twine &destination) {
|
||||
namespace fs = llvm::sys::fs;
|
||||
|
||||
@@ -3,6 +3,7 @@ add_swift_library(swiftFrontendTool STATIC
|
||||
ImportedModules.cpp
|
||||
ReferenceDependencies.cpp
|
||||
TBD.cpp
|
||||
TextualInterfaceGeneration.cpp
|
||||
DEPENDS
|
||||
swift-syntax-generated-headers SwiftOptions
|
||||
LINK_LIBRARIES
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
// Copyright (c) 2014 - 2018 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
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "ImportedModules.h"
|
||||
#include "ReferenceDependencies.h"
|
||||
#include "TBD.h"
|
||||
#include "TextualInterfaceGeneration.h"
|
||||
|
||||
#include "swift/Subsystems.h"
|
||||
#include "swift/AST/ASTScope.h"
|
||||
@@ -62,11 +63,7 @@
|
||||
#include "swift/Syntax/SyntaxNodes.h"
|
||||
#include "swift/TBDGen/TBDGen.h"
|
||||
|
||||
// FIXME: We're just using CompilerInstance::createOutputFile.
|
||||
// This API should be sunk down to LLVM.
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/APINotes/Types.h"
|
||||
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
@@ -314,47 +311,64 @@ static bool writeSIL(SILModule &SM, const PrimarySpecificPaths &PSPs,
|
||||
PSPs.OutputFilename, opts.EmitSortedSIL);
|
||||
}
|
||||
|
||||
static bool printAsObjCIfNeeded(StringRef outputPath, ModuleDecl *M,
|
||||
StringRef bridgingHeader, bool moduleIsPublic) {
|
||||
using namespace llvm::sys;
|
||||
/// A wrapper around swift::atomicallyWritingToFile that handles diagnosing any
|
||||
/// filesystem errors and ignores empty output paths.
|
||||
///
|
||||
/// \returns true if there were any errors, either from the filesystem
|
||||
/// operations or from \p action returning true.
|
||||
static bool atomicallyWritingToTextFile(
|
||||
StringRef outputPath, DiagnosticEngine &diags,
|
||||
llvm::function_ref<bool(llvm::raw_pwrite_stream &)> action) {
|
||||
assert(!outputPath.empty());
|
||||
|
||||
if (outputPath.empty())
|
||||
return false;
|
||||
|
||||
clang::CompilerInstance Clang;
|
||||
|
||||
std::string tmpFilePath;
|
||||
std::error_code EC;
|
||||
std::unique_ptr<llvm::raw_pwrite_stream> out =
|
||||
Clang.createOutputFile(outputPath, EC,
|
||||
/*Binary=*/false,
|
||||
/*RemoveFileOnSignal=*/true,
|
||||
/*BaseInput=*/"",
|
||||
path::extension(outputPath),
|
||||
/*UseTemporary=*/true,
|
||||
/*CreateMissingDirectories=*/false,
|
||||
/*ResultPathName=*/nullptr,
|
||||
&tmpFilePath);
|
||||
|
||||
if (!out) {
|
||||
M->getASTContext().Diags.diagnose(SourceLoc(), diag::error_opening_output,
|
||||
tmpFilePath, EC.message());
|
||||
return true;
|
||||
}
|
||||
|
||||
auto requiredAccess = moduleIsPublic ? AccessLevel::Public
|
||||
: AccessLevel::Internal;
|
||||
bool hadError = printAsObjC(*out, M, bridgingHeader, requiredAccess);
|
||||
out->flush();
|
||||
|
||||
EC = swift::moveFileIfDifferent(tmpFilePath, outputPath);
|
||||
bool actionFailed = false;
|
||||
std::error_code EC =
|
||||
swift::atomicallyWritingToFile(outputPath, /*binary*/false,
|
||||
[&](llvm::raw_pwrite_stream &out) {
|
||||
actionFailed = action(out);
|
||||
});
|
||||
if (EC) {
|
||||
M->getASTContext().Diags.diagnose(SourceLoc(), diag::error_opening_output,
|
||||
diags.diagnose(SourceLoc(), diag::error_opening_output,
|
||||
outputPath, EC.message());
|
||||
return true;
|
||||
}
|
||||
return actionFailed;
|
||||
}
|
||||
|
||||
return hadError;
|
||||
/// Prints the Objective-C "generated header" interface for \p M to \p
|
||||
/// outputPath.
|
||||
///
|
||||
/// ...unless \p outputPath is empty, in which case it does nothing.
|
||||
///
|
||||
/// \returns true if there were any errors
|
||||
///
|
||||
/// \see swift::printAsObjC
|
||||
static bool printAsObjCIfNeeded(StringRef outputPath, ModuleDecl *M,
|
||||
StringRef bridgingHeader, bool moduleIsPublic) {
|
||||
if (outputPath.empty())
|
||||
return false;
|
||||
return atomicallyWritingToTextFile(outputPath, M->getDiags(),
|
||||
[&](raw_ostream &out) -> bool {
|
||||
auto requiredAccess = moduleIsPublic ? AccessLevel::Public
|
||||
: AccessLevel::Internal;
|
||||
return printAsObjC(out, M, bridgingHeader, requiredAccess);
|
||||
});
|
||||
}
|
||||
|
||||
/// Prints the stable textual interface for \p M to \p outputPath.
|
||||
///
|
||||
/// ...unless \p outputPath is empty, in which case it does nothing.
|
||||
///
|
||||
/// \returns true if there were any errors
|
||||
///
|
||||
/// \see swift::emitModuleInterface
|
||||
static bool printModuleInterfaceIfNeeded(StringRef outputPath, ModuleDecl *M) {
|
||||
if (outputPath.empty())
|
||||
return false;
|
||||
return atomicallyWritingToTextFile(outputPath, M->getDiags(),
|
||||
[M](raw_ostream &out) -> bool {
|
||||
return swift::emitModuleInterface(out, M);
|
||||
});
|
||||
}
|
||||
|
||||
/// Returns the OutputKind for the given Action.
|
||||
@@ -1322,6 +1336,10 @@ static bool performCompileStepsPostSILGen(
|
||||
Instance.getMainModule(),
|
||||
opts.ImplicitObjCHeaderPath, moduleIsPublic);
|
||||
|
||||
(void)printModuleInterfaceIfNeeded(
|
||||
PSPs.SupplementaryOutputs.ModuleInterfaceOutputPath,
|
||||
Instance.getMainModule());
|
||||
|
||||
if (Action == FrontendOptions::ActionType::EmitSIB)
|
||||
return serializeSIB(SM.get(), PSPs, Instance.getASTContext(), MSF);
|
||||
|
||||
|
||||
31
lib/FrontendTool/TextualInterfaceGeneration.cpp
Normal file
31
lib/FrontendTool/TextualInterfaceGeneration.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
//===--- TextualInterfaceGeneration.cpp - swiftinterface files ------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2018 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 "TextualInterfaceGeneration.h"
|
||||
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/Module.h"
|
||||
|
||||
using namespace swift;
|
||||
|
||||
bool swift::emitModuleInterface(raw_ostream &out, ModuleDecl *M) {
|
||||
const PrintOptions printOptions = PrintOptions::printTextualInterfaceFile();
|
||||
SmallVector<Decl *, 16> topLevelDecls;
|
||||
M->getTopLevelDecls(topLevelDecls);
|
||||
for (const Decl *D : topLevelDecls) {
|
||||
if (!D->shouldPrintInContext(printOptions))
|
||||
continue;
|
||||
D->print(out, printOptions);
|
||||
out << "\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
39
lib/FrontendTool/TextualInterfaceGeneration.h
Normal file
39
lib/FrontendTool/TextualInterfaceGeneration.h
Normal file
@@ -0,0 +1,39 @@
|
||||
//===--- TextualInterfaceGeneration.h - swiftinterface files ----*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2018 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_FRONTENDTOOL_TEXTUALINTERFACEGENERATION_H
|
||||
#define SWIFT_FRONTENDTOOL_TEXTUALINTERFACEGENERATION_H
|
||||
|
||||
#include "swift/Basic/LLVM.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
class ModuleDecl;
|
||||
|
||||
/// Emit a stable, textual interface for \p M, which can be used by a client
|
||||
/// source file to import this module.
|
||||
///
|
||||
/// Unlike a serialized module, the textual format generated by
|
||||
/// emitModuleInterface is intended to be stable across compiler versions while
|
||||
/// still describing the full ABI of the module in question.
|
||||
///
|
||||
/// The initial plan for this format can be found at
|
||||
/// https://forums.swift.org/t/plan-for-module-stability/14551/
|
||||
///
|
||||
/// \return true if an error occurred
|
||||
///
|
||||
/// \sa swift::serialize
|
||||
bool emitModuleInterface(raw_ostream &out, ModuleDecl *M);
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
// Copyright (c) 2014 - 2018 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
|
||||
@@ -38,9 +38,7 @@
|
||||
#include "swift/Serialization/SerializationOptions.h"
|
||||
#include "swift/Strings.h"
|
||||
|
||||
// FIXME: We're just using CompilerInstance::createOutputFile.
|
||||
// This API should be sunk down to LLVM.
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/Basic/Module.h"
|
||||
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
@@ -5093,44 +5091,15 @@ void Serializer::writeDocToStream(raw_ostream &os, ModuleOrSourceFile DC,
|
||||
static inline bool
|
||||
withOutputFile(ASTContext &ctx, StringRef outputPath,
|
||||
llvm::function_ref<void(raw_ostream &)> action){
|
||||
namespace path = llvm::sys::path;
|
||||
clang::CompilerInstance Clang;
|
||||
std::error_code EC = swift::atomicallyWritingToFile(outputPath,
|
||||
/*binary*/true,
|
||||
action);
|
||||
if (!EC)
|
||||
return false;
|
||||
|
||||
std::string tmpFilePath;
|
||||
{
|
||||
std::error_code EC;
|
||||
std::unique_ptr<llvm::raw_pwrite_stream> out =
|
||||
Clang.createOutputFile(outputPath, EC,
|
||||
/*Binary=*/true,
|
||||
/*RemoveFileOnSignal=*/true,
|
||||
/*BaseInput=*/"",
|
||||
path::extension(outputPath),
|
||||
/*UseTemporary=*/true,
|
||||
/*CreateMissingDirectories=*/false,
|
||||
/*ResultPathName=*/nullptr,
|
||||
&tmpFilePath);
|
||||
|
||||
if (!out) {
|
||||
StringRef problematicPath =
|
||||
tmpFilePath.empty() ? outputPath : StringRef(tmpFilePath);
|
||||
ctx.Diags.diagnose(SourceLoc(), diag::error_opening_output,
|
||||
problematicPath, EC.message());
|
||||
return true;
|
||||
}
|
||||
|
||||
action(*out);
|
||||
}
|
||||
|
||||
if (!tmpFilePath.empty()) {
|
||||
std::error_code EC = swift::moveFileIfDifferent(tmpFilePath, outputPath);
|
||||
if (EC) {
|
||||
ctx.Diags.diagnose(SourceLoc(), diag::error_opening_output,
|
||||
outputPath, EC.message());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void swift::serialize(ModuleOrSourceFile DC,
|
||||
|
||||
1
test/ModuleInterface/Inputs/other.swift
Normal file
1
test/ModuleInterface/Inputs/other.swift
Normal file
@@ -0,0 +1 @@
|
||||
public func otherFileFunction() {}
|
||||
9
test/ModuleInterface/print-from-partial-modules.swift
Normal file
9
test/ModuleInterface/print-from-partial-modules.swift
Normal file
@@ -0,0 +1,9 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend -emit-module -o %t/main~partial.swiftmodule -primary-file %s %S/Inputs/other.swift -module-name main
|
||||
// RUN: %target-swift-frontend -emit-module -o %t/other~partial.swiftmodule %s -primary-file %S/Inputs/other.swift -module-name main
|
||||
// RUN: %target-swift-frontend -merge-modules -emit-module -o /dev/null -emit-interface-path - %t/main~partial.swiftmodule -module-name main %t/other~partial.swiftmodule | %FileCheck %s
|
||||
|
||||
// CHECK: {{^}}func verySimpleFunction(){{$}}
|
||||
public func verySimpleFunction() {}
|
||||
|
||||
// CHECK: {{^}}func otherFileFunction(){{$}}
|
||||
8
test/ModuleInterface/smoke-test.swift
Normal file
8
test/ModuleInterface/smoke-test.swift
Normal file
@@ -0,0 +1,8 @@
|
||||
// RUN: %target-swift-frontend -emit-interface-path - -emit-module -o /dev/null %s | %FileCheck %s
|
||||
// RUN: %target-swift-frontend -emit-interface-path - -emit-module -o /dev/null %s %S/Inputs/other.swift | %FileCheck -check-prefix CHECK-MULTI-FILE %s
|
||||
|
||||
// CHECK: public func verySimpleFunction(){{$}}
|
||||
// CHECK-MULTI-FILE: public func verySimpleFunction(){{$}}
|
||||
public func verySimpleFunction() {}
|
||||
|
||||
// CHECK-MULTI-FILE: public func otherFileFunction(){{$}}
|
||||
Reference in New Issue
Block a user