diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 20d4ceeed..af8963858 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -24,11 +24,18 @@ jobs: - name: Run Tests run: CI=1 ./scripts/all-tests.sh "${{ matrix.environment }}" + linux: + name: "Test (Android)" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: "Test Swift Package on Android" + uses: skiptools/swift-android-action@v2 + # We're having some issues with the Linux tests, so we're disabling them for now. # Hopefully we'll be able to fix and re-enable them soon. # Even more hopefully that I won't git blame this comment in the future and see it was 5 years ago :) # Some more info on part of the breakage is here: https://forums.swift.org/t/swift-6-0-regression-cannot-inherit-from-some-foundation-classes-on-linux-because-it-has-overridable-members-that-could-not-be-loaded/74794 - # linux: # name: "Test (Linux)" # runs-on: ubuntu-latest @@ -36,4 +43,5 @@ jobs: # steps: # - uses: actions/checkout@v3 # - name: Run tests - # run: CI=1 ./scripts/all-tests.sh "Unix" \ No newline at end of file + # run: CI=1 ./scripts/all-tests.sh "Unix" + diff --git a/.swiftformat b/.swiftformat index 93777b0da..ef7da1df4 100644 --- a/.swiftformat +++ b/.swiftformat @@ -1,3 +1,3 @@ --ifdef no-indent --wrap-arguments before-first ---exclude Sources/AllTestz/main.swift \ No newline at end of file +--exclude Sources/AllTestz/main.swift,RxTest/HotObservable.swift,Tests/RxSwiftTests/BagTest.swift \ No newline at end of file diff --git a/Package.swift b/Package.swift index ebc51712f..71f81745d 100644 --- a/Package.swift +++ b/Package.swift @@ -1,8 +1,24 @@ // swift-tools-version:5.5 +import Foundation import PackageDescription +func isTargetingDarwin() -> Bool { + // Check if building for Android or other non-Darwin platforms + if (ProcessInfo.processInfo.environment["ANDROID_DATA"] != nil) || + (ProcessInfo.processInfo.environment["ANDROID_ROOT"] != nil) { + return false + } + + #if canImport(Darwin) + return true + #else + return false + #endif +} + let buildTests = false +let targetsDarwin = isTargetingDarwin() extension Product { static func allTests() -> [Product] { @@ -12,6 +28,17 @@ extension Product { [] } } + + static func rxCocoaProducts() -> [Product] { + if targetsDarwin { + return [ + .library(name: "RxCocoa", targets: ["RxCocoa"]), + .library(name: "RxCocoa-Dynamic", type: .dynamic, targets: ["RxCocoa"]), + ] + } else { + return [] + } + } } extension Target { @@ -26,19 +53,35 @@ extension Target { extension Target { static func rxCocoa() -> [Target] { - #if os(Linux) - return [.rxTarget(name: "RxCocoa", dependencies: ["RxSwift", "RxRelay"])] - #else - return [.rxTarget(name: "RxCocoa", dependencies: ["RxSwift", "RxRelay", "RxCocoaRuntime"])] - #endif + if !targetsDarwin { + return [] + } else { + return [ + .target( + name: "RxCocoa", + dependencies: [ + "RxSwift", + "RxRelay", + .target(name: "RxCocoaRuntime", condition: .when(platforms: [.iOS, .macOS, .tvOS, .watchOS])) + ], + resources: [.copy("PrivacyInfo.xcprivacy")] + ) + ] + } } static func rxCocoaRuntime() -> [Target] { - #if os(Linux) - return [] - #else - return [.rxTarget(name: "RxCocoaRuntime", dependencies: ["RxSwift"])] - #endif + if !targetsDarwin { + return [] + } else { + return [ + .target( + name: "RxCocoaRuntime", + dependencies: ["RxSwift"], + resources: [.copy("PrivacyInfo.xcprivacy")] + ) + ] + } } static func allTests() -> [Target] { @@ -56,16 +99,15 @@ let package = Package( products: ([ [ .library(name: "RxSwift", targets: ["RxSwift"]), - .library(name: "RxCocoa", targets: ["RxCocoa"]), .library(name: "RxRelay", targets: ["RxRelay"]), .library(name: "RxBlocking", targets: ["RxBlocking"]), .library(name: "RxTest", targets: ["RxTest"]), .library(name: "RxSwift-Dynamic", type: .dynamic, targets: ["RxSwift"]), - .library(name: "RxCocoa-Dynamic", type: .dynamic, targets: ["RxCocoa"]), .library(name: "RxRelay-Dynamic", type: .dynamic, targets: ["RxRelay"]), .library(name: "RxBlocking-Dynamic", type: .dynamic, targets: ["RxBlocking"]), .library(name: "RxTest-Dynamic", type: .dynamic, targets: ["RxTest"]), ], + Product.rxCocoaProducts(), Product.allTests(), ] as [[Product]]).flatMap(\.self), targets: ([ diff --git a/Package@swift-5.9.swift b/Package@swift-5.9.swift index d3ec95b02..9a5fc1659 100644 --- a/Package@swift-5.9.swift +++ b/Package@swift-5.9.swift @@ -1,8 +1,24 @@ // swift-tools-version:5.9 +import Foundation import PackageDescription +func isTargetingDarwin() -> Bool { + // Check if building for Android or other non-Darwin platforms + if (ProcessInfo.processInfo.environment["ANDROID_DATA"] != nil) || + (ProcessInfo.processInfo.environment["ANDROID_ROOT"] != nil) { + return false + } + + #if canImport(Darwin) + return true + #else + return false + #endif +} + let buildTests = false +let targetsDarwin = isTargetingDarwin() extension Product { static func allTests() -> [Product] { @@ -12,6 +28,17 @@ extension Product { [] } } + + static func rxCocoaProducts() -> [Product] { + if targetsDarwin { + return [ + .library(name: "RxCocoa", targets: ["RxCocoa"]), + .library(name: "RxCocoa-Dynamic", type: .dynamic, targets: ["RxCocoa"]), + ] + } else { + return [] + } + } } extension Target { @@ -26,19 +53,35 @@ extension Target { extension Target { static func rxCocoa() -> [Target] { - #if os(Linux) - return [.rxTarget(name: "RxCocoa", dependencies: ["RxSwift", "RxRelay"])] - #else - return [.rxTarget(name: "RxCocoa", dependencies: ["RxSwift", "RxRelay", "RxCocoaRuntime"])] - #endif + if !targetsDarwin { + return [] + } else { + return [ + .target( + name: "RxCocoa", + dependencies: [ + "RxSwift", + "RxRelay", + .target(name: "RxCocoaRuntime", condition: .when(platforms: [.iOS, .macCatalyst, .macOS, .tvOS, .watchOS, .visionOS])) + ], + resources: [.copy("PrivacyInfo.xcprivacy")] + ) + ] + } } static func rxCocoaRuntime() -> [Target] { - #if os(Linux) - return [] - #else - return [.rxTarget(name: "RxCocoaRuntime", dependencies: ["RxSwift"])] - #endif + if !targetsDarwin { + return [] + } else { + return [ + .target( + name: "RxCocoaRuntime", + dependencies: ["RxSwift"], + resources: [.copy("PrivacyInfo.xcprivacy")] + ) + ] + } } static func allTests() -> [Target] { @@ -56,16 +99,15 @@ let package = Package( products: ([ [ .library(name: "RxSwift", targets: ["RxSwift"]), - .library(name: "RxCocoa", targets: ["RxCocoa"]), .library(name: "RxRelay", targets: ["RxRelay"]), .library(name: "RxBlocking", targets: ["RxBlocking"]), .library(name: "RxTest", targets: ["RxTest"]), .library(name: "RxSwift-Dynamic", type: .dynamic, targets: ["RxSwift"]), - .library(name: "RxCocoa-Dynamic", type: .dynamic, targets: ["RxCocoa"]), .library(name: "RxRelay-Dynamic", type: .dynamic, targets: ["RxRelay"]), .library(name: "RxBlocking-Dynamic", type: .dynamic, targets: ["RxBlocking"]), .library(name: "RxTest-Dynamic", type: .dynamic, targets: ["RxTest"]), ], + Product.rxCocoaProducts(), Product.allTests(), ] as [[Product]]).flatMap(\.self), targets: ([ diff --git a/Platform/Platform.Darwin.swift b/Platform/Platform.Darwin.swift index 370b73065..26771ab7e 100644 --- a/Platform/Platform.Darwin.swift +++ b/Platform/Platform.Darwin.swift @@ -6,7 +6,7 @@ // Copyright © 2015 Krunoslav Zaher. All rights reserved. // -#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) || os(visionOS) +#if canImport(Darwin) import Darwin import Foundation diff --git a/Platform/Platform.Linux.swift b/Platform/Platform.Linux.swift index 379a45a98..7a9856629 100644 --- a/Platform/Platform.Linux.swift +++ b/Platform/Platform.Linux.swift @@ -6,7 +6,7 @@ // Copyright © 2015 Krunoslav Zaher. All rights reserved. // -#if os(Linux) +#if !canImport(Darwin) import Foundation diff --git a/RxBlocking/RunLoopLock.swift b/RxBlocking/RunLoopLock.swift index 0943f623e..dbe747c8f 100644 --- a/RxBlocking/RunLoopLock.swift +++ b/RxBlocking/RunLoopLock.swift @@ -10,7 +10,7 @@ import CoreFoundation import Foundation import RxSwift -#if os(Linux) +#if !canImport(Darwin) import Foundation let runLoopMode: RunLoop.Mode = .default @@ -61,7 +61,7 @@ final class RunLoopLock { fatalError("Run can be only called once") } if let timeout { - #if os(Linux) + #if !canImport(Darwin) let runLoopResult = CFRunLoopRunInMode(runLoopModeRaw, timeout, false) #else let runLoopResult = CFRunLoopRunInMode(runLoopMode, timeout, false) diff --git a/RxCocoa/Foundation/URLSession+Rx.swift b/RxCocoa/Foundation/URLSession+Rx.swift index 5cbbb3ce6..2e7b48d49 100644 --- a/RxCocoa/Foundation/URLSession+Rx.swift +++ b/RxCocoa/Foundation/URLSession+Rx.swift @@ -122,7 +122,7 @@ public extension Reactive where Base: URLSession { if URLSession.rx.shouldLogRequest(request) { let interval = Date().timeIntervalSince(d ?? Date()) print(convertURLRequestToCurlCommand(request)) - #if os(Linux) + #if !canImport(Darwin) print(convertResponseToString(response, error.flatMap { $0 as NSError }, interval)) #else print(convertResponseToString(response, error.map { $0 as NSError }, interval)) diff --git a/RxCocoa/Traits/SharedSequence/SchedulerType+SharedSequence.swift b/RxCocoa/Traits/SharedSequence/SchedulerType+SharedSequence.swift index d6ac33ad6..0bbc8de48 100644 --- a/RxCocoa/Traits/SharedSequence/SchedulerType+SharedSequence.swift +++ b/RxCocoa/Traits/SharedSequence/SchedulerType+SharedSequence.swift @@ -43,7 +43,7 @@ public enum SharingScheduler { } } -#if os(Linux) +#if !canImport(Darwin) import Glibc #else import Foundation @@ -51,7 +51,7 @@ import Foundation func _forceCompilerToStopDoingInsaneOptimizationsThatBreakCode(_ scheduler: () -> SchedulerType) { let a: Int32 = 1 - #if os(Linux) + #if !canImport(Darwin) let b = 314 + Int32(Glibc.random() & 1) #else let b = 314 + Int32(arc4random() & 1) diff --git a/RxSwift/RxMutableBox.swift b/RxSwift/RxMutableBox.swift index 4e07a7ce0..47551b89b 100644 --- a/RxSwift/RxMutableBox.swift +++ b/RxSwift/RxMutableBox.swift @@ -6,12 +6,12 @@ // Copyright © 2015 Krunoslav Zaher. All rights reserved. // -#if os(Linux) +#if !canImport(Darwin) /// As Swift 5 was released, A patch to `Thread` for Linux /// changed `threadDictionary` to a `NSMutableDictionary` instead of /// a `Dictionary`: https://github.com/apple/swift-corelibs-foundation/pull/1762/files /// -/// This means that on Linux specifically, `RxMutableBox` must be a `NSObject` +/// This means that on non-Darwin platforms (Linux, Android, etc.), `RxMutableBox` must be a `NSObject` /// or it won't be possible to store it in `Thread.threadDictionary`. /// /// For more information, read the discussion at: diff --git a/RxSwift/Schedulers/CurrentThreadScheduler.swift b/RxSwift/Schedulers/CurrentThreadScheduler.swift index 81ac93148..8d526e216 100644 --- a/RxSwift/Schedulers/CurrentThreadScheduler.swift +++ b/RxSwift/Schedulers/CurrentThreadScheduler.swift @@ -9,7 +9,7 @@ import Dispatch import Foundation -#if os(Linux) +#if !canImport(Darwin) fileprivate enum CurrentThreadSchedulerQueueKey { fileprivate static let instance = "RxSwift.CurrentThreadScheduler.Queue" } diff --git a/RxTest/Event+Equatable.swift b/RxTest/Event+Equatable.swift index eabf8910d..cda88f276 100644 --- a/RxTest/Event+Equatable.swift +++ b/RxTest/Event+Equatable.swift @@ -88,7 +88,7 @@ func equals(lhs: MaybeEvent, rhs: MaybeEvent Bool { switch (lhs, rhs) { case (.completed, .completed): return true @@ -108,13 +108,13 @@ extension CompletableEvent: @retroactive Equatable { } } -extension Event: @retroactive Equatable where Element: Equatable { +extension Event: Equatable where Element: Equatable { public static func == (lhs: Event, rhs: Event) -> Bool { equals(lhs: lhs, rhs: rhs) } } -extension MaybeEvent: @retroactive Equatable where Element: Equatable { +extension MaybeEvent: Equatable where Element: Equatable { public static func == (lhs: MaybeEvent, rhs: MaybeEvent) -> Bool { equals(lhs: lhs, rhs: rhs) }