Adding resources to targets in Package.swift leads to generating resource_bundle_accessor.swift which imports Foundation even if there is no "import Foundation", other imports or dependencies.
// resource_bundle_accessor.swift
import class Foundation.Bundle
import class Foundation.ProcessInfo
import struct Foundation.URL
private class BundleFinder {}
extension Foundation.Bundle {
/// Returns the resource bundle associated with the current Swift module.
static let module: Bundle = {
let bundleName = "<name>_<target>"
let overrides: [URL]
#if DEBUG
// The 'PACKAGE_RESOURCE_BUNDLE_PATH' name is preferred since the expected value is a path. The
// check for 'PACKAGE_RESOURCE_BUNDLE_URL' will be removed when all clients have switched over.
// This removal is tracked by rdar://107766372.
if let override = ProcessInfo.processInfo.environment["PACKAGE_RESOURCE_BUNDLE_PATH"]
?? ProcessInfo.processInfo.environment["PACKAGE_RESOURCE_BUNDLE_URL"] {
overrides = [URL(fileURLWithPath: override)]
} else {
overrides = []
}
#else
overrides = []
#endif
let candidates = overrides + [
// Bundle should be present here when the package is linked into an App.
Bundle.main.resourceURL,
// Bundle should be present here when the package is linked into a framework.
Bundle(for: BundleFinder.self).resourceURL,
// For command-line tools.
Bundle.main.bundleURL,
]
for candidate in candidates {
let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle")
if let bundle = bundlePath.flatMap(Bundle.init(url:)) {
return bundle
}
}
fatalError("unable to find bundle named <name>_<target>")
}()
}
I'm developing cross-platform library for Linux, Android and Apple OSes which needs nothing from Foundation. Wanted to add resources in SwiftPM in the way that structure of Package.swift expects.
I faced the issue when I was trying to launch swift target on Android that has defined resources in Package.swift, it crashes on launch due to lack of Foundation dependencies (libswiftDispatch.so, libFoundationInternationalization.so, libFoundationEssentials.so, libFoundation.so, lib_FoundationICU.so). So I need to pack all this dependencies to my .apk, even if I use nothing from Foundation.
Why I don't want Foundation linking:
- no need any code from it. Maybe only
Bundle.module.bundlePath, where I can extract bundle name. Even this code is not from Foundation, it is from generatedresource_bundle_accessor.swiftfile; - my
.apksize foraarch64went from 6.3 mb to 27.9 mb when all Foundation libraries are included. Also it went from 18.1 mb to 83.5 mb when bundling.apkfor all three targets:aarch64,armv7,x86_64. - due to specific character of
resource_bundle_accessor.swiftto Apple platforms, it crashes in runtime on other platforms;
Ideas for alleged proposals:
- cross-platform dependency-less code in
resource_bundle_accessor.swift, for example something like this:
public struct ResourcesBundle {
public static let bundleName = "<name>_<target>" // as it is now
}
- search for
resource_bundle_accessor.swiftin target sources where resources arguments are defined, if not found use default variation; - pass path to custom
.swiftfile for resources definition as argument to-Xbuild-tools-swiftc, if argument isn't defined use default variation;