diff --git a/Package.swift b/Package.swift index a82241527..6cde28ea4 100644 --- a/Package.swift +++ b/Package.swift @@ -363,6 +363,19 @@ extension BuildSettingCondition { } } +/// A constant set of platforms including Android when the compiler is 6.3 or +/// newer. +/// +/// This constant is used to conditionally enable features on Android only on +/// newer compilers. +nonisolated(unsafe) var androidIfCompiler6_3: some Collection { +#if compiler(>=6.3) + CollectionOfOne(.android) +#else + EmptyCollection() +#endif +} + extension Array where Element == PackageDescription.SwiftSetting { /// Settings intended to be applied to every Swift target in this package. /// Analogous to project-level build settings in an Xcode project. @@ -398,8 +411,8 @@ extension Array where Element == PackageDescription.SwiftSetting { .define("SWT_TARGET_OS_APPLE", .whenApple()), - .define("SWT_NO_EXIT_TESTS", .whenEmbedded(or: .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .android]))), - .define("SWT_NO_PROCESS_SPAWNING", .whenEmbedded(or: .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .android]))), + .define("SWT_NO_EXIT_TESTS", .whenEmbedded(or: .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi] + androidIfCompiler6_3))), + .define("SWT_NO_PROCESS_SPAWNING", .whenEmbedded(or: .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi] + androidIfCompiler6_3))), .define("SWT_NO_SNAPSHOT_TYPES", .whenEmbedded(or: .whenApple(false))), .define("SWT_NO_DYNAMIC_LINKING", .whenEmbedded(or: .when(platforms: [.wasi]))), .define("SWT_NO_PIPES", .whenEmbedded(or: .when(platforms: [.wasi]))), @@ -457,8 +470,8 @@ extension Array where Element == PackageDescription.CXXSetting { var result = Self() result += [ - .define("SWT_NO_EXIT_TESTS", .whenEmbedded(or: .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .android]))), - .define("SWT_NO_PROCESS_SPAWNING", .whenEmbedded(or: .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi, .android]))), + .define("SWT_NO_EXIT_TESTS", .whenEmbedded(or: .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi]))), + .define("SWT_NO_PROCESS_SPAWNING", .whenEmbedded(or: .when(platforms: [.iOS, .watchOS, .tvOS, .visionOS, .wasi]))), .define("SWT_NO_SNAPSHOT_TYPES", .whenEmbedded(or: .whenApple(false))), .define("SWT_NO_DYNAMIC_LINKING", .whenEmbedded(or: .when(platforms: [.wasi]))), .define("SWT_NO_PIPES", .whenEmbedded(or: .when(platforms: [.wasi]))), diff --git a/Sources/Overlays/_Testing_Foundation/Attachments/Attachment+URL.swift b/Sources/Overlays/_Testing_Foundation/Attachments/Attachment+URL.swift index 3ca05b8d1..a7fec71ea 100644 --- a/Sources/Overlays/_Testing_Foundation/Attachments/Attachment+URL.swift +++ b/Sources/Overlays/_Testing_Foundation/Attachments/Attachment+URL.swift @@ -160,6 +160,13 @@ private let _archiverPath: String? = { /// an archive (currently of `.zip` format, although this is subject to change.) private func _compressContentsOfDirectory(at directoryURL: URL) async throws -> Data { #if !SWT_NO_PROCESS_SPAWNING +#if os(Android) + guard #available(Android 28, *) else { + // API level 28 corresponds to Android 9 Pie. + throw CocoaError(.featureUnsupported, userInfo: [NSLocalizedDescriptionKey: "Attaching directories to tests requires Android 9 (API level 28) or newer."]) + } +#endif + let temporaryName = "\(UUID().uuidString).zip" let temporaryURL = FileManager.default.temporaryDirectory.appendingPathComponent(temporaryName) defer { @@ -180,12 +187,15 @@ private func _compressContentsOfDirectory(at directoryURL: URL) async throws -> // OpenBSD's tar(1) does not support writing PKZIP archives, and /usr/bin/zip // tool is an optional install, so we check if it's present before trying to // execute it. -#if os(Linux) || os(OpenBSD) + // + // TODO: figure out whether tar or zip is available on Android and where it's stored +#if os(Linux) || os(OpenBSD) || os(Android) let archiverPath = "/bin/sh" -#if os(Linux) +#if os(Linux) || os(Android) let trueArchiverPath = "/usr/bin/zip" #else let trueArchiverPath = "/usr/local/bin/zip" +#endif var isDirectory = false if !FileManager.default.fileExists(atPath: trueArchiverPath, isDirectory: &isDirectory) || isDirectory { throw CocoaError(.fileNoSuchFile, userInfo: [ @@ -193,7 +203,6 @@ private func _compressContentsOfDirectory(at directoryURL: URL) async throws -> NSFilePathErrorKey: trueArchiverPath ]) } -#endif #elseif SWT_TARGET_OS_APPLE || os(FreeBSD) let archiverPath = "/usr/bin/tar" #elseif os(Windows) @@ -211,7 +220,7 @@ private func _compressContentsOfDirectory(at directoryURL: URL) async throws -> let sourcePath = directoryURL.path let destinationPath = temporaryURL.path let arguments = { -#if os(Linux) || os(OpenBSD) +#if os(Linux) || os(OpenBSD) || os(Android) // The zip command constructs relative paths from the current working // directory rather than from command-line arguments. ["-c", #"cd "$0" && "$1" "$2" --recurse-paths ."#, sourcePath, trueArchiverPath, destinationPath] diff --git a/Sources/Testing/ExitTests/ExitStatus.swift b/Sources/Testing/ExitTests/ExitStatus.swift index 21fa2335e..031348681 100644 --- a/Sources/Testing/ExitTests/ExitStatus.swift +++ b/Sources/Testing/ExitTests/ExitStatus.swift @@ -23,7 +23,10 @@ private import _TestingInternals /// @Available(Swift, introduced: 6.2) /// @Available(Xcode, introduced: 26.0) /// } -#if SWT_NO_PROCESS_SPAWNING +#if !SWT_NO_PROCESS_SPAWNING +@available(Android 28, *) +#else +@_unavailableInEmbedded @available(*, unavailable, message: "Exit tests are not available on this platform.") #endif public enum ExitStatus: Sendable { @@ -90,7 +93,10 @@ public enum ExitStatus: Sendable { // MARK: - Equatable -#if SWT_NO_PROCESS_SPAWNING +#if !SWT_NO_PROCESS_SPAWNING +@available(Android 28, *) +#else +@_unavailableInEmbedded @available(*, unavailable, message: "Exit tests are not available on this platform.") #endif extension ExitStatus: Equatable {} @@ -109,7 +115,10 @@ private let _sigabbrev_np = symbol(named: "sigabbrev_np").map { } #endif -#if SWT_NO_PROCESS_SPAWNING +#if !SWT_NO_PROCESS_SPAWNING +@available(Android 28, *) +#else +@_unavailableInEmbedded @available(*, unavailable, message: "Exit tests are not available on this platform.") #endif extension ExitStatus: CustomStringConvertible { diff --git a/Sources/Testing/ExitTests/ExitTest.CapturedValue.swift b/Sources/Testing/ExitTests/ExitTest.CapturedValue.swift index 556fc0cf6..28ce5d4d5 100644 --- a/Sources/Testing/ExitTests/ExitTest.CapturedValue.swift +++ b/Sources/Testing/ExitTests/ExitTest.CapturedValue.swift @@ -11,7 +11,9 @@ private import _TestingInternals @_spi(ForToolsIntegrationOnly) -#if SWT_NO_EXIT_TESTS +#if !SWT_NO_EXIT_TESTS +@available(Android 28, *) +#else @_unavailableInEmbedded @available(*, unavailable, message: "Exit tests are not available on this platform.") #endif diff --git a/Sources/Testing/ExitTests/ExitTest.Condition.swift b/Sources/Testing/ExitTests/ExitTest.Condition.swift index edd94193b..1d1494fbc 100644 --- a/Sources/Testing/ExitTests/ExitTest.Condition.swift +++ b/Sources/Testing/ExitTests/ExitTest.Condition.swift @@ -10,7 +10,9 @@ private import _TestingInternals -#if SWT_NO_EXIT_TESTS +#if !SWT_NO_EXIT_TESTS +@available(Android 28, *) +#else @_unavailableInEmbedded @available(*, unavailable, message: "Exit tests are not available on this platform.") #endif @@ -58,7 +60,9 @@ extension ExitTest { // MARK: - -#if SWT_NO_EXIT_TESTS +#if !SWT_NO_EXIT_TESTS +@available(Android 28, *) +#else @_unavailableInEmbedded @available(*, unavailable, message: "Exit tests are not available on this platform.") #endif @@ -178,7 +182,9 @@ extension ExitTest.Condition { // MARK: - CustomStringConvertible -#if SWT_NO_EXIT_TESTS +#if !SWT_NO_EXIT_TESTS +@available(Android 28, *) +#else @_unavailableInEmbedded @available(*, unavailable, message: "Exit tests are not available on this platform.") #endif @@ -201,7 +207,9 @@ extension ExitTest.Condition: CustomStringConvertible { // MARK: - Comparison -#if SWT_NO_EXIT_TESTS +#if !SWT_NO_EXIT_TESTS +@available(Android 28, *) +#else @_unavailableInEmbedded @available(*, unavailable, message: "Exit tests are not available on this platform.") #endif diff --git a/Sources/Testing/ExitTests/ExitTest.Result.swift b/Sources/Testing/ExitTests/ExitTest.Result.swift index 53d816c85..3c72e43ed 100644 --- a/Sources/Testing/ExitTests/ExitTest.Result.swift +++ b/Sources/Testing/ExitTests/ExitTest.Result.swift @@ -8,7 +8,9 @@ // See https://swift.org/CONTRIBUTORS.txt for Swift project authors // -#if SWT_NO_EXIT_TESTS +#if !SWT_NO_EXIT_TESTS +@available(Android 28, *) +#else @_unavailableInEmbedded @available(*, unavailable, message: "Exit tests are not available on this platform.") #endif diff --git a/Sources/Testing/ExitTests/ExitTest.swift b/Sources/Testing/ExitTests/ExitTest.swift index da4da4c91..5d7891d7b 100644 --- a/Sources/Testing/ExitTests/ExitTest.swift +++ b/Sources/Testing/ExitTests/ExitTest.swift @@ -34,7 +34,9 @@ private import _TestingInternals /// @Available(Swift, introduced: 6.2) /// @Available(Xcode, introduced: 26.0) /// } -#if SWT_NO_EXIT_TESTS +#if !SWT_NO_EXIT_TESTS +@available(Android 28, *) +#else @_unavailableInEmbedded @available(*, unavailable, message: "Exit tests are not available on this platform.") #endif @@ -223,6 +225,21 @@ extension ExitTest { // as I can tell, special-case RLIMIT_CORE=1. var rl = rlimit(rlim_cur: 0, rlim_max: 0) _ = setrlimit(RLIMIT_CORE, &rl) +#elseif os(Android) + // Android inherits the RLIMIT_CORE=1 special case from Linux. + // SEE: https://android.googlesource.com/kernel/common/+/refs/heads/android-mainline/fs/coredump.c#978 + var rl = rlimit(rlim_cur: 1, rlim_max: 1) + _ = setrlimit(RLIMIT_CORE, &rl) + + // In addition, Android installs signal handlers in native processes that + // cause the system to generate "tombstone" files. Suppress those too by + // resetting all signal handlers to SIG_DFL. debuggerd_register_handlers() + // is not exported, so we must manually walk all the signals it handles. + // SEE: https://android.googlesource.com/platform/system/core/+/main/debuggerd/include/debuggerd/handler.h#81 + let BIONIC_SIGNAL_DEBUGGER = __SIGRTMIN + 3 + for sig in [SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGSTKFLT, SIGSYS, SIGTRAP, BIONIC_SIGNAL_DEBUGGER] { + _ = signal(sig, swt_SIG_DFL()) + } #elseif os(Windows) // On Windows, similarly disable Windows Error Reporting and the Windows // Error Reporting UI. Note we expect to be the first component to call @@ -662,7 +679,7 @@ extension ExitTest { Environment.setVariable(nil, named: name) var fd: CInt? -#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) +#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) fd = CInt(environmentVariable) #elseif os(Windows) if let handle = UInt(environmentVariable).flatMap(HANDLE.init(bitPattern:)) { @@ -699,7 +716,7 @@ extension ExitTest { /// back to a (new) file handle with `_makeFileHandle()`, or `nil` if the /// file handle could not be converted to a string. private static func _makeEnvironmentVariable(for fileHandle: borrowing FileHandle) -> String? { -#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) +#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) return fileHandle.withUnsafePOSIXFileDescriptor { fd in fd.map(String.init(describing:)) } diff --git a/Sources/Testing/ExitTests/SpawnProcess.swift b/Sources/Testing/ExitTests/SpawnProcess.swift index 6114566f1..04d0ec358 100644 --- a/Sources/Testing/ExitTests/SpawnProcess.swift +++ b/Sources/Testing/ExitTests/SpawnProcess.swift @@ -17,7 +17,7 @@ internal import _TestingInternals /// A platform-specific value identifying a process running on the current /// system. -#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) +#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) typealias ProcessID = pid_t #elseif os(Windows) typealias ProcessID = HANDLE @@ -62,6 +62,7 @@ private let _posix_spawn_file_actions_addclosefrom_np = symbol(named: "posix_spa /// resources. /// /// - Throws: Any error that prevented the process from spawning. +@available(Android 28, *) func spawnExecutable( atPath executablePath: String, arguments: [String], @@ -71,15 +72,16 @@ func spawnExecutable( standardError: borrowing FileHandle? = nil, additionalFileHandles: [UnsafePointer] = [] ) throws -> ProcessID { - // Darwin and Linux differ in their optionality for the posix_spawn types we - // use, so use this typealias to paper over the differences. + // Darwin, the BSDs, Linux, and Android all differ in their optionality for + // the posix_spawn types we use, so use this typealias and helper function to + // paper over the differences. #if SWT_TARGET_OS_APPLE || os(FreeBSD) || os(OpenBSD) typealias P = T? -#elseif os(Linux) +#elseif os(Linux) || os(Android) typealias P = T #endif -#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) +#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) return try withUnsafeTemporaryAllocation(of: P.self, capacity: 1) { fileActions in let fileActions = fileActions.baseAddress! let fileActionsInitialized = posix_spawn_file_actions_init(fileActions) @@ -92,7 +94,13 @@ func spawnExecutable( return try withUnsafeTemporaryAllocation(of: P.self, capacity: 1) { attrs in let attrs = attrs.baseAddress! +#if os(Android) + let attrsInitialized = attrs.withMemoryRebound(to: posix_spawnattr_t?.self, capacity: 1) { attrs in + posix_spawnattr_init(attrs) + } +#else let attrsInitialized = posix_spawnattr_init(attrs) +#endif guard 0 == attrsInitialized else { throw CError(rawValue: attrsInitialized) } @@ -194,6 +202,9 @@ func spawnExecutable( // spawned child process if we control its execution. var environment = environment environment["SWT_CLOSEFROM"] = String(describing: highestFD + 1) +#elseif os(Android) + // Android does not have posix_spawn_file_actions_addclosefrom_np() nor + // closefrom(2), so we don't attempt this operation there. #else #warning("Platform-specific implementation missing: cannot close unused file descriptors") #endif @@ -225,7 +236,11 @@ func spawnExecutable( } var pid = pid_t() +#if os(Android) + let processSpawned = swt_posix_spawn(&pid, executablePath, fileActions, attrs, argv, environ) +#else let processSpawned = posix_spawn(&pid, executablePath, fileActions, attrs, argv, environ) +#endif guard 0 == processSpawned else { throw CError(rawValue: processSpawned) } @@ -463,6 +478,7 @@ private func _escapeCommandLine(_ arguments: [String]) -> String { /// This function is a convenience that spawns the given process and waits for /// it to terminate. It is primarily for use by other targets in this package /// such as its cross-import overlays. +@available(Android 28, *) package func spawnExecutableAtPathAndWait( _ executablePath: String, arguments: [String] = [], diff --git a/Sources/Testing/ExitTests/WaitFor.swift b/Sources/Testing/ExitTests/WaitFor.swift index f0326ff3c..cdf0e500d 100644 --- a/Sources/Testing/ExitTests/WaitFor.swift +++ b/Sources/Testing/ExitTests/WaitFor.swift @@ -11,7 +11,7 @@ #if !SWT_NO_PROCESS_SPAWNING internal import _TestingInternals -#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) +#if SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) /// Block the calling thread, wait for the target process to exit, and return /// a value describing the conditions under which it exited. /// @@ -29,9 +29,9 @@ private func _blockAndWait(for pid: consuming pid_t) throws -> ExitStatus { if 0 == waitid(P_PID, id_t(pid), &siginfo, WEXITED) { switch siginfo.si_code { case .init(CLD_EXITED): - return .exitCode(siginfo.si_status) + return .exitCode(swt_siginfo_t_si_status(siginfo)) case .init(CLD_KILLED), .init(CLD_DUMPED): - return .signal(siginfo.si_status) + return .signal(swt_siginfo_t_si_status(siginfo)) default: throw SystemError(description: "Unexpected siginfo_t value. Please file a bug report at https://github.com/swiftlang/swift-testing/issues/new and include this information: \(String(reflecting: siginfo))") } @@ -78,7 +78,7 @@ func wait(for pid: consuming pid_t) async throws -> ExitStatus { return try _blockAndWait(for: pid) } -#elseif SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) +#elseif SWT_TARGET_OS_APPLE || os(Linux) || os(FreeBSD) || os(OpenBSD) || os(Android) /// A mapping of awaited child PIDs to their corresponding Swift continuations. private nonisolated(unsafe) let _childProcessContinuations = { let result = ManagedBuffer<[pid_t: CheckedContinuation], pthread_mutex_t>.create( @@ -146,7 +146,7 @@ private let _createWaitThread: Void = { // continuation (if available) before reaping. var siginfo = siginfo_t() if 0 == waitid(P_ALL, 0, &siginfo, WEXITED | WNOWAIT) { - if case let pid = siginfo.si_pid, pid != 0 { + if case let pid = swt_siginfo_t_si_pid(siginfo), pid != 0 { let continuation = _withLockedChildProcessContinuations { childProcessContinuations, _ in childProcessContinuations.removeValue(forKey: pid) } @@ -189,8 +189,9 @@ private let _createWaitThread: Void = { { _ in // Set the thread name to help with diagnostics. Note that different // platforms support different thread name lengths. See MAXTHREADNAMESIZE - // on Darwin, TASK_COMM_LEN on Linux, MAXCOMLEN on FreeBSD, and _MAXCOMLEN - // on OpenBSD. We try to maximize legibility in the available space. + // on Darwin, TASK_COMM_LEN on Linux, MAXCOMLEN on FreeBSD, _MAXCOMLEN on + // OpenBSD, and MAX_TASK_COMM_LEN on Android. We try to maximize + // legibility in the available space. #if SWT_TARGET_OS_APPLE _ = pthread_setname_np("Swift Testing exit test monitor") #elseif os(Linux) @@ -201,6 +202,8 @@ private let _createWaitThread: Void = { pthread_set_name_np(pthread_self(), "SWT ex test monitor") #elseif os(OpenBSD) pthread_set_name_np(pthread_self(), "SWT exit test monitor") +#elseif os(Android) + _ = pthread_setname_np(pthread_self(), "SWT ExT monitor") #else #warning("Platform-specific implementation missing: thread naming unavailable") #endif @@ -233,6 +236,7 @@ private let _createWaitThread: Void = { /// /// On Apple platforms, the libdispatch-based implementation above is more /// efficient because it does not need to permanently reserve a thread. +@available(Android 28, *) func wait(for pid: consuming pid_t) async throws -> ExitStatus { let pid = consume pid diff --git a/Sources/Testing/Expectations/Expectation+Macro.swift b/Sources/Testing/Expectations/Expectation+Macro.swift index ea007f667..281f8259d 100644 --- a/Sources/Testing/Expectations/Expectation+Macro.swift +++ b/Sources/Testing/Expectations/Expectation+Macro.swift @@ -876,7 +876,9 @@ public macro require( /// } @freestanding(expression) @discardableResult -#if SWT_NO_EXIT_TESTS +#if !SWT_NO_EXIT_TESTS +@available(Android 28, *) +#else @_unavailableInEmbedded @available(*, unavailable, message: "Exit tests are not available on this platform.") #endif @@ -924,7 +926,9 @@ public macro expect( /// } @freestanding(expression) @discardableResult -#if SWT_NO_EXIT_TESTS +#if !SWT_NO_EXIT_TESTS +@available(Android 28, *) +#else @_unavailableInEmbedded @available(*, unavailable, message: "Exit tests are not available on this platform.") #endif diff --git a/Sources/_TestingInternals/include/Stubs.h b/Sources/_TestingInternals/include/Stubs.h index 636ea9aff..1f02128a3 100644 --- a/Sources/_TestingInternals/include/Stubs.h +++ b/Sources/_TestingInternals/include/Stubs.h @@ -126,28 +126,49 @@ static char *_Nullable *_Null_unspecified swt_environ(void) { } #endif -#if !defined(__ANDROID__) -#if __has_include() && defined(si_pid) +#if !SWT_NO_PROCESS_SPAWNING && __has_include() +#if defined(__APPLE__) || defined(si_pid) /// Get the value of the `si_pid` field of a `siginfo_t` structure. /// /// This function is provided because `si_pid` is a complex macro on some -/// platforms and cannot be imported directly into Swift. It is renamed back to -/// `siginfo_t.si_pid` in Swift. -SWT_SWIFT_NAME(getter:siginfo_t.si_pid(self:)) -static pid_t swt_siginfo_t_si_pid(const siginfo_t *siginfo) { - return siginfo->si_pid; +/// platforms and cannot be imported directly into Swift. +static pid_t swt_siginfo_t_si_pid(siginfo_t siginfo) { + return siginfo.si_pid; } #endif -#if __has_include() && defined(si_status) +#if defined(__APPLE__) || defined(si_status) /// Get the value of the `si_status` field of a `siginfo_t` structure. /// /// This function is provided because `si_status` is a complex macro on some -/// platforms and cannot be imported directly into Swift. It is renamed back to -/// `siginfo_t.si_status` in Swift. -SWT_SWIFT_NAME(getter:siginfo_t.si_status(self:)) -static int swt_siginfo_t_si_status(const siginfo_t *siginfo) { - return siginfo->si_status; +/// platforms and cannot be imported directly into Swift. +static int swt_siginfo_t_si_status(siginfo_t siginfo) { + return siginfo.si_status; +} +#endif + +#if __has_include() && !defined(__wasi__) +/// Get the default signal handler. +/// +/// This function is provided because `SIG_DFL` is a complex macro on some +/// platforms and cannot be imported directly into Swift. +static __typeof__(SIG_DFL) _Null_unspecified swt_SIG_DFL(void) { + return SIG_DFL; +} +#endif + +#if defined(__ANDROID__) +/// Call `posix_spawn(3)`. +/// +/// This function is provided because the nullability for `posix_spawn(3)` is +/// incorrectly specified in the Android NDK. +static int swt_posix_spawn( + pid_t *_Nullable pid, const char *path, + const posix_spawn_file_actions_t _Nonnull *_Nullable fileActions, + const posix_spawnattr_t _Nonnull *_Nullable attrs, + char *const _Nullable argv[_Nonnull], char *const _Nullable env[_Nonnull] +) { + return posix_spawn(pid, path, fileActions, attrs, argv, env); } #endif #endif diff --git a/cmake/modules/shared/CompilerSettings.cmake b/cmake/modules/shared/CompilerSettings.cmake index b3c0fe3aa..cd961f6de 100644 --- a/cmake/modules/shared/CompilerSettings.cmake +++ b/cmake/modules/shared/CompilerSettings.cmake @@ -26,11 +26,11 @@ add_compile_options( if(APPLE) add_compile_definitions("SWT_TARGET_OS_APPLE") endif() -set(SWT_NO_EXIT_TESTS_LIST "iOS" "watchOS" "tvOS" "visionOS" "WASI" "Android") +set(SWT_NO_EXIT_TESTS_LIST "iOS" "watchOS" "tvOS" "visionOS" "WASI") if(CMAKE_SYSTEM_NAME IN_LIST SWT_NO_EXIT_TESTS_LIST) add_compile_definitions("SWT_NO_EXIT_TESTS") endif() -set(SWT_NO_PROCESS_SPAWNING_LIST "iOS" "watchOS" "tvOS" "visionOS" "WASI" "Android") +set(SWT_NO_PROCESS_SPAWNING_LIST "iOS" "watchOS" "tvOS" "visionOS" "WASI") if(CMAKE_SYSTEM_NAME IN_LIST SWT_NO_PROCESS_SPAWNING_LIST) add_compile_definitions("SWT_NO_PROCESS_SPAWNING") endif() diff --git a/foo.txt b/foo.txt new file mode 100644 index 000000000..e5e3b6e74 --- /dev/null +++ b/foo.txt @@ -0,0 +1,2 @@ +int posix_spawn(pid_t* _Nullable __pid, const char* _Nonnull __path, const posix_spawn_file_actions_t _Nullable * _Nullable __actions, const posix_spawnattr_t _Nullable * _Nullable __attr, char* const _Nonnull __argv[_Nonnull], char* const _Nullable __env[_Nullable]) __INTRODUCED_IN(28); +int posix_spawnp(pid_t* _Nullable __pid, const char* _Nonnull __file, const posix_spawn_file_actions_t _Nullable * _Nullable __actions, const posix_spawnattr_t _Nullable * _Nullable __attr, char* const _Nonnull __argv[_Nonnull], char* const _Nullable __env[_Nullable]) __INTRODUCED_IN(28);