Closed cezarsignori closed 2 years ago
Hi! I think I know why it is happening that let me just verify:
Networking
is a hybrid target, where some ObjC files import its own Swift API via #import "Network-Swift.h"
?I saw that it is caused becaused your Network-Swift.h
is placed in ...buck-out/xcode/derived-sources
. XCRemoteCache doesn't know that it is a file coming from DerivedData
.
It is an interesting step to move -Swift.h
PBXCp
from DerivedSources to back-out
, probably you need it for some other integration. To workaround, you could move xcpostbuild
before that Copy step
on a producer side. Most likely that will eliminate -Swift.h
from the meta as XCRemoteCache will realize that this file is special - comes as a derived product of the target itself.
Hi @polac24 !
Yes, Networking
is a hybrid target where some ObjC files import its own Swift API via #import "Network-Swift.h"
and the problem only happens on the consumer side.
I moved the xcpostbuild
before the Copy step
on the producer side for Networking
and the result in the consumer side was the same.
The Copy step
(called Fake Swift Dependencies
) is actually copying 3 static libraries and has destination set to Products Directory
.
Just in case, I also moved the Copy step
from the DMLProtoShowdown
target that copies the OTPublishersHeadlessSDK.framework
to Frameworks
(listed in the error message) after the xcpostbuild
step. Again, the same error message showed up on the 2nd build of the consumer.
If Fake Swift Dependencies
moves only 3 static libraries and does nothing with Networking-Swift.h
, then you need to find the step that is responsible for that:
command: target-Networking-f5133eebb2ffb8190194ce0ce8a1ee02a28b59ec223466b45be229c4860cfbd9-:Debug:PBXCp /Users/csignori/Library/Developer/Xcode/DerivedData/DMLProto_Showdown-fnyfbyrumovpfnfvglkwmudrshgr/Build/Intermediates.noindex/Networking.build/Debug-iphonesimulator/Networking.build/Objects-normal/arm64/Networking-Swift.h /Users/csignori/Projects/iphone/{project}/Modules/CoreModules/buck-out/xcode/derived-sources/Networking-720ecdc4254a9a596d1698dc8a91303c9363b022/Networking-Swift.h ->
It looks like a very custom setup.
How to troubleshoot? On a producer side, after a successful build of the Networking
target, open /Users/csignori/Library/Developer/Xcode/DerivedData/DMLProto_Showdown-fnyfbyrumovpfnfvglkwmudrshgr/Build/Intermediates.noindex/Networking.build/xccache/produced/{hash}.json
(or similar) and see if there is Networking-Swift.h
listed. It shouldn't be. If still have it, find the culprit of the cp
step mentioned above and try deferring it a bit (reorder).
disable_vfs_overlay: true
in .rcinfo
eliminates the problem?Hi!
Yes, I find Networking-Swift.h
listed in the json file as "$(CORE_MODULES_BUCK-OUT)\/xcode\/derived-sources\/Networking-720ecdc4254a9a596d1698dc8a91303c9363b022\/Networking-Swift.h"
.
However I cannot find any xcodeproj
files with explicit PBXcp
for that file. Nor manually looking at Build Phases nor for example via find . -type d -name '*.xcodeproj' -exec grep -r "Networking-Swift.h" {} +
. It seems like Xcode is doing it automatically and dynamically.
Isn't it showing up in the json file because that's the header which makes the Swift API in the module available to Objective-C code?
disable_vfs_overlay: true
does not eliminate the problem.
Hello!
There are many places in an Xcode project where the destination location can be customized. Without a project to review, it would be very difficult to guess.
Nevertheless, let me try: does your Networking
target have a custom build setting that overrides Xcode's default location? Here is a non exhaustive list of settings that could potentially cause that:
DERIVED_FILES_DIR
DERIVED_FILE_DIR
DERIVED_SOURCES_DIR
OBJROOT
PROJECT_DERIVED_FILE_DIR
PROJECT_TEMP_DIR
PROJECT_TEMP_ROOT
SHARED_PRECOMPS_DIR
TARGET_TEMP_DIR
TEMP_ROOT
TEMP_FILE_DIR
TEMP_FILES_DIR
CONFIGURATION_TEMP_DIR
Hi! From my investigation I found out that this integration issue between Buck <> XC-RC is because of the following:
When Buck generates the xcodeproj file, it does not populate the “Dependencies” build step with the target dependencies and relies on HEADER_SEARCH_PATHS
instead (implicit dependencies).
For mixed modules, Buck sets DERIVED_FILES_DIR
build setting to point to a location inside buck-out
directory, so during the compilation step, the ./buckw generate <project>
phase Buck creates symlinks to the source header files (and to buck-out/gen/_p/<module-dir>-pub
folder. These symlinks point to the location of header files inside module source code (symlink of DERIVED_FILES_DIR
build setting defines where the compiler generates and finds the
The dump issue that buck has is that it hard codes the symlink of module>-Swift.h during the project generation phase to the default location of where buck sets DERIVED_FILES_DIR
value. So any try to change the value of DERIVED_FILES_DIR
while make the generated link is invalid, and will make any module that depends on that mixed module fails to import that mixed module (because simply any module that depends on that mixed module would have buck-out/gen/_p/<mixed-module-dir>-pub
added to HEADER_SEARCH_PATHS and it will only see an invalid symlink).
The Buck <> RC integration issue is mainly happening because buck sets DERIVED_FILES_DIR
to a location inside 'buck-out' which is outside the DerivedFiles
folder where RC expects any buck-out
is an auto-generated file during compilation so it lists it in the meta file where it should not do.
The issue is solved on my side by overriding DERIVED_FILES_DIR
value to a new location inside DerivedData
folder, during project generation phase and at the same time adding build-step for each mixed module that has internal import to <module>-Swift.h
generated by buck, so any module depending on mixed module would be able to find the new location of <module>-Swift.h
. Also RC now is aware that <module>-Swift.h
is an auto-generated file so it does not include it into meta file.
Thanks for a context, your workaround makes sense.
XCRemoteCache can be smarter and also inspect DERIVED_FILES_DIR
when looking for intermediate files (right now it only classifies files in TARGET_TEMP_DIR
):
https://github.com/spotify/XCRemoteCache/blob/963e6858ee31d750b2a3cae65c37cf31f279d5d0/Sources/XCRemoteCache/Dependencies/DependencyProcessor.swift#L78-L79
The fix should be simple:
PostbuildContext
DependencyProcessorImpl
if
thereLet me know if you would like to contribute.
_In the future, we could make the classification configurable (which ENV directory points to the directory with given dependency kind) but for now, adding only DERIVED_FILES_DIR
makes sense._
My integration setup
[X] Automatic integration using
xcprepare integrate ...
Expected/desired behavior
The application build succeeds every time I hit build without making changes after a successful build.
Minimal reproduction of the problem with instructions
Step 1. Integrate XCRemoteCache with the application using the automatic integration method; Step 2. Run
rm -rf ~/Library/Developer/Xcode/DerivedData
andrm -rf ~/Library/Caches/XCRemoteCache
; Step 3. Build the application (success) Step 4. Build the application (failure).Consumer Logs
Environment
Post build stats
Others
I am on an Apple M1 Max with macOS Monterey 12.2.1 (21D62).
I am testing RC 0.3.7 on small application with 70 dependencies (across my own modules, git submodules and Pods committed to the repo).
Each xcodeproj has an associated manually created
.rcinfo
file with the following content:The first build succeeds, and then the second fails with the following error:
DMLProto_Showdown
is my application workspace andNetworking
is one of the dependencies.Without integrating RC, Xcode always/consistently succeeds in building the same application.
DMLProto_Showdown
does not depend onNetworking
(though some of theDMLProto_Showdown
dependencies do) andNetworking
does not depend onDMLProto_Showdown
. The cyclic dependency issue seems to be introduced by RC and is related to the build steps of the targets involved.