Skip to content
New issue

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

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

Already on GitHub? # to your account

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

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,13 @@ include(XCTest)

set(CF_DEPLOYMENT_SWIFT YES CACHE BOOL "Build for Swift" FORCE)

set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG OFF)
if(HAS_LIBDISPATCH_API)
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG OFF)
if(ANDROID)
set(CMAKE_THREAD_LIBS_INIT "-lc")
set(THREADS_HAVE_PTHREAD_ARG FALSE)
endif()
find_package(Threads REQUIRED)
endif()

Expand Down
1 change: 1 addition & 0 deletions CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
#include <sys/stat.h>
#include <sys/syscall.h>
#include <termios.h>
#include <linux/stat.h>
#elif TARGET_OS_WASI
#include <fcntl.h>
#include <sys/stat.h>
Expand Down
6 changes: 6 additions & 0 deletions CoreFoundation/Base.subproj/module.modulemap
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
framework module CoreFoundation [extern_c] [system] {
umbrella header "CoreFoundation.h"
explicit module CFPlugInCOM { header "CFPlugInCOM.h" }
explicit module ForSwiftFoundationOnly {
header "ForSwiftFoundationOnly.h"
// Do not re-export imported Clang modules to avoid pulling in
// system headers like linux/stat.h whose constants might conflict
// with constants from the platform module.
}

export *
module * {
Expand Down
4 changes: 4 additions & 0 deletions Sources/Foundation/CGFloat.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//

#if canImport(Android)
import Android
#endif

@frozen
public struct CGFloat: Sendable {
#if arch(i386) || arch(arm) || arch(wasm32)
Expand Down
9 changes: 9 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 All @@ -57,6 +64,8 @@ internal func malloc_good_size(_ size: Int) -> Int {
import Glibc
#elseif canImport(Musl)
import Musl
#elseif canImport(Android)
import Android
#elseif canImport(WASILibc)
import WASILibc
#endif
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
38 changes: 28 additions & 10 deletions Sources/Foundation/FileManager+POSIX.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
//
#if !os(Windows)

#if canImport(Android)
import Android
#endif

#if os(Android) && (arch(i386) || arch(arm)) // struct stat.st_mode is UInt32
internal func &(left: UInt32, right: mode_t) -> mode_t {
return mode_t(left) & right
Expand Down Expand Up @@ -803,29 +807,36 @@ 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) { rebound_ps in
#if canImport(Android)
let arg = rebound_ps
Copy link
Member

Choose a reason for hiding this comment

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

This change and the similar one 370 lines below are likely no longer needed after swiftlang/swift#74829. Try it out and see, I will check natively on Android also.

#else
let arg = ps
#endif
return fts_open(arg, 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 +1182,14 @@ 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) { rebound_ps in
#if canImport(Android)
let arg = rebound_ps
#else
let arg = ps
#endif
return fts_open(arg, 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 +1236,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 +1416,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
10 changes: 6 additions & 4 deletions Sources/Foundation/FileManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import WinSDK

#if os(WASI)
import WASILibc
#elseif canImport(Android)
import Android
#endif

#if os(Windows)
Expand Down Expand Up @@ -579,13 +581,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
9 changes: 5 additions & 4 deletions Sources/Foundation/Host.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
import WinSDK
#endif

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

// IFF_LOOPBACK is part of the enumeration net_device_flags, which needs to
// convert to UInt32.
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
5 changes: 5 additions & 0 deletions Sources/Foundation/NSData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#if !os(WASI)
import Dispatch
#endif
#if canImport(Android)
import Android
#endif

extension NSData {
public struct ReadingOptions : OptionSet {
Expand Down Expand Up @@ -495,6 +498,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: 2 additions & 0 deletions Sources/Foundation/NSPathUtilities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
@_implementationOnly import CoreFoundation
#if os(Windows)
import WinSDK
#elseif canImport(Android)
import Android
#elseif os(WASI)
import WASILibc
// CoreFoundation brings <errno.h> but it conflicts with WASILibc.errno
Expand Down
3 changes: 3 additions & 0 deletions Sources/Foundation/NSPlatform.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
#if os(macOS) || os(iOS)
fileprivate let _NSPageSize = Int(vm_page_size)
#elseif os(Linux) || os(Android) || os(OpenBSD)
#if canImport(Android)
import Android
#endif
fileprivate let _NSPageSize = Int(getpagesize())
#elseif os(Windows)
import WinSDK
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(Bionic)
@_exported import Bionic
#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
9 changes: 9 additions & 0 deletions Sources/Foundation/Process.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import struct WinSDK.HANDLE

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

extension Process {
Expand Down Expand Up @@ -928,6 +930,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
2 changes: 2 additions & 0 deletions Sources/FoundationNetworking/HTTPCookie.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import Foundation

#if os(Windows)
import WinSDK
#elseif canImport(Android)
import Android
#endif

public struct HTTPCookiePropertyKey : RawRepresentable, Equatable, Hashable {
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
Loading