cgrindel / rules_swift_package_manager

Collection of utilities and Bazel rules to aid in the development and maintenance of Swift repositories using Bazel.
Apache License 2.0
72 stars 26 forks source link

Support for other resource file extensions such as `.stencil` and `.png` #1028

Open tinder-cfuller opened 4 months ago

tinder-cfuller commented 4 months ago

How to include .stencil and .png resources in bundle?

Target resources are defined as resources: [.process("Resources")], and when building with SPM natively, all files are copied to bundle. I could be wrong, but I believe that .process() includes all files, regardless of file type/extension, while performing optimizations for specific types/extensions.

FWIW, resources: [.copy("Resources/Image.png")] is also not working.

In both cases, the following error is reported when running the executable target:

Generator/Generator.rspm_resource_bundle_accessor_ResourceBundleAccessor.swift:42: Fatal error: unable to find bundle

Any help or suggestions are welcome. Thank you!

tinder-cfuller commented 4 months ago

I just noticed Unable to find dependency labels for s in the log, is it related?

bazelisk run //:update_build_files
INFO: Analyzed target //:update_build_files (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //:update_build_files up-to-date:
  bazel-bin/update_build_files-runner.bash
  bazel-bin/update_build_files
INFO: Elapsed time: 0.226s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
INFO: Running command line: bazel-bin/update_build_files
gazelle: Unable to find dependency labels for s
cgrindel commented 4 months ago

I just noticed Unable to find dependency labels for s in the log, is it related?

Not sure.

resources: [.process("Resources")]

Is this in the Package.swift for one of your dependencies or is it in the Package.swift for your repository?

tinder-cfuller commented 4 months ago

@cgrindel Thank you for taking time to reply. Very much appreciated 👍

The resources are in one of the dependencies.

cgrindel commented 4 months ago

By any chance is this dependency publicly available, it would be great to add a repro to one of the examples in this repository.

tinder-cfuller commented 1 month ago

Hi @cgrindel 👋

I published an example dependency for use in attempting to repro my issue:

https://github.com/tinder-cfuller/rspm-example

Since rules_swift_package_manager has been updated since I originally submitted my issue, I am attempting to repro with the latest version that has new instructions.

After following the latest instructions in the README, I am receiving the following error:

$ bazel run //:update_build_files
ERROR: no such package '@@[unknown repo 'swift_deps_info' requested from @@]//': The repository '@@[unknown repo 'swift_deps_info' requested from @@]' could not be resolved: No repository visible as '@swift_deps_info' from main repository
ERROR: /Users/christopherfuller/Downloads/rules_swift_package_manager_debugging/Executable/BUILD.bazel:25:8: no such package '@@[unknown repo 'swift_deps_info' requested from @@]//': The repository '@@[unknown repo 'swift_deps_info' requested from @@]' could not be resolved: No repository visible as '@swift_deps_info' from main repository and referenced by '//:update_build_files'
ERROR: Analysis of target '//:update_build_files' failed; build aborted: Analysis failed
INFO: Elapsed time: 0.150s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
ERROR: Build did NOT complete successfully
ERROR: Build failed. Not running target

If I manually add swift_deps_info to MODULE.bazel, the error of course is:

$ bazel run //:update_build_files
WARNING: /Users/christopherfuller/Downloads/rules_swift_package_manager_debugging/Executable/MODULE.bazel:5:27: The module extension swift_deps defined in @rules_swift_package_manager//:extensions.bzl reported incorrect imports of repositories via use_repo():

Imported, but not created by the extension (will cause the build to fail):
    swift_deps_info

Fix the use_repo calls by running 'bazel mod tidy'.
ERROR: Analysis of target '//:update_build_files' failed; build aborted: module extension "swift_deps" from "@@rules_swift_package_manager~//:extensions.bzl" does not generate repository "swift_deps_info", yet it is imported as "swift_deps_info" in the usage at /Users/christopherfuller/Downloads/rules_swift_package_manager_debugging/Executable/MODULE.bazel:5:27
INFO: Elapsed time: 0.190s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
ERROR: Build did NOT complete successfully
ERROR: Build failed. Not running target

I have attached my sample executable project:

Executable.zip

This can be executed via SPM directly with:

swift run example

Which will output:

Hello World

For reference, I ultimately expect to validate by executing:

bazel run //:example

May you please help me to fix the error I am receiving so I am then able to continue to repo my original issue. Thank you!

tinder-cfuller commented 1 month ago

@cgrindel Looking through the source code, I found usage of declare_swift_deps_info, which is not currently in the README instructions. Adding this has helped:

swift_deps.from_package(
    declare_swift_deps_info = True, # <- here
    resolved = "//:Package.resolved",
    swift = "//:Package.swift",
)

With this in place, I am able to execute:

bazel run //Sources/ExampleExecutable

But this fails with the same bundle error I reported:

ExampleLibrary/ExampleLibrary.rspm_resource_bundle_accessor_ResourceBundleAccessor.swift:42: Fatal error: unable to find bundle

Here is the up-to-date sample executable project:

Executable.zip

Now that we have a repro example in place, may you please help diagnose the resources issue? Thank you!

[!NOTE] The repro example is only setup for a .stencil file resource, but the reported issue affects other resource types including, but not limited to, png images.

As a reminder, I believe that .process() includes all files, regardless of file type/extension, while performing optimizations for specific types/extensions.

cgrindel commented 1 month ago

Looking through the source code, I found usage of declare_swift_deps_info, which is not currently in the README instructions. Adding this has helped:

I just put up #1185 to clarify when one needs to specify that attribute. Can you review and let me know if that helps?

Regarding the resource issue, I will take a look now that we have a repro. Thanks!

tinder-cfuller commented 1 month ago

@cgrindel Thank you!

tinder-cfuller commented 2 weeks ago

Hi @cgrindel 👋

I am kindly checking in to see whether you can please look into this issue?

cgrindel commented 2 weeks ago

Sorry for the delay, @tinder-cfuller. I am a bit behind on my open-source work. I'll try to look at it this weekend.

cgrindel commented 2 weeks ago

There are a couple of issues.

First, to use resources with Bazel-built Apple applications, you must use a rules_apple rule that supports resources (e.g. macos_application, ios_application). This means that you need to change the example so that ExampleExecutable is a macos_application instead of a swift_binary.

Second: However, as @tinder-cfuller rightly points out, SPM allows you to create a command-line application that can access resources. Unfortunately, macos_command_line_application does not. In theory, I think that we need to update rules_apple to support resources. Then, the example could be defined as

load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
load("@rules_apple//apple:macos.bzl", "macos_command_line_application")
load(
    "@rules_apple//apple:versioning.bzl",
    "apple_bundle_version",
)

swift_library(
    name = "ExampleExecutableLib",
    srcs = ["ExampleExecutable.swift"],
    module_name = "ExampleExecutable",
    visibility = ["//visibility:public"],
    deps = ["@swiftpkg_rspm_example//:ExampleLibrary"],
)

apple_bundle_version(
    name = "CommandLineSwiftVersion",
    build_version = "1.0",
)

macos_command_line_application(
    name = "ExampleExecutable",
    bundle_id = "com.example.command-line-swift",
    infoplists = [":Info.plist"],
    minimum_os_version = "10.13",
    version = ":CommandLineSwiftVersion",
    deps = [":ExampleExecutableLib"],
) 

@brentleyjones @luispadron Do you have thoughts on adding resource bundle support to macos_command_line_application?

tinder-cfuller commented 2 weeks ago

Thank you @cgrindel 👍 Very much appreciated!

And just for my own Bazel learning, may you please clarify, would the example Bazel config you provided ultimately be code generated just like the swift_binary one is today? Asking since I was considering adopting rules_swift_package_manager as a way to avoid manually creating and maintaining BUILD files.

Also, are we sure that macos_command_line_application would be required? I would very much like to see a Bazel solution that matches how SPM works as apposed to xcodebuild for example. This would result in the same bundle format and without the property list, etc. And I am not familiar enough the resulting binary formats, but I would guess that the SPM format is different. Ultimately, if I have some consumers that consume this executable via SPM and some via Bazel, I would expect that the executable and bundle formats are the same.

cgrindel commented 2 weeks ago

would the example Bazel config you provided ultimately be code generated just like the swift_binary one is today?

Yes and no. It will generate the swift_binary as you saw. However, if you change it to a swift_library, it should respect that and apply any future changes to the swift_library. The gazelle plugin does not support any of the rules_apple targets, at this time.

Asking since I was considering adopting rules_swift_package_manager as a way to avoid manually creating and maintaining BUILD files.

Great. FYI. Per a request from the community, I am working to separate the Gazelle plugin from the rules_swift_package_manager. In the coming months, they will be two separate projects.

are we sure that macos_command_line_application would be required?

Well, all of the Apple bundle support is implemented in rules_apple rules. The Bazel rules try to separate Swift from the Apple-specific functionality. Swift Package Manager does not.

I would expect that the executable and bundle formats are the same.

By any change, did you try your example on Linux? Did it work? If so, that could be a good argument for adding the resource bundling to the Swift Bazel rules. 🤷‍♂️ @brentleyjones @luispadron Do you have any thoughts on this?