Skip to content

[TBDGen] Allow user-provided dylib version flags #18716

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 4 commits into from
Aug 15, 2018
Merged
Show file tree
Hide file tree
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
11 changes: 11 additions & 0 deletions include/swift/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define SWIFT_FRONTEND_FRONTENDOPTIONS_H

#include "swift/Basic/FileTypes.h"
#include "swift/Basic/Version.h"
#include "swift/Frontend/FrontendInputsAndOutputs.h"
#include "swift/Frontend/InputFile.h"
#include "llvm/ADT/Hashing.h"
Expand Down Expand Up @@ -262,6 +263,16 @@ class FrontendOptions {
/// The install_name to use in the TBD file.
std::string TBDInstallName;

// The current project version to use in the generated TBD file. Defaults
// to 1, which matches the default if the DYLIB_CURRENT_VERSION build setting
// is not set.
version::Version TBDCurrentVersion = {1, 0, 0};

// The dylib compatibility-version to use in the generated TBD file. Defaults
// to 1, which matches the default if the DYLIB_COMPATIBILITY_VERSION build
// setting is not set.
version::Version TBDCompatibilityVersion = {1, 0, 0};

/// An enum with different modes for automatically crashing at defined times.
enum class DebugCrashMode {
None, ///< Don't automatically crash.
Expand Down
14 changes: 14 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,20 @@ def tbd_install_name
def tbd_install_name_EQ : Joined<["-"], "tbd-install_name=">,
Alias<tbd_install_name>;

def tbd_current_version
: Separate<["-"], "tbd-current-version">, MetaVarName<"<version>">,
HelpText<"The current_version to use in an emitted TBD file">;

def tbd_current_version_EQ : Joined<["-"], "tbd-current-version=">,
Alias<tbd_current_version>;

def tbd_compatibility_version
: Separate<["-"], "tbd-compatibility-version">, MetaVarName<"<version>">,
HelpText<"The compatibility_version to use in an emitted TBD file">;

def tbd_compatibility_version_EQ : Joined<["-"], "tbd-compatibility-version=">,
Alias<tbd_compatibility_version>;

def verify : Flag<["-"], "verify">,
HelpText<"Verify diagnostics against expected-{error|warning|note} "
"annotations">;
Expand Down
5 changes: 5 additions & 0 deletions include/swift/TBDGen/TBDGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "swift/Basic/Version.h"

namespace llvm {
class raw_ostream;
Expand All @@ -35,6 +36,10 @@ struct TBDGenOptions {
llvm::StringRef InstallName;
/// \brief The module link name (for force loading).
llvm::StringRef ModuleLinkName;
/// \brief The current project version.
version::Version CurrentVersion;
/// \brief The dylib compatibility version.
version::Version CompatibilityVersion;
};

void enumeratePublicSymbols(FileUnit *module, llvm::StringSet<> &symbols,
Expand Down
12 changes: 12 additions & 0 deletions lib/Frontend/ArgsToFrontendOptionsConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,18 @@ void ArgsToFrontendOptionsConverter::computeTBDOptions() {
if (const Arg *A = Args.getLastArg(OPT_tbd_install_name)) {
Opts.TBDInstallName = A->getValue();
}
if (const Arg *A = Args.getLastArg(OPT_tbd_compatibility_version)) {
if (auto vers = version::Version::parseVersionString(
A->getValue(), SourceLoc(), &Diags)) {
Opts.TBDCompatibilityVersion = *vers;
}
}
if (const Arg *A = Args.getLastArg(OPT_tbd_current_version)) {
if (auto vers = version::Version::parseVersionString(
A->getValue(), SourceLoc(), &Diags)) {
Opts.TBDCurrentVersion = *vers;
}
}
}

void ArgsToFrontendOptionsConverter::setUnsignedIntegerArgument(
Expand Down
2 changes: 2 additions & 0 deletions lib/FrontendTool/FrontendTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,8 @@ static bool writeTBDIfNeeded(CompilerInvocation &Invocation,
opts.InstallName = installName;
opts.HasMultipleIGMs = Invocation.getSILOptions().hasMultipleIGMs();
opts.ModuleLinkName = frontendOpts.ModuleLinkName;
opts.CurrentVersion = frontendOpts.TBDCurrentVersion;
opts.CompatibilityVersion = frontendOpts.TBDCompatibilityVersion;

return writeTBD(Instance.getMainModule(), TBDPath, opts);
}
Expand Down
17 changes: 14 additions & 3 deletions lib/TBDGen/TBDGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,18 @@ void TBDGenVisitor::addFirstFileSymbols() {
}
}

/// Converts a version tuple into a packed version, ignoring components beyond
/// major, minor, and subminor.
static tapi::internal::PackedVersion
convertToPacked(version::Version &version) {
// FIXME: Warn if version is greater than 3 components?
unsigned major = 0, minor = 0, subminor = 0;
if (version.size() > 0) major = version[0];
if (version.size() > 1) minor = version[1];
if (version.size() > 2) subminor = version[2];
return tapi::internal::PackedVersion(major, minor, subminor);
}

static void enumeratePublicSymbolsAndWrite(ModuleDecl *M, FileUnit *singleFile,
StringSet *symbols,
llvm::raw_ostream *os,
Expand All @@ -422,10 +434,9 @@ static void enumeratePublicSymbolsAndWrite(ModuleDecl *M, FileUnit *singleFile,
tapi::internal::InterfaceFile file;
file.setFileType(tapi::internal::FileType::TBD_V3);
file.setInstallName(opts.InstallName);
file.setCompatibilityVersion(tapi::internal::PackedVersion(1, 0, 0));
file.setCurrentVersion(convertToPacked(opts.CurrentVersion));
file.setCompatibilityVersion(convertToPacked(opts.CompatibilityVersion));
file.setTwoLevelNamespace();
// FIXME: proper version
file.setCurrentVersion(tapi::internal::PackedVersion(1, 0, 0));
file.setSwiftABIVersion(TAPI_SWIFT_ABI_VERSION);
file.setPlatform(tapi::internal::mapToSinglePlatform(target));
auto arch = tapi::internal::getArchType(target.getArchName());
Expand Down
26 changes: 26 additions & 0 deletions test/TBD/dylib-version.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-ir -o /dev/null %s -tbd-current-version 2.0.3 -tbd-compatibility-version 1.7 -emit-tbd -emit-tbd-path %t/both_provided.tbd
// RUN: %target-swift-frontend -emit-ir -o /dev/null %s -tbd-current-version 2.0 -emit-tbd -emit-tbd-path %t/only_current_provided.tbd
// RUN: %target-swift-frontend -emit-ir -o /dev/null %s -tbd-compatibility-version 2 -emit-tbd -emit-tbd-path %t/only_compat_provided.tbd
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a test case for something that doesn't parse, to be sure that it produces a diagnostic?

// RUN: not %target-swift-frontend -emit-ir -o /dev/null %s -tbd-compatibility-version not_a_version_string -emit-tbd -emit-tbd-path /dev/null 2>&1 | %FileCheck %s --check-prefix BOGUS

// RUN: %FileCheck %s --check-prefix BOTH < %t/both_provided.tbd
// RUN: %FileCheck %s --check-prefix CURRENT < %t/only_current_provided.tbd
// RUN: %FileCheck %s --check-prefix COMPAT < %t/only_compat_provided.tbd

// BOTH: current-version: 2.0.3
// BOTH: compatibility-version: 1.7
// CURRENT: current-version: 2

// Compatibility version defaults to 1 if not present in TBD file, and
// tapi does not write field if compatibility version is 1

// CURRENT-NOT: compatibility-version: 1

// COMPAT: compatibility-version: 2

// Same as above -- current version defaults to 1 and is not present in
// emitted TBD file if it's 1.
// COMPAT-NOT: current-version: 1

// BOGUS: version component contains non-numeric characters