Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Xcode 13(.1) support - CMake pre-build phase #1196

Closed
turekj opened this issue Dec 2, 2021 · 5 comments
Closed

Xcode 13(.1) support - CMake pre-build phase #1196

turekj opened this issue Dec 2, 2021 · 5 comments
Labels

Comments

@turekj
Copy link

turekj commented Dec 2, 2021

Hello everyone!

We've been using gluecodium successfully for our iOS/Android project up to the point when Xcode 13 was released. Our setup is that we generate the iOS framework containing C++ sources and gluecodium generated Swift interfaces for that. The cmake generated project (with gluecodium steps) is later added as a subproject to the main project.

Xcode 13 introduced a new regression (feature?) that causes all code-generation libraries to malfunction. In short, the build indexing for Xcode (that's running in parallel to the regular build) now triggers all the build phases, causing the regular builds to fail if indexing is happening at the same time. More details can be found here.

The solution to this problem is to check the environment variables for the value of $ACTION. The value of indexbuild means that the step was run as a part of the indexing mechanism, thus we shouldn't generate the code.

I think that gluecodium should have a similar check implemented. I'd like to contribute to building this. However, I'm not sure what's the best place to have that check implemented.

Initially, I thought about the gluecodium main function. However, runGenerate.cmake also seems like a viable option and fits the scheme even better since it's a part of the build phase script that's executed.

Can you please help me figure out where this check fits and also how do you expect me to test whether this is working properly? Any help is much appreciated.

@DanielKamkha
Copy link
Contributor

@Hsilgos, do we have the same issue for internal Xcode builds?

@Hsilgos
Copy link
Contributor

Hsilgos commented Dec 3, 2021

Hi @turekj , thank you for your interest. We didn't see such issue with Xcode 13(.1) so far. Which cmake do you use? May be you can provide small example?
According to your description the best place should be runGenerate.cmake, yes. May be something should be added to AddGenerateCommand.cmake.
You may add your test case to our unit tests for cmake scripts and run them like
GLUECODIUM_BUILD_ENVIRONMENT=ios-x86_64 ./run-cmake-unit-test.cmake

Unfortunately we don't run those tests on CI because it takes too long for Xcode. You may also specify filter to run only your test with environment variable CTEST_FILTER="regex-filter".
There are known unit tests failures related to dart

@DanielKamkha DanielKamkha assigned turekj and unassigned Hsilgos Dec 3, 2021
@turekj
Copy link
Author

turekj commented Dec 3, 2021

@Hsilgos We're currently on cmake 3.21.4.

Unfortunately, it's unlikely that I'm able to provide a small example. The problem is that:

  • The issue is time-sensitive. The indexing must kick in at the exact time the build is happening*.
  • The problem is hit-or-miss. We've identified it's happening with ~5% of our builds but there are periods where you can make 20-30 consecutive builds with no issue.
  • I suppose that the complex project setup can heavily accelerate indexing issues with Xcode. In our project, the main target consists of Swift, Objective-C(++), C++, external libraries added with cocoapods & the C++ framework powered by gluecodium. The project containing gluecodium-powered framework is generated using cmake and added as a subproject to the main workspace. The framework is later added as a dependency to the main target. This setup had 100% build success rate at Xcode 12.
  • Cocoapods might play a factor because they offset the time when gluecodium is run. The pods are compiled first and then the framework is generated and compiled.

What I can offer is:

  • A video showcasing the issue happening for us. It manifests itself with (target)_main_cglue.cpp file not compiling, the error is that's one of the included files is missing. The subsequent build is usually fine. Our investigation led us to believe that it's caused by the generation script ran from within the indexing job that clears the build directory and re-generates the files. I can also couple it with logs that prove it's what causes the issue.
  • A blank project that mimics our gluecodium setup (workspace + framework coming from a subproject). I'll set it up the way you can verify that gluecodium is also triggered by indexing as of Xcode 13. Although, I'd prefer to spend my time patching the problem. Afterward, you'll decide whether you want to merge that patch.

@Hsilgos thank you for pointing me how to run the tests, that's greatly appreciated and will help me do a meaningful contribution. 🌮

* - the indexing might be triggered due to the way our project is set up. It's impossible to verify, though. 😢

@Hsilgos
Copy link
Contributor

Hsilgos commented Apr 13, 2023

@turekj , do you have any update regarding this issue? Do you still have it in latest Xcodes?

@turekj
Copy link
Author

turekj commented Apr 14, 2023

@Hsilgos thank you for following up. We have not resolved the issue. However, we can no longer reproduce it as we had to alter the project architecture. Yet another issue popped up with our original approach and forced us to do the switch.

The original approach was:

Main project workspace:
    - Application Target
        - C++ framework target (generated by Gluecodium Cmake and imported as an Xcode project dependency)

so that the framework was built alongside the main target of the application. However, with recent build optimizations at Xcode, we encountered two major issues:

  1. The issue with build failing due to indexing I've originally mentioned. The build would fail as the parallel index build would re-generate the files.
  2. The compilation times were very long. I've investigated the problem and I found out that the .modulemap replacement that happens as a part of the build step is throwing the compiler off and making incremental builds of the framework hit or miss.

I tried various approaches for the .modulemap patching, for example never deleting it and replacing the file contents but I never really got to the bottom of incremental build problems and was just sinking time there.

As a result, I decided to migrate the C++ framework target to be independently built as a .xcframework.

Main project workspace:
    - Application Target
        - Binary dependency on the C++ framework

C++ library workspace:
    - Framework Target

Shell script to build C++ library as .xcframework

This approach resolves all the issues:

  1. Indexing issue is not a thing as we're never opening C++ library project and it's a single target project so no parallelism.
  2. Incremental builds are not a thing as we're always doing a full clean build of the .xcframework when changes are made.

I'll close this issue as I have no insight on how to make the original architecture work.

@turekj turekj closed this as completed Apr 14, 2023
@turekj turekj removed their assignment Apr 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants