spotify / XCRemoteCache

Other
825 stars 50 forks source link

Missing file Swift.h.md5 when building on consumer side #179

Open iSalah opened 1 year ago

iSalah commented 1 year ago

My integration setup:

Description

When building FrameworkA on consumer side, in the "RemoteCache_prebuild" build phase, the "xcprebuild" binary logs this error:

Prebuild step failed with error: missingFile(file:///Users/me/Library/Developer/Xcode/DerivedData/MyApp-hcdhdsaluzstendufballcumqkgv/Build/Products/Debug-iphonesimulator/FrameworkB.framework/Headers/FrameworkB-Swift.h.md5)

The README says I should move the "*-Swift.h.md5", but I'm not sure how and if it's even needed with the automatic integration.

Am I missing something ?

Other

Environment

polac24 commented 1 year ago

Hi! First, am I right that an error in Xcode that fails the entire build?

For frameworks, that (edge case documented in #149) should be automatically handled, but only if the FrameworkB was taken from remote cache - can you double check if that is a case for your? _If FrameworkB was not taken from cache, but built locally

  1. If so, in /Users/me/Library/Developer/Xcode/DerivedData/MyApp-hcdhdsaluzstendufballcumqkgv/Build/Products/Debug-iphonesimulator/FrameworkB.framework you should see both Swift.h and -Swift.h.md5
  2. These files should be taken from the zip artifact of FrameworkB. Can you check its content (e.g. from ~/Library/Caches/XCRemoteCache/.... local cache)?
polac24 commented 1 year ago

These files should be taken from the zip artifact of FrameworkB.

That might be unclear, so here is what I mean:

  1. Does the file -Swift.h (in the zip artifact) contain some absolute paths in the content? I would assume it just contains a placeholder $(SRCROOT) like :
    #import "$(SRCROOT)/FrameworkB/FrameworkB-Bridging-Header.h"
  2. Does the file -Swift.h.md5 (in the zip artifact) exist next to the -Swift.h? I assume not.

Having a small sample app that demonstrates your setup would be helpful (but not absolutely required).

_Sidenote: This is an edge case with NSENUM exposed from ObjC to Swift, so if possible I recommend rewriting that enum(s) to Swift (if possible).

iSalah commented 1 year ago

Thank you @polac24 for your help, answers below:

First, am I right that an error in Xcode that fails the entire build?

No, Xcode builds just fine, I've updated the xcprebuild binary to print messages to the stdout so I can see the logs directly from the build output within xcode.

For frameworks, that (edge case documented in https://github.com/spotify/XCRemoteCache/pull/149) should be automatically handled, but only if the FrameworkB was taken from remote cache

Yes, FrameworkB is taken from remote cache (I can see it from the xcprebuild logs that it had downloaded and unzipped the artifact). I've downlaoded the zip from the server, it only contains the "-Swift.h", but not the "-Swift.h.md5". The -Swift.h doesn't have any absolute path, no referece to $(SRCROOT) either. It does import the umbrella header though: #import <FrameworkB/FrameworkB.h> which is not present in the .zip.

Having a small sample app that demonstrates your setup would be helpful (but not absolutely required).

Before posting this issue, I've created a sample app with minimal code (objc and swift code + ns_enum), but unfortunately I don't reproduce this issue in that sampleapp.

polac24 commented 1 year ago
  1. I looked into the flow for the .framework scenario and this is how the .framework directory should look like (in DerivedData) if it has been correctly taken from cache (on a consumer side). Can you verify if the FrameworkB-Swift.h.md5 exists there (both in Intermediates and Build dirs)?
image image
  1. Also, to be 100% sure that a FrameworkB has been taken from remote cache, you should check if it prints in Xcode "[RC] Cached build for FrameworkB", like here:
image

There are cases where XCRC finds something off at the very last moment, after downloading the zip artifact.

iSalah commented 1 year ago

Oh I'm sorry, it turns out the cache is disabled in the postbuild phase so that's why the -Swift.h.md5 file is missing.

I tried to find out why it's not using the cache, it seems that the "rc.enabled" file is missing in the FrameworkB build dir. The FrameworkB prebuild phase does have the rc.enabled in output files:

image

Any idea why it's not generating the rc.enabled file ?

iSalah commented 1 year ago

I've added some logs and I'm getting progress with this issue: The rc.enabled file is created at prebuild phase, but it is removed by the "Compile sources" phase.

It's like this compilation phase is cleaning the $TARGET_TEMP_DIR before building the framework target. I've made a dirty fix which moves the rc.enabled file after the prebuild phase and move it back in after the compile, now Xcode prints "[RC] Cached build for FrameworkB".

polac24 commented 1 year ago

rc.enabled is a discrimination file and in some cases, it is expected that it is deleted by the compilation. I would carefully inspect all logs, e.g. log show --predicate 'sender BEGINSWITH "xc"' --style compact --info --debug -last 10m after a build to see which unexpected event has happened. If you cannot find anything in logs, then probably the rc.enabled is deleted by xccc file (it is a plain C programand doesn't report any errors to log). The template you can find here