Skip to content

Commit 946f29a

Browse files
finagolfinaciidgh
authored andcommitted
Android: add native platform support (#2396)
* Android: add host platform support * Android: add some build platform support
1 parent 6444c13 commit 946f29a

File tree

18 files changed

+106
-42
lines changed

18 files changed

+106
-42
lines changed

Fixtures/Miscellaneous/EchoExecutable/Sources/secho/main.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#if os(Linux)
1+
#if canImport(Glibc)
22
import Glibc
33
#else
44
import Darwin.C

Sources/Build/BuildPlan.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ public struct BuildParameters: Encodable {
234234
var currentPlatform: PackageModel.Platform {
235235
if self.triple.isDarwin() {
236236
return .macOS
237+
} else if self.triple.isAndroid() {
238+
return .android
237239
} else {
238240
return .linux
239241
}

Sources/Build/Triple.swift

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ public struct Triple: Encodable {
101101
return nil
102102
}
103103

104+
public func isAndroid() -> Bool {
105+
return os == .linux && abi == .android
106+
}
107+
104108
public func isDarwin() -> Bool {
105109
return vendor == .apple || os == .macOS || os == .darwin
106110
}
@@ -128,7 +132,10 @@ public struct Triple: Encodable {
128132
public static let s390xLinux = try! Triple("s390x-unknown-linux")
129133
public static let arm64Linux = try! Triple("aarch64-unknown-linux")
130134
public static let armLinux = try! Triple("armv7-unknown-linux-gnueabihf")
131-
public static let android = try! Triple("armv7-unknown-linux-androideabi")
135+
public static let armAndroid = try! Triple("armv7a-unknown-linux-androideabi")
136+
public static let arm64Android = try! Triple("aarch64-unknown-linux-android")
137+
public static let x86_64Android = try! Triple("x86_64-unknown-linux-android")
138+
public static let i686Android = try! Triple("i686-unknown-linux-android")
132139
public static let windows = try! Triple("x86_64-unknown-windows-msvc")
133140

134141
#if os(macOS)
@@ -149,6 +156,16 @@ public struct Triple: Encodable {
149156
#elseif arch(arm)
150157
public static let hostTriple: Triple = .armLinux
151158
#endif
159+
#elseif os(Android)
160+
#if arch(arm)
161+
public static let hostTriple: Triple = .armAndroid
162+
#elseif arch(arm64)
163+
public static let hostTriple: Triple = .arm64Android
164+
#elseif arch(x86_64)
165+
public static let hostTriple: Triple = .x86_64Android
166+
#elseif arch(i386)
167+
public static let hostTriple: Triple = .i686Android
168+
#endif
152169
#endif
153170
}
154171

Sources/Commands/SwiftTool.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,12 @@ public class SwiftTool<Options: ToolOptions> {
375375
action.__sigaction_u.__sa_handler = SIG_DFL
376376
sigaction(SIGINT, &action, nil)
377377
kill(getpid(), SIGINT)
378+
#elseif os(Android)
379+
// Install the default signal handler.
380+
var action = sigaction()
381+
action.sa_handler = SIG_DFL
382+
sigaction(SIGINT, &action, nil)
383+
kill(getpid(), SIGINT)
378384
#else
379385
var action = sigaction()
380386
action.__sigaction_handler = unsafeBitCast(

Sources/PackageDescription4/Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
99
*/
1010

11-
#if os(Linux)
11+
#if canImport(Glibc)
1212
import Glibc
1313
#elseif os(iOS) || os(macOS) || os(tvOS) || os(watchOS)
1414
import Darwin.C

Sources/PackageDescription4/SupportedPlatforms.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ public struct Platform: Encodable {
3737
/// The Windows platform
3838
@available(_PackageDescription, introduced: 5.2)
3939
public static let windows: Platform = Platform(name: "windows")
40+
41+
/// The Android platform
42+
@available(_PackageDescription, introduced: 5.2)
43+
public static let android: Platform = Platform(name: "android")
4044
}
4145

4246
/// A platform that the Swift package supports.

Sources/PackageModel/Platform.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public final class PlatformRegistry {
2929

3030
/// The static list of known platforms.
3131
private static var _knownPlatforms: [Platform] {
32-
return [.macOS, .iOS, .tvOS, .watchOS, .linux]
32+
return [.macOS, .iOS, .tvOS, .watchOS, .linux, .android]
3333
}
3434
}
3535

@@ -55,6 +55,7 @@ public struct Platform: Equatable, Hashable {
5555
public static let tvOS: Platform = Platform(name: "tvos", oldestSupportedVersion: "9.0")
5656
public static let watchOS: Platform = Platform(name: "watchos", oldestSupportedVersion: "2.0")
5757
public static let linux: Platform = Platform(name: "linux", oldestSupportedVersion: .unknown)
58+
public static let android: Platform = Platform(name: "android", oldestSupportedVersion: .unknown)
5859
}
5960

6061
/// Represents a platform version.

Sources/TSCBasic/Process.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ public final class Process: ObjectIdentifierProtocol {
312312
try _process?.run()
313313
#else
314314
// Initialize the spawn attributes.
315-
#if canImport(Darwin)
315+
#if canImport(Darwin) || os(Android)
316316
var attributes: posix_spawnattr_t? = nil
317317
#else
318318
var attributes = posix_spawnattr_t()
@@ -357,7 +357,7 @@ public final class Process: ObjectIdentifierProtocol {
357357
posix_spawnattr_setflags(&attributes, Int16(flags))
358358

359359
// Setup the file actions.
360-
#if canImport(Darwin)
360+
#if canImport(Darwin) || os(Android)
361361
var fileActions: posix_spawn_file_actions_t? = nil
362362
#else
363363
var fileActions = posix_spawn_file_actions_t()

Sources/TSCLibc/libc.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
99
*/
1010

11-
#if os(Linux)
11+
#if canImport(Glibc)
1212
@_exported import Glibc
1313
#elseif os(Windows)
1414
@_exported import MSVCRT

Sources/TSCUtility/FSWatch.swift

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -428,55 +428,76 @@ public final class Inotify {
428428
// FIXME: <rdar://problem/45794219> Swift should provide shims for FD_ macros
429429

430430
private func FD_ZERO(_ set: inout fd_set) {
431+
#if os(Android)
432+
set.fds_bits = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
433+
#else
431434
set.__fds_bits = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
435+
#endif
432436
}
433437

434438
private func FD_SET(_ fd: Int32, _ set: inout fd_set) {
435439
let intOffset = Int(fd / 16)
436440
let bitOffset = Int(fd % 16)
441+
#if os(Android)
442+
var fd_bits = set.fds_bits
443+
let mask: UInt = 1 << bitOffset
444+
#else
445+
var fd_bits = set.__fds_bits
437446
let mask = 1 << bitOffset
447+
#endif
438448
switch intOffset {
439-
case 0: set.__fds_bits.0 = set.__fds_bits.0 | mask
440-
case 1: set.__fds_bits.1 = set.__fds_bits.1 | mask
441-
case 2: set.__fds_bits.2 = set.__fds_bits.2 | mask
442-
case 3: set.__fds_bits.3 = set.__fds_bits.3 | mask
443-
case 4: set.__fds_bits.4 = set.__fds_bits.4 | mask
444-
case 5: set.__fds_bits.5 = set.__fds_bits.5 | mask
445-
case 6: set.__fds_bits.6 = set.__fds_bits.6 | mask
446-
case 7: set.__fds_bits.7 = set.__fds_bits.7 | mask
447-
case 8: set.__fds_bits.8 = set.__fds_bits.8 | mask
448-
case 9: set.__fds_bits.9 = set.__fds_bits.9 | mask
449-
case 10: set.__fds_bits.10 = set.__fds_bits.10 | mask
450-
case 11: set.__fds_bits.11 = set.__fds_bits.11 | mask
451-
case 12: set.__fds_bits.12 = set.__fds_bits.12 | mask
452-
case 13: set.__fds_bits.13 = set.__fds_bits.13 | mask
453-
case 14: set.__fds_bits.14 = set.__fds_bits.14 | mask
454-
case 15: set.__fds_bits.15 = set.__fds_bits.15 | mask
449+
case 0: fd_bits.0 = fd_bits.0 | mask
450+
case 1: fd_bits.1 = fd_bits.1 | mask
451+
case 2: fd_bits.2 = fd_bits.2 | mask
452+
case 3: fd_bits.3 = fd_bits.3 | mask
453+
case 4: fd_bits.4 = fd_bits.4 | mask
454+
case 5: fd_bits.5 = fd_bits.5 | mask
455+
case 6: fd_bits.6 = fd_bits.6 | mask
456+
case 7: fd_bits.7 = fd_bits.7 | mask
457+
case 8: fd_bits.8 = fd_bits.8 | mask
458+
case 9: fd_bits.9 = fd_bits.9 | mask
459+
case 10: fd_bits.10 = fd_bits.10 | mask
460+
case 11: fd_bits.11 = fd_bits.11 | mask
461+
case 12: fd_bits.12 = fd_bits.12 | mask
462+
case 13: fd_bits.13 = fd_bits.13 | mask
463+
case 14: fd_bits.14 = fd_bits.14 | mask
464+
case 15: fd_bits.15 = fd_bits.15 | mask
455465
default: break
456466
}
467+
#if os(Android)
468+
set.fds_bits = fd_bits
469+
#else
470+
set.__fds_bits = fd_bits
471+
#endif
457472
}
458473

459474
private func FD_ISSET(_ fd: Int32, _ set: inout fd_set) -> Bool {
460475
let intOffset = Int(fd / 32)
461476
let bitOffset = Int(fd % 32)
477+
#if os(Android)
478+
let fd_bits = set.fds_bits
479+
let mask: UInt = 1 << bitOffset
480+
#else
481+
let fd_bits = set.__fds_bits
462482
let mask = 1 << bitOffset
483+
#endif
463484
switch intOffset {
464-
case 0: return set.__fds_bits.0 & mask != 0
465-
case 1: return set.__fds_bits.1 & mask != 0
466-
case 2: return set.__fds_bits.2 & mask != 0
467-
case 3: return set.__fds_bits.3 & mask != 0
468-
case 4: return set.__fds_bits.4 & mask != 0
469-
case 5: return set.__fds_bits.5 & mask != 0
470-
case 6: return set.__fds_bits.6 & mask != 0
471-
case 7: return set.__fds_bits.7 & mask != 0
472-
case 8: return set.__fds_bits.8 & mask != 0
473-
case 9: return set.__fds_bits.9 & mask != 0
474-
case 10: return set.__fds_bits.10 & mask != 0
475-
case 11: return set.__fds_bits.11 & mask != 0
476-
case 12: return set.__fds_bits.12 & mask != 0
477-
case 13: return set.__fds_bits.13 & mask != 0
478-
case 14: return set.__fds_bits.14 & mask != 0
479-
case 15: return set.__fds_bits.15 & mask != 0
485+
case 0: return fd_bits.0 & mask != 0
486+
case 1: return fd_bits.1 & mask != 0
487+
case 2: return fd_bits.2 & mask != 0
488+
case 3: return fd_bits.3 & mask != 0
489+
case 4: return fd_bits.4 & mask != 0
490+
case 5: return fd_bits.5 & mask != 0
491+
case 6: return fd_bits.6 & mask != 0
492+
case 7: return fd_bits.7 & mask != 0
493+
case 8: return fd_bits.8 & mask != 0
494+
case 9: return fd_bits.9 & mask != 0
495+
case 10: return fd_bits.10 & mask != 0
496+
case 11: return fd_bits.11 & mask != 0
497+
case 12: return fd_bits.12 & mask != 0
498+
case 13: return fd_bits.13 & mask != 0
499+
case 14: return fd_bits.14 & mask != 0
500+
case 15: return fd_bits.15 & mask != 0
480501
default: return false
481502
}
482503
}

Sources/TSCUtility/IndexStore.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ public final class IndexStoreAPI {
193193
self.path = path
194194
#if os(Windows)
195195
let flags: DLOpenFlags = []
196+
#elseif os(Android)
197+
let flags: DLOpenFlags = [.lazy, .local, .first]
196198
#else
197199
let flags: DLOpenFlags = [.lazy, .local, .first, .deepBind]
198200
#endif

Sources/TSCUtility/InterruptHandler.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ public final class InterruptHandler {
6565
var action = sigaction()
6666
#if canImport(Darwin)
6767
action.__sigaction_u.__sa_handler = signalHandler
68+
#elseif os(Android)
69+
action.sa_handler = signalHandler
6870
#else
6971
action.__sigaction_handler = unsafeBitCast(
7072
signalHandler,

Sources/TSCUtility/Platform.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Foundation
1313

1414
/// Recognized Platform types.
1515
public enum Platform {
16+
case android
1617
case darwin
1718
case linux(LinuxFlavor)
1819

@@ -33,6 +34,10 @@ public enum Platform {
3334
if localFileSystem.isFile(AbsolutePath("/etc/debian_version")) {
3435
return .linux(.debian)
3536
}
37+
if localFileSystem.isFile(AbsolutePath("/system/bin/toolbox")) ||
38+
localFileSystem.isFile(AbsolutePath("/system/bin/toybox")) {
39+
return .android
40+
}
3641
default:
3742
return nil
3843
}

Sources/TSCUtility/dlopen.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,10 @@ public struct DLOpenFlags: RawRepresentable, OptionSet {
6060
public static let deepBind: DLOpenFlags = DLOpenFlags(rawValue: 0)
6161
#else
6262
public static let first: DLOpenFlags = DLOpenFlags(rawValue: 0)
63+
#if !os(Android)
6364
public static let deepBind: DLOpenFlags = DLOpenFlags(rawValue: RTLD_DEEPBIND)
6465
#endif
66+
#endif
6567
#endif
6668

6769
public var rawValue: Int32

Tests/FunctionalTests/MiscellaneousTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ class MiscellaneousTestCase: XCTestCase {
439439
}
440440

441441
func testUnicode() {
442-
#if !os(Linux) // TODO: - Linux has trouble with this and needs investigation.
442+
#if !os(Linux) && !os(Android) // TODO: - Linux has trouble with this and needs investigation.
443443
fixture(name: "Miscellaneous/Unicode") { prefix in
444444
// See the fixture manifest for an explanation of this string.
445445
let complicatedString = "πשּׁµ𝄞🇺🇳🇮🇱x̱̱̱̱̱̄̄̄̄̄"

Tests/FunctionalTests/ModuleMapTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class ModuleMapsTestCase: XCTestCase {
2626
try systemQuietly(["clang", "-shared", input.pathString, "-o", output.pathString])
2727

2828
var Xld = ["-L", outdir.pathString]
29-
#if os(Linux)
29+
#if os(Linux) || os(Android)
3030
Xld += ["-rpath", outdir.pathString]
3131
#endif
3232

Tests/PackageLoadingTests/PackageBuilderTests.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,7 @@ class PackageBuilderTests: XCTestCase {
13761376
"ios": "8.0",
13771377
"tvos": "9.0",
13781378
"watchos": "2.0",
1379+
"android": "0.0",
13791380
]
13801381

13811382
PackageBuilderTester(manifest, in: fs) { result in
@@ -1411,6 +1412,7 @@ class PackageBuilderTests: XCTestCase {
14111412
"linux": "0.0",
14121413
"ios": "8.0",
14131414
"watchos": "2.0",
1415+
"android": "0.0",
14141416
]
14151417

14161418
PackageBuilderTester(manifest, in: fs) { result in

Tests/TSCBasicTests/FileSystemTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ class FileSystemTests: XCTestCase {
391391
}
392392

393393
func testSetAttribute() throws {
394-
#if os(macOS) || os(Linux)
394+
#if os(macOS) || os(Linux) || os(Android)
395395
mktmpdir { path in
396396
let fs = TSCBasic.localFileSystem
397397

0 commit comments

Comments
 (0)