Skip to content

Foundation: repair the build for Android API level 28+ #4889

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ if(HAS_LIBDISPATCH_API)
find_package(Threads REQUIRED)
endif()

# CMake's Threads adds '-pthread' flag to the interface link
# libraries, which isn't supported by Swift. This is not enabled
# when building with MSVC, but it trips up the Android build, so
# we need to clear out the threads INTERFACE_LINK_LIBRARIES.
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @iCharlesHu -- we will need to make sure this is kept in our transition to the newer cmake files

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been updated now.

set_property(TARGET Threads::Threads PROPERTY INTERFACE_LINK_LIBRARIES "")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this probably addresses the same issue I fixed in build-script years ago. Maybe it would be better to add that CMake flag to build.ps1?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I resolved it differently now, thanks to @compnerd 's suggestion.

endif()

set(SAVED_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
set(BUILD_SHARED_LIBS NO)
add_subdirectory(CoreFoundation EXCLUDE_FROM_ALL)
Expand Down
7 changes: 7 additions & 0 deletions Sources/Foundation/Data.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@
@usableFromInline let memset = WASILibc.memset
@usableFromInline let memcpy = WASILibc.memcpy
@usableFromInline let memcmp = WASILibc.memcmp
#elseif canImport(Android)
@usableFromInline let calloc = Android.calloc
@usableFromInline let malloc = Android.malloc
@usableFromInline let free = Android.free
@usableFromInline let memset = Android.memset
@usableFromInline let memcpy = Android.memcpy
@usableFromInline let memcmp = Android.memcmp
#endif

#if !canImport(Darwin)
Expand Down
7 changes: 6 additions & 1 deletion Sources/Foundation/FileHandle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ import WASILibc
fileprivate let _read = WASILibc.read(_:_:_:)
fileprivate let _write = WASILibc.write(_:_:_:)
fileprivate let _close = WASILibc.close(_:)
#elseif canImport(Android)
import Android
fileprivate let _read = Android.read(_:_:_:)
fileprivate let _write = Android.write(_:_:_:)
fileprivate let _close = Android.close(_:)
#endif

#if canImport(WinSDK)
Expand Down Expand Up @@ -324,7 +329,7 @@ open class FileHandle : NSObject {
let data = mmap(nil, mapSize, PROT_READ, MAP_PRIVATE, _fd, 0)
// Swift does not currently expose MAP_FAILURE
if data != UnsafeMutableRawPointer(bitPattern: -1) {
return NSData.NSDataReadResult(bytes: data!, length: mapSize) { buffer, length in
return NSData.NSDataReadResult(bytes: data, length: mapSize) { buffer, length in
munmap(buffer, length)
}
}
Expand Down
32 changes: 20 additions & 12 deletions Sources/Foundation/FileManager+POSIX.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
internal func &(left: UInt32, right: mode_t) -> mode_t {
return mode_t(left) & right
}
#elseif os(Android)
internal func &(left: mode_t, right: Int32) -> mode_t {
return left & mode_t(right)
}
#endif

#if os(WASI)
Expand Down Expand Up @@ -409,7 +413,7 @@ extension FileManager {
if !parent.isEmpty && !fileExists(atPath: parent, isDirectory: &isDir) {
try createDirectory(atPath: parent, withIntermediateDirectories: true, attributes: attributes)
}
if mkdir(pathFsRep, S_IRWXU | S_IRWXG | S_IRWXO) != 0 {
if mkdir(pathFsRep, mode_t(S_IRWXU) | mode_t(S_IRWXG) | mode_t(S_IRWXO)) != 0 {
let posixError = errno
if posixError == EEXIST && fileExists(atPath: path, isDirectory: &isDir) && isDir.boolValue {
// Continue; if there is an existing file and it is a directory, that is still a success.
Expand All @@ -428,7 +432,7 @@ extension FileManager {
throw _NSErrorWithErrno(EEXIST, reading: false, path: path)
}
} else {
if mkdir(pathFsRep, S_IRWXU | S_IRWXG | S_IRWXO) != 0 {
if mkdir(pathFsRep, mode_t(S_IRWXU) | mode_t(S_IRWXG) | mode_t(S_IRWXO)) != 0 {
throw _NSErrorWithErrno(errno, reading: false, path: path)
} else if let attr = attributes {
try self.setAttributes(attr, ofItemAtPath: path)
Expand Down Expand Up @@ -803,29 +807,31 @@ extension FileManager {
let ps = UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>.allocate(capacity: 2)
ps.initialize(to: UnsafeMutablePointer(mutating: fsRep))
ps.advanced(by: 1).initialize(to: nil)
let stream = fts_open(ps, FTS_PHYSICAL | FTS_XDEV | FTS_NOCHDIR | FTS_NOSTAT, nil)
let stream = ps.withMemoryRebound(to: UnsafeMutablePointer<CChar>.self, capacity: 2) {
fts_open($0, FTS_PHYSICAL | FTS_XDEV | FTS_NOCHDIR | FTS_NOSTAT, nil)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ps.deinitialize(count: 2)
ps.deallocate()

if stream != nil {
if let stream {
defer {
fts_close(stream)
}

while let current = fts_read(stream)?.pointee {
let itemPath = string(withFileSystemRepresentation: current.fts_path, length: Int(current.fts_pathlen))
while let current = fts_read(stream)?.pointee, let fts_path = current.fts_path {
let itemPath = string(withFileSystemRepresentation: fts_path, length: Int(current.fts_pathlen))
guard alreadyConfirmed || shouldRemoveItemAtPath(itemPath, isURL: isURL) else {
continue
}

do {
switch Int32(current.fts_info) {
case FTS_DEFAULT, FTS_F, FTS_NSOK, FTS_SL, FTS_SLNONE:
if unlink(current.fts_path) == -1 {
if unlink(fts_path) == -1 {
throw _NSErrorWithErrno(errno, reading: false, path: itemPath)
}
case FTS_DP:
if rmdir(current.fts_path) == -1 {
if rmdir(fts_path) == -1 {
throw _NSErrorWithErrno(errno, reading: false, path: itemPath)
}
case FTS_DNR, FTS_ERR, FTS_NS:
Expand Down Expand Up @@ -1171,7 +1177,9 @@ extension FileManager {
defer { ps.deallocate() }
ps.initialize(to: UnsafeMutablePointer(mutating: fsRep))
ps.advanced(by: 1).initialize(to: nil)
return fts_open(ps, FTS_PHYSICAL | FTS_XDEV | FTS_NOCHDIR | FTS_NOSTAT, nil)
return ps.withMemoryRebound(to: UnsafeMutablePointer<CChar>.self, capacity: 2) {
fts_open($0, FTS_PHYSICAL | FTS_XDEV | FTS_NOCHDIR | FTS_NOSTAT, nil)
}
}
if _stream == nil {
throw _NSErrorWithErrno(errno, reading: true, url: url)
Expand Down Expand Up @@ -1218,13 +1226,13 @@ extension FileManager {

_current = fts_read(stream)
while let current = _current {
let filename = FileManager.default.string(withFileSystemRepresentation: current.pointee.fts_path, length: Int(current.pointee.fts_pathlen))
let filename = FileManager.default.string(withFileSystemRepresentation: current.pointee.fts_path!, length: Int(current.pointee.fts_pathlen))

switch Int32(current.pointee.fts_info) {
case FTS_D:
let (showFile, skipDescendants) = match(filename: filename, to: _options, isDir: true)
if skipDescendants {
fts_set(_stream, _current, FTS_SKIP)
fts_set(stream, _current!, FTS_SKIP)
}
if showFile {
return URL(fileURLWithPath: filename, isDirectory: true)
Expand Down Expand Up @@ -1398,7 +1406,7 @@ extension FileManager {
let finalErrno = originalItemURL.withUnsafeFileSystemRepresentation { (originalFS) -> Int32? in
return newItemURL.withUnsafeFileSystemRepresentation { (newItemFS) -> Int32? in
// This is an atomic operation in many OSes, but is not guaranteed to be atomic by the standard.
if rename(newItemFS, originalFS) == 0 {
if rename(newItemFS!, originalFS!) == 0 {
return nil
} else {
return errno
Expand Down
24 changes: 14 additions & 10 deletions Sources/Foundation/FileManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ import WinSDK
import WASILibc
#endif

#if os(Android)
import Android
#endif

#if os(Windows)
internal typealias NativeFSRCharType = WCHAR
internal let NativeFSREncoding = String.Encoding.utf16LittleEndian.rawValue
Expand Down Expand Up @@ -579,13 +583,13 @@ open class FileManager : NSObject {
#elseif os(WASI)
let type = FileAttributeType(statMode: mode_t(s.st_mode))
#else
if let pwd = getpwuid(s.st_uid), pwd.pointee.pw_name != nil {
let name = String(cString: pwd.pointee.pw_name)
if let pwd = getpwuid(s.st_uid), let pw_name = pwd.pointee.pw_name {
let name = String(cString: pw_name)
result[.ownerAccountName] = name
}

if let grd = getgrgid(s.st_gid), grd.pointee.gr_name != nil {
let name = String(cString: grd.pointee.gr_name)
if let grd = getgrgid(s.st_gid), let gr_name = grd.pointee.gr_name {
let name = String(cString: gr_name)
result[.groupOwnerAccountName] = name
}

Expand Down Expand Up @@ -1342,12 +1346,12 @@ public struct FileAttributeType : RawRepresentable, Equatable, Hashable {
#else
internal init(statMode: mode_t) {
switch statMode & S_IFMT {
case S_IFCHR: self = .typeCharacterSpecial
case S_IFDIR: self = .typeDirectory
case S_IFBLK: self = .typeBlockSpecial
case S_IFREG: self = .typeRegular
case S_IFLNK: self = .typeSymbolicLink
case S_IFSOCK: self = .typeSocket
case mode_t(S_IFCHR): self = .typeCharacterSpecial
case mode_t(S_IFDIR): self = .typeDirectory
case mode_t(S_IFBLK): self = .typeBlockSpecial
case mode_t(S_IFREG): self = .typeRegular
case mode_t(S_IFLNK): self = .typeSymbolicLink
case mode_t(S_IFSOCK): self = .typeSocket
default: self = .typeUnknown
}
}
Expand Down
5 changes: 3 additions & 2 deletions Sources/Foundation/Host.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import WinSDK
#endif

#if os(Android)
import Android
// Android Glibc differs a little with respect to the Linux Glibc.

// IFF_LOOPBACK is part of the enumeration net_device_flags, which needs to
Expand All @@ -24,8 +25,8 @@ import WinSDK
}

// getnameinfo uses size_t for its 4th and 6th arguments.
private func getnameinfo(_ addr: UnsafePointer<sockaddr>?, _ addrlen: socklen_t, _ host: UnsafeMutablePointer<Int8>?, _ hostlen: socklen_t, _ serv: UnsafeMutablePointer<Int8>?, _ servlen: socklen_t, _ flags: Int32) -> Int32 {
return Glibc.getnameinfo(addr, addrlen, host, Int(hostlen), serv, Int(servlen), flags)
private func getnameinfo(_ addr: UnsafePointer<sockaddr>, _ addrlen: socklen_t, _ host: UnsafeMutablePointer<Int8>?, _ hostlen: socklen_t, _ serv: UnsafeMutablePointer<Int8>?, _ servlen: socklen_t, _ flags: Int32) -> Int32 {
return Android.getnameinfo(addr, addrlen, host, Int(hostlen), serv, Int(servlen), flags)
}

// getifaddrs and freeifaddrs are not available in Android 6.0 or earlier, so call these functions dynamically.
Expand Down
2 changes: 2 additions & 0 deletions Sources/Foundation/NSData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,8 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
let createMode = Int(Musl.S_IRUSR) | Int(Musl.S_IWUSR) | Int(Musl.S_IRGRP) | Int(Musl.S_IWGRP) | Int(Musl.S_IROTH) | Int(Musl.S_IWOTH)
#elseif canImport(WASILibc)
let createMode = Int(WASILibc.S_IRUSR) | Int(WASILibc.S_IWUSR) | Int(WASILibc.S_IRGRP) | Int(WASILibc.S_IWGRP) | Int(WASILibc.S_IROTH) | Int(WASILibc.S_IWOTH)
#elseif canImport(Android)
let createMode = Int(Android.S_IRUSR) | Int(Android.S_IWUSR) | Int(Android.S_IRGRP) | Int(Android.S_IWGRP) | Int(Android.S_IROTH) | Int(Android.S_IWOTH)
#endif
guard let fh = FileHandle(path: path, flags: flags, createMode: createMode) else {
throw _NSErrorWithErrno(errno, reading: false, path: path)
Expand Down
2 changes: 2 additions & 0 deletions Sources/Foundation/NSError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import Darwin
import Glibc
#elseif canImport(CRT)
import CRT
#elseif canImport(Android)
import Android
#endif

@_implementationOnly import CoreFoundation
Expand Down
2 changes: 2 additions & 0 deletions Sources/Foundation/NSLock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

#if canImport(Glibc)
import Glibc
#elseif canImport(Android)
import Android
#endif

#if os(Windows)
Expand Down
2 changes: 1 addition & 1 deletion Sources/Foundation/NSPathUtilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,7 @@ internal func _NSCreateTemporaryFile(_ filePath: String) throws -> (Int32, Strin
}

// Set the file mode to match macOS
guard fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) != -1 else {
guard fchmod(fd, mode_t(S_IRUSR) | mode_t(S_IWUSR) | mode_t(S_IRGRP) | mode_t(S_IWGRP) | mode_t(S_IROTH) | mode_t(S_IWOTH)) != -1 else {
let _errno = errno
close(fd)
throw _NSErrorWithErrno(_errno, reading: false, path: pathResult)
Expand Down
2 changes: 2 additions & 0 deletions Sources/Foundation/NSSwiftRuntime.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
@_exported import Glibc
#elseif canImport(Musl)
@_exported import Musl
#elseif canImport(Android)
@_exported import Android
#elseif os(WASI)
@_exported import WASILibc
#elseif os(Windows)
Expand Down
2 changes: 2 additions & 0 deletions Sources/Foundation/NSURL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import Darwin
import Glibc
#elseif canImport(Musl)
import Musl
#elseif canImport(Android)
import Android
#endif

// NOTE: this represents PLATFORM_PATH_STYLE
Expand Down
12 changes: 9 additions & 3 deletions Sources/Foundation/Port.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,22 +90,28 @@ open class SocketPort: Port {}

#else

#if canImport(Glibc) && !os(Android) && !os(OpenBSD)
#if canImport(Glibc) && !os(OpenBSD)
import Glibc
fileprivate let SOCK_STREAM = Int32(Glibc.SOCK_STREAM.rawValue)
fileprivate let SOCK_DGRAM = Int32(Glibc.SOCK_DGRAM.rawValue)
fileprivate let IPPROTO_TCP = Int32(Glibc.IPPROTO_TCP)
#endif

#if canImport(Glibc) && os(Android) || os(OpenBSD)
#if canImport(Glibc) && os(OpenBSD)
import Glibc
fileprivate let SOCK_STREAM = Int32(Glibc.SOCK_STREAM)
fileprivate let SOCK_DGRAM = Int32(Glibc.SOCK_DGRAM)
fileprivate let IPPROTO_TCP = Int32(Glibc.IPPROTO_TCP)
fileprivate let INADDR_ANY: in_addr_t = 0
#if os(OpenBSD)
fileprivate let INADDR_LOOPBACK = 0x7f000001
#endif

#if canImport(Android)
import Android
fileprivate let SOCK_STREAM = Int32(Android.SOCK_STREAM)
fileprivate let SOCK_DGRAM = Int32(Android.SOCK_DGRAM)
fileprivate let IPPROTO_TCP = Int32(Android.IPPROTO_TCP)
fileprivate let INADDR_ANY: in_addr_t = 0
#endif


Expand Down
7 changes: 7 additions & 0 deletions Sources/Foundation/Process.swift
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,13 @@ open class Process: NSObject {
var spawnAttrs: posix_spawnattr_t? = nil
#else
var spawnAttrs: posix_spawnattr_t = posix_spawnattr_t()
#endif
#if os(Android)
guard var spawnAttrs else {
throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno), userInfo: [
NSURLErrorKey:self.executableURL!
])
}
#endif
try _throwIfPosixError(posix_spawnattr_init(&spawnAttrs))
try _throwIfPosixError(posix_spawnattr_setflags(&spawnAttrs, .init(POSIX_SPAWN_SETPGROUP)))
Expand Down
2 changes: 2 additions & 0 deletions Sources/Foundation/Thread.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import WinSDK
import Glibc
#elseif canImport(Musl)
import Musl
#elseif canImport(Android)
import Android
#endif

// WORKAROUND_SR9811
Expand Down
3 changes: 3 additions & 0 deletions Sources/Tools/plutil/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import Glibc
#elseif canImport(Musl)
import Foundation
import Musl
#elseif canImport(Android)
import Foundation
import Android
#elseif canImport(CRT)
import Foundation
import CRT
Expand Down