From dd68ef05f1b508f40a035ca597c98098dcf3109c Mon Sep 17 00:00:00 2001 From: Harlan Haskins Date: Tue, 14 Aug 2018 18:01:56 -0700 Subject: [PATCH 1/4] [TBDGen] Allow user-provided dylib version flags This patch adds two frontend arguments, -tbd-compatibility-version and -tbd-current-version, both of which accept SemVer versions. These will show up in the generated TBD file for a given module as current-version: 2.7 compatibility-version: 2.0 These flags both default to `1.0.0`. --- include/swift/Frontend/FrontendOptions.h | 5 ++++ include/swift/Option/FrontendOptions.td | 14 +++++++++++ include/swift/TBDGen/TBDGen.h | 5 ++++ .../ArgsToFrontendOptionsConverter.cpp | 12 ++++++++++ lib/FrontendTool/FrontendTool.cpp | 2 ++ lib/TBDGen/TBDGen.cpp | 17 +++++++++++--- test/TBD/dylib-version.swift | 23 +++++++++++++++++++ 7 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 test/TBD/dylib-version.swift diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index 8b130b59f0073..ebec55cea9039 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -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" @@ -262,6 +263,10 @@ class FrontendOptions { /// The install_name to use in the TBD file. std::string TBDInstallName; + // The compatibility_version to use in the TBD file. + version::Version TBDCurrentVersion = {1, 0, 0}; + 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. diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index 6bc86d88139a5..fa834f1891cbe 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -74,6 +74,20 @@ def tbd_install_name def tbd_install_name_EQ : Joined<["-"], "tbd-install_name=">, Alias; +def tbd_current_version + : Separate<["-"], "tbd-current-version">, MetaVarName<"">, + HelpText<"The current_version to use in an emitted TBD file">; + +def tbd_current_version_EQ : Joined<["-"], "tbd-current-version=">, + Alias; + +def tbd_compatibility_version + : Separate<["-"], "tbd-compatibility-version">, MetaVarName<"">, + HelpText<"The compatibility_version to use in an emitted TBD file">; + +def tbd_compatibility_version_EQ : Joined<["-"], "tbd-compatibility-version=">, + Alias; + def verify : Flag<["-"], "verify">, HelpText<"Verify diagnostics against expected-{error|warning|note} " "annotations">; diff --git a/include/swift/TBDGen/TBDGen.h b/include/swift/TBDGen/TBDGen.h index ef4190079ba5d..0c4142cdfec9a 100644 --- a/include/swift/TBDGen/TBDGen.h +++ b/include/swift/TBDGen/TBDGen.h @@ -14,6 +14,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" +#include "swift/Basic/Version.h" namespace llvm { class raw_ostream; @@ -35,6 +36,10 @@ struct TBDGenOptions { llvm::StringRef InstallName; /// \brief The module link name (for force loading). llvm::StringRef ModuleLinkName; + /// \brief The current dylib version. + version::Version CurrentVersion; + /// \brief The dylib compatibility version. + version::Version CompatibilityVersion; }; void enumeratePublicSymbols(FileUnit *module, llvm::StringSet<> &symbols, diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index 770b1c8e1b6ca..0c05036cd0240 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -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( diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 09bc9a2379268..ccb3d1274b1d0 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -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); } diff --git a/lib/TBDGen/TBDGen.cpp b/lib/TBDGen/TBDGen.cpp index bd00a6d5913b2..1c65cbd7ce45f 100644 --- a/lib/TBDGen/TBDGen.cpp +++ b/lib/TBDGen/TBDGen.cpp @@ -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, @@ -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()); diff --git a/test/TBD/dylib-version.swift b/test/TBD/dylib-version.swift new file mode 100644 index 0000000000000..321c6d244e61a --- /dev/null +++ b/test/TBD/dylib-version.swift @@ -0,0 +1,23 @@ +// 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 + +// 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 From 68dcb9e6d0d64d2c1d8805642f7e40c7ae978599 Mon Sep 17 00:00:00 2001 From: Harlan Haskins Date: Tue, 14 Aug 2018 18:11:54 -0700 Subject: [PATCH 2/4] Reword some comments --- include/swift/Frontend/FrontendOptions.h | 4 +++- include/swift/TBDGen/TBDGen.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index ebec55cea9039..f05b74115f8c1 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -263,8 +263,10 @@ class FrontendOptions { /// The install_name to use in the TBD file. std::string TBDInstallName; - // The compatibility_version to use in the TBD file. + // The current project version to use in the generated TBD file. version::Version TBDCurrentVersion = {1, 0, 0}; + + // The dylib compatibility-version to use in the generated TBD file. version::Version TBDCompatibilityVersion = {1, 0, 0}; /// An enum with different modes for automatically crashing at defined times. diff --git a/include/swift/TBDGen/TBDGen.h b/include/swift/TBDGen/TBDGen.h index 0c4142cdfec9a..2f940180ccb78 100644 --- a/include/swift/TBDGen/TBDGen.h +++ b/include/swift/TBDGen/TBDGen.h @@ -36,7 +36,7 @@ struct TBDGenOptions { llvm::StringRef InstallName; /// \brief The module link name (for force loading). llvm::StringRef ModuleLinkName; - /// \brief The current dylib version. + /// \brief The current project version. version::Version CurrentVersion; /// \brief The dylib compatibility version. version::Version CompatibilityVersion; From fc2ff48b814b99cb1e92c60106d90bb40c04ee66 Mon Sep 17 00:00:00 2001 From: Harlan Haskins Date: Wed, 15 Aug 2018 10:35:37 -0700 Subject: [PATCH 3/4] Add test for invalid version string --- test/TBD/dylib-version.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/TBD/dylib-version.swift b/test/TBD/dylib-version.swift index 321c6d244e61a..4df259ba9a63d 100644 --- a/test/TBD/dylib-version.swift +++ b/test/TBD/dylib-version.swift @@ -2,6 +2,7 @@ // 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 +// 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 @@ -21,3 +22,5 @@ // 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 From 1be5dd85936e73d4e258055bc5f5013123188b6f Mon Sep 17 00:00:00 2001 From: Harlan Haskins Date: Wed, 15 Aug 2018 10:40:46 -0700 Subject: [PATCH 4/4] Expand on comments for TBD flags --- include/swift/Frontend/FrontendOptions.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index f05b74115f8c1..6b9b422209a4e 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -263,10 +263,14 @@ 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. + // 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. + // 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.