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.swift
file; - my
.apk
size foraarch64
went 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.apk
for all three targets:aarch64
,armv7
,x86_64
. - due to specific character of
resource_bundle_accessor.swift
to 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.swift
in target sources where resources arguments are defined, if not found use default variation; - pass path to custom
.swift
file for resources definition as argument to-Xbuild-tools-swiftc
, if argument isn't defined use default variation;