diff --git a/Package.swift b/Package.swift index 5206b268e..840541887 100644 --- a/Package.swift +++ b/Package.swift @@ -468,16 +468,23 @@ extension Array where Element == PackageDescription.CXXSetting { .define("SWT_NO_LIBDISPATCH", .whenEmbedded()), ] - // Capture the testing library's version as a C++ string constant. + // Capture the testing library's commit info as C++ constants. if let git { - let testingLibraryVersion = if let tag = git.currentTag { - tag - } else if git.hasUncommittedChanges { - "\(git.currentCommit) (modified)" + if let tag = git.currentTag { + result.append(.define("SWT_TESTING_LIBRARY_VERSION", to: #""\#(tag)""#)) } else { - git.currentCommit + result.append(.define("SWT_TESTING_LIBRARY_VERSION", to: "0")) } - result.append(.define("SWT_TESTING_LIBRARY_VERSION", to: #""\#(testingLibraryVersion)""#)) + + result.append(.define("SWT_TESTING_LIBRARY_COMMIT_HASH", to: #""\#(git.currentCommit)""#)) + if git.hasUncommittedChanges { + result.append(.define("SWT_TESTING_LIBRARY_COMMIT_MODIFIED", to: "1")) + } + } else if let gitHubSHA = Context.environment["GITHUB_SHA"] { + // When building in GitHub Actions, the git command may fail to get us the + // commit hash, so check if GitHub shared it with us instead. + result.append(.define("SWT_TESTING_LIBRARY_VERSION", to: "0")) + result.append(.define("SWT_TESTING_LIBRARY_COMMIT_HASH", to: #""\#(gitHubSHA)""#)) } return result diff --git a/Sources/Testing/Support/Versions.swift b/Sources/Testing/Support/Versions.swift index 62193d6c4..76c5aeaf6 100644 --- a/Sources/Testing/Support/Versions.swift +++ b/Sources/Testing/Support/Versions.swift @@ -129,9 +129,26 @@ let simulatorVersion: String = { /// an event writer. /// /// This value is not part of the public interface of the testing library. -var testingLibraryVersion: String { - swt_getTestingLibraryVersion().flatMap(String.init(validatingCString:)) ?? "unknown" -} +let testingLibraryVersion: String = { + var result = swt_getTestingLibraryVersion().flatMap(String.init(validatingCString:)) ?? "unknown" + + // Get details of the git commit used when compiling the testing library. + var commitHash: UnsafePointer? + var commitModified = CBool(false) + swt_getTestingLibraryCommit(&commitHash, &commitModified) + + if let commitHash = commitHash.flatMap(String.init(validatingCString:)) { + // Truncate to 15 characters of the hash to match `swift --version`. + let commitHash = commitHash.prefix(15) + if commitModified { + result = "\(result) (\(commitHash) - modified)" + } else { + result = "\(result) (\(commitHash))" + } + } + + return result +}() /// Get the LLVM target triple used to build the testing library, if available. /// diff --git a/Sources/_TestingInternals/CMakeLists.txt b/Sources/_TestingInternals/CMakeLists.txt index 16713ab27..2b385cb1b 100644 --- a/Sources/_TestingInternals/CMakeLists.txt +++ b/Sources/_TestingInternals/CMakeLists.txt @@ -8,6 +8,7 @@ set(CMAKE_CXX_SCAN_FOR_MODULES 0) +include(GitCommit) include(LibraryVersion) include(TargetTriple) add_library(_TestingInternals STATIC diff --git a/Sources/_TestingInternals/Versions.cpp b/Sources/_TestingInternals/Versions.cpp index 97eace99e..8e85f3d06 100644 --- a/Sources/_TestingInternals/Versions.cpp +++ b/Sources/_TestingInternals/Versions.cpp @@ -19,6 +19,19 @@ const char *swt_getTestingLibraryVersion(void) { #endif } +void swt_getTestingLibraryCommit(const char *_Nullable *_Nonnull outHash, bool *outModified) { +#if defined(SWT_TESTING_LIBRARY_COMMIT_HASH) + *outHash = SWT_TESTING_LIBRARY_COMMIT_HASH; +#else + *outHash = nullptr; +#endif +#if defined(SWT_TESTING_LIBRARY_COMMIT_MODIFIED) + *outModified = (SWT_TESTING_LIBRARY_COMMIT_MODIFIED != 0); +#else + *outModified = false; +#endif +} + const char *swt_getTargetTriple(void) { #if defined(SWT_TARGET_TRIPLE) return SWT_TARGET_TRIPLE; diff --git a/Sources/_TestingInternals/include/Versions.h b/Sources/_TestingInternals/include/Versions.h index ed523b86f..b188a4d66 100644 --- a/Sources/_TestingInternals/include/Versions.h +++ b/Sources/_TestingInternals/include/Versions.h @@ -38,6 +38,15 @@ static inline uint64_t swt_getSwiftCompilerVersion(void) { /// other conditions. Do not attempt to parse it. SWT_EXTERN const char *_Nullable swt_getTestingLibraryVersion(void); +/// Get details of the source control (git) commit from which the testing +/// library was built. +/// +/// - Parameters: +/// - outHash: On return, set to a pointer to a string containing the commit +/// hash from which the testing library was built. +/// - outModified: On return, whether or not there were uncommitted changes. +SWT_EXTERN void swt_getTestingLibraryCommit(const char *_Nullable *_Nonnull outHash, bool *outModified); + /// Get the LLVM target triple used to build the testing library. /// /// - Returns: A string containing the LLVM target triple used to build the diff --git a/cmake/modules/GitCommit.cmake b/cmake/modules/GitCommit.cmake new file mode 100644 index 000000000..86b0b4733 --- /dev/null +++ b/cmake/modules/GitCommit.cmake @@ -0,0 +1,35 @@ +# This source file is part of the Swift.org open source project +# +# Copyright (c) 2024–2025 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 Swift project authors + +find_package(Git QUIET) +if(Git_FOUND) + # Get the commit hash corresponding to the current build. + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-parse --verify HEAD + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + OUTPUT_VARIABLE SWT_TESTING_LIBRARY_COMMIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) + + # Check if there are local changes. + execute_process( + COMMAND ${GIT_EXECUTABLE} status -s + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + OUTPUT_VARIABLE SWT_TESTING_LIBRARY_COMMIT_MODIFIED + OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() + +if(SWT_TESTING_LIBRARY_COMMIT_HASH) + message(STATUS "Swift Testing commit hash: ${SWT_TESTING_LIBRARY_COMMIT_HASH}") + add_compile_definitions( + "$<$:SWT_TESTING_LIBRARY_COMMIT_HASH=\"${SWT_TESTING_LIBRARY_COMMIT_HASH}\">") + if(SWT_TESTING_LIBRARY_COMMIT_MODIFIED) + add_compile_definitions( + "$<$:SWT_TESTING_LIBRARY_COMMIT_MODIFIED=1>") + endif() +endif() diff --git a/cmake/modules/LibraryVersion.cmake b/cmake/modules/LibraryVersion.cmake index 259ead608..32901365a 100644 --- a/cmake/modules/LibraryVersion.cmake +++ b/cmake/modules/LibraryVersion.cmake @@ -10,34 +10,6 @@ # remember to remove -dev. set(SWT_TESTING_LIBRARY_VERSION "6.3-dev") -find_package(Git QUIET) -if(Git_FOUND) - # Get the commit hash corresponding to the current build. Limit length to 15 - # to match `swift --version` output format. - execute_process( - COMMAND ${GIT_EXECUTABLE} rev-parse --short=15 --verify HEAD - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - OUTPUT_VARIABLE GIT_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_QUIET) - - # Check if there are local changes. - execute_process( - COMMAND ${GIT_EXECUTABLE} status -s - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - OUTPUT_VARIABLE GIT_STATUS - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(GIT_STATUS) - set(GIT_VERSION "${GIT_VERSION} - modified") - endif() -endif() - -# Combine the hard-coded Swift version with available Git information. -if(GIT_VERSION) -set(SWT_TESTING_LIBRARY_VERSION "${SWT_TESTING_LIBRARY_VERSION} (${GIT_VERSION})") -endif() - -# All done! message(STATUS "Swift Testing version: ${SWT_TESTING_LIBRARY_VERSION}") add_compile_definitions( "$<$:SWT_TESTING_LIBRARY_VERSION=\"${SWT_TESTING_LIBRARY_VERSION}\">")