spotify / XCRemoteCache

Other
827 stars 50 forks source link

Local code changes not reflected in Simulator #138

Open cezarsignori opened 2 years ago

cezarsignori commented 2 years ago

Integration setup

XCRemoteCache: RC 0.3.12 or locally built master (91505a59d2a3b8db3dc0eef90c6fbdc051141169) HTTP cache server: Local Demo Docker Xcode: 13.2.1 (13C100) or 13.3.1 (13E500a) Automatic Integration or Manual integration via Buck

Problem and Expectation

Code changes with RC builds are not reflected in the Simulator. Expected to see changes.

How to reproduce

  1. Clean build the app with RC enabled for 100% cache hit rate;
  2. Change the code (either Objective-C or Swift);
  3. Build and Run the app;
  4. In the 1st incremental build, the target and reverse dependencies are re-built. If 2nd incremental build, only changed file is rebuilt;
  5. Test the app in the Simulator. The changes are not in.
  6. The debugger is able to step in the deleted or commented out code as if it was there.
cezarsignori commented 2 years ago

The problem was that the root app binary was also cached, so Xcode would compile the changes but run the cached app binary. Avoiding that causes the local code changes to be reflected and the build time to increase by ~40s.

I am ready to close this ticket. But before that, @polac24, shouldn't the top-level target (root app binary) have been disabled due to changes to dependencies (any module in the app)?

polac24 commented 2 years ago

That should work, the top-level target should not be cached if any of its dependencies have been modified. Looking on the top-level target's meta.json, can you all expected dependencies?

cezarsignori commented 2 years ago

Actually no. The meta.json file shows as dependencies the main.m file and multiple Mapbox.framework files, but it does not contain the Host module which is actually our top-level module and the only dependency declared in the root app binary's BUCK file.

The cached file for the root app binary contains the entire app and dSYM file. In BUCK terms, it is an apple_binary not an apple_library.

Is it expected from RC that app and dSYM file are cached as well?

polac24 commented 2 years ago
  1. Yes, if you don't exclude the "root" target (apple_binary) from XCRemoteCache, it will also cache the binary and dSYM. However, we found that not caching the root target (aka the app) performs better. As a consequence, the linking phase always happens locally but with the optimized linker (e.g. zld), we get acceptable results.

  2. To verify why the root target doesn't contain any dependencies on the Host, on a producer side, you should inspect all .d files generated for the root-level app (let's call it RootAppTarget) (e.g. .../DerivedData/Project/Build/Intermediates.noindex/Project.build/Debug-iphonesimulator/RootAppTarget.build/Objects-normal/arm64.*.d. Does it list anything from Host's module? If not, maybe you could shed more light on the RootAppTarget and Host context (static/dynamic, library/framework, how do you import Host - @import, #import, import etc.).

ahmednafei commented 2 years ago

Our RootAppTarget does not contain any code actually except main.m that do import Host module.

Host module is a staticLib and is imported with @import Host; inside main.m. Although I can see that main.d file does not contain any dependency on Host module

polac24 commented 2 years ago

Our RootAppTarget does not contain any code actually except main.m that do import Host module.

Similar to what we have - really recommend not enabling XCRemoteCache for that target.

Host module is a staticLib and is imported with @import Host; inside main.m. Although I can see that main.d file does not contain any dependency on Host module

Just to double check: that is on a producer side, right?

ahmednafei commented 2 years ago

Just to double check: that is on a producer side, right?

Yes.

polac24 commented 2 years ago

I quickly built a sample project and in.../DerivedData/PP/Build/Intermediates.noindex/PP.build/Debug-iphonesimulator/PP.build/Objects-normal/arm64/SceneDelegate.d there is Host-Swift.h listed.

PP.zip

Sidenote: The project doesn't use XCRC but on the producer side, compilation always happens locally.

polac24 commented 2 years ago

I thought about that and since you have only main.m (not main.swift), compilation dependencies will only contain -Swift.h (which is often the same). Thus, you cannot use cache for the "root" target.

That is a limitation (for now) in XCRemoteCache, will add that to the Readme.md.