MobileNativeFoundation / rules_xcodeproj

Bazel rules for generating Xcode projects.
MIT License
502 stars 76 forks source link

Feature Request: Co-locate Bazel Generated Files with targets #3037

Open sebastianv1 opened 1 month ago

sebastianv1 commented 1 month ago

Curious how difficult it might be to co-locate the generated files (i.e genrule or swift_proto_compile sources) under the target's group in Xcode?

For example, in addition to the top-level group Bazel Generated Files there could be a generated files group for a target package.

.
└── Modules/
    ├── Foo/
    │   ├── Sources/
    │   │   └── Baz.swift
    │   └── Bazel Generated/
    │       ├── <config_ios15>/
    │       │   └── File_Genrule_Generated.swift
    │       └── <config_ios16>/
    │           └── File_Genrule_Generated.swift
    └── Proto/
        ├── proto/
        │   └── test.proto
        └── Bazel Generated/
            └── test.pb.swift  

I've abbreviated the true output_base paths for brevity (but noted multiple potential configurations for a generated file with the config_ios15 and config_ios16).

Unsure if this is really feasible, but thought I'd ask since it can currently be a bit tricky to find generated files in Xcode to inspect their contents.

brentleyjones commented 1 month ago

@erikkerber Do you want to add to this feature request, since you've personally asked for something similar in the past?

@sebastianv1 this is doable, it just hasn't been a priority since I've only had one other request for it before.

sebastianv1 commented 1 month ago

@brentleyjones Makes sense and glad to hear it's doable! Any pointers on where I might get started on a potential implementation?

@erikkerber Would love to hear what y'all would find helpful as well.

brentleyjones commented 1 month ago

https://github.com/MobileNativeFoundation/rules_xcodeproj/blob/4b19da21da942bb80642cb4f0eef25cc889c0881/tools/generators/files_and_groups/src/ElementCreator/CreateSpecialRootGroupElement.swift#L52-L56 is where we kick off creating the Bazel Generated Files group in Xcode.

https://github.com/MobileNativeFoundation/rules_xcodeproj/blob/4b19da21da942bb80642cb4f0eef25cc889c0881/tools/generators/files_and_groups/src/ElementCreator/CreateRootElements.swift#L116-L122 is where we create normal groups.

https://github.com/MobileNativeFoundation/rules_xcodeproj/blob/4b19da21da942bb80642cb4f0eef25cc889c0881/tools/generators/files_and_groups/src/Generator/CalculatePathTree.swift is where we create the path tree that everything else works off of. This code is very performance critical, so be careful if modifying.

I think you would essentially have to cause CalculatePathTree to create nodes in the correct spot to make the generated files next to the normal files. I think the transformation would be something like bazel-out/ios_sim_arm64-dbg-ios-sim_arm64-min15.0-applebin_ios-ST-99dd961771c3/bin/Source/Path/File.swift (which is Bazel Generated/ios_sim_arm64-dbg-ios-sim_arm64-min15.0-applebin_ios-ST-99dd961771c3/bin/Source/Path/File.swift in Xcode) -> Source/Path/Bazel Generated/ios_sim_arm64-dbg-ios-sim_arm64-min15.0-applebin_ios-ST-99dd961771c3/File.swift (with both Bazel Generated and ios_sim_arm64-dbg-ios-sim_arm64-min15.0-applebin_ios-ST-99dd961771c3 being explicit paths like the single Bazel Generated is today). Bazel Generated/ios_sim_arm64-dbg-ios-sim_arm64-min15.0-applebin_ios-ST-99dd961771c3 could probably be represented by a single node in in the PathTree, and the code that generates from it would just create the two PBXGroup elements for it.

erikkerber commented 1 month ago

I remember mentioning this before, but I don't have anything profound to add to the general idea of putting generated files in an Xcode group that corresponds to the package a generated file shares with a i.e. Swift module.

sebastianv1 commented 3 weeks ago

Thanks for the pointers @brentleyjones ! I'll actually have some time to try implementing this.

I did a superficial pass, and one problem I'm thinking about is how we would know which group the Bazel Generated files should fall under solely based on the path, and not the Bazel package + label.

For instance, let's say we have Modules/Foo:genrule_x and Modules/Foo/Bar:genrule_y. I believe the generated BazelPath instances would just be bazel-out/darwin-<x>/bin/Modules/Foo/GenruleX.swift and bazel-out/darwin-<x>/bin/Modules/Foo/Bar/GenruleY.swift? In my mind it makes sense to add a Bazel Generated files group next to package's group (if it exists) in Xcode. Maybe it's possible to infer this if a BUILD.bazel is present?

brentleyjones commented 3 weeks ago

The generated files have owner labels, so we can determine their package, pass that info along somehow, and then place these groups there.

sebastianv1 commented 1 week ago

Initial draft PR where we could probably continue any implementation specific details: #3047 🙏