Packages with xcassets that use generated ColorResource and ImageResource extensions fail to build
If a Swift package contains an asset catalog, in iOS 17+/macOS 14+, Xcode will generate Swift extensions for ColorResource and ImageResource for each color and image asset in the catalog. For example, if a color is named "primaryBackground" in the catalog, Xcode will generate a file with these contents:
@available(iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0, *)
extension DeveloperToolsSupport.ColorResource {
/// The "primaryBackground" asset catalog color resource.
static let primaryBackground = DeveloperToolsSupport.ColorResource(name: "primaryBackground", bundle: resourceBundle)
}
The color can then be instantiated with Color(.primaryBackground).
When using rules_swift_package_manager, if you depend on a package that uses these accessors, the build fails with the following error:
external/rules_swift_package_manager++swift_deps+swiftpkg_dependency/Sources/Dependency/Dependency.swift:7:50: error: reference to member 'primaryBackground' cannot be resolved without a contextual type
5 | public static let primaryAccent = Color(.primaryAccent)
6 | public static let secondaryAccent = Color(.secondaryAccent)
7 | public static let primaryBackground = Color(.primaryBackground)
| `- error: reference to member 'primaryBackground' cannot be resolved without a contextual type
I've created a sample project to demonstrate this issue. Clone the repo, then run:
bazel build //Example
Of course, this problem is not specific to Swift packages, so I'd imagine we could benefit from a new rule in rules_apple like "apple_xcassets_accessors" or something. Because of this, let me know if you think this issue is misplaced here.
@daltonclaybrook Do you manage this package yourself?
I find R.swift generated accessors for resources great, as it stays a bit outside the Apple ecosystem and allows you to better use resources in a static libs — keeping resources separate. You are able to make a genrule for this that uses the binary built from rules_swift_package_manger via $(location @swiftpkg_r.swift//:rswift). Good luck!
def rswift_resource_module(name, resources, access_level = "public"):
native.genrule(
name = name + "_generate_r",
srcs = [ resources ],
outs = [ "Resources/" + name + "_R.generated.swift" ],
tools = [
"@swiftpkg_r.swift//:rswift",
],
cmd = """
set -e
"$(location @swiftpkg_r.swift//:rswift)" generate \
--access-level {access} \
--input-files $(locations {res}) \
--input-type input-files \
$(OUTS)
""".format(name = name, access = access_level, res = resources),
visibility = ["//visibility:public"],
)
swift_library(
name = name,
srcs = [ "Resources/" + name + "_R.generated.swift" ],
module_name = name,
deps = [
"@swiftpkg_r.swift//:RswiftLibrary",
],
visibility = ["//visibility:public"],
)