iOS Build Environment Help Center

Problems Building a fresh project containing only Nineva GoogleMaps Plugin

append delete Stefan Vasilev

Windows version: 10
Builder version: 3.62 (clang 16.0.0, swiftc 5.9.1, lld 16.0.0, ld64 907-20231214)
iOS SDK version: 17.4
Link to build log: See below

Hey there Pierre! Long time no chat - but here I am getting back in business with a couple of issues (as usual). Since we all know Apple forces us now to update to SDK 17 - this is what I did. This triggered the update of my GoogleMaps Plugin (https://assetstore.unity.com/packages/tools/integration/google-maps-view-82542)
I am having nightmares building this thing using the Builder. I started a fresh project and I included only this plugin to isolate the problem. I will also write a mail to you with a zip to the Unity project as well as the exported folder and some frameworks (see below). I will outline the several problems that I went through while building and what workarounds I managed to make and what I need help with:

1. I installed the latest version of the builder and I used a friend's Mac to migrate the SDK - 17.4. When I used the Step 2 Script I noticed an error that stated "The system cannot find the path specified" (See this https://pastebin.com/GhWHFEaP) but the process actually finished and the SDK was successfully extracted. I opened the script and removed @echo off so I had more logs - see them here: https://pastebin.com/bzs5W9fh The Mac that we used has the following specs:
Darwin GNXCY7D1WX 23.4.0 Darwin Kernel Version 23.4.0: Wed Feb 21 21:45:49 PST 2024; root:xnu-10063.101.15~2/RELEASE_ARM64_T6020 arm64 arm Darwin

I am not sure if any of this is of importance to the rest of the problems but I thought it is important to share for future improvements of the Builder

2. After I updated the plugin and started building I had some errors for headers that are included but cannot be found. So I contacted the developer of the plugin and he said that they updated the way libraries are built/layed out in the project. He told me that for him, on XCode the libraries are linked normally (and the project builds) and advised me to try to link them manually with the Builder. I tried the "Add extra framework" but since the libraries in the plugin are now ".xcframework" instead of just ".framework". I got the error: "This .xcframework directory doesn't seem to support the platform (iOS) and/or architecture(s) for which you are building". Thankfully, I had the previous version of the plugin still on my drive so I used the old ".framework" directories (they are 3 and I will add them to the .zip file that I will send you so you can analyze them and build the project). I don't like this workaround since the developer will continue to update the plugin and I will sooner or later hit a blocker. I really need to know how and if I can link the "xcframework" directories.

3. After the above workaround the build continued but hit the next error: https://pastebin.com/TXUHkDUL I browsed the web and I saw that I can just replace nil with the digit zero. So I edited the plugin myself (in two places) and the build succeeded. I really need to know if there is a compiler flag or something that will help in this case. The developer of the GoogleMaps plugin confirmed that he does not get such errors while building in XCode.

4. After this clown-fest of workarounds I almost cried when the App actually crashed when opening the GoogleMapsDemoScene. I enabled the remote debugger and inspected the error: https://pastebin.com/NAf67Y1p . I asked the developer of the plugin if he is sure that the App doesn't crash on his iPhone when he builds the DemoProject and he confirmed that it doesn't crash but he tested it only in the simulator. This seems like a very low-level API error that I don't even know or have control to fix.

So I am at a loss here - I have very little time to find proper solutions for problems 2,3,4 (and possibly 1, if related). I know that you have a Mac and probably you will be able to compare the differences when building with XCode. I have faith in you and I hope you can raply soon :)

Reply RSS

Replies

append delete #1. Pierre-Marie Baty

Hello and sorry for the delay of my reply. That was a long message so I thought I'd need time to address it properly and unfortunately time is rare these days.

Anyway. About 1, that's a benign warning. It means that your SDK doesn't need the "fix" described in the bit of code you spotted. Thank you for reporting it, I'll add more checks so that it doesn't happen again.

About 2. I confirm that the builder can digest .xcframeworks as well as .frameworks, but the only mandatory condition is that the .xcframework must contain at least one variant of the framework that is usable with a real iOS device. Basically, .xcframeworks are a bundle of several variants of the same framework for different targets. For example you can have one variant for iOS simulator, one variant for iOS/arm64, one variant for macOS/arm64 and another one for macOS/x86_64, another one for tvOS, etc. So if you get this message it's likely that the .xcframework you want to instruct the builder to use doesn't have any usable variant for it. Open the .xcframework's Info.plist and make sure it has a variant for iOS/arm64 (and not the iOS simulator). If it doesn't, you'll need to go and look for another one. Perhaps you simply downloaded the wrong one.

About 3. "nil" in Objective-C is semantically a *pointer* to address zero. It's not "just" a zero, even if it looks exactly the same when loaded into a 64-bit register. So, using "nil" in place where an integer value is expected (actually, an enum, but enums are integers) is wrong, code-wise, and the compiler is right to complain. If Xcode doesn't, it means the compiler is allowed to ignore semantic differences between pointers and pointees, and to "cast" any pointer address value into an integer without complaining. This is controlled by the -Wno-int-conversion compiler flag. Try adding it and see if the error goes away.

About 4. The crash happens in libsystem_platform.dylib. It's a low-level library, part of the iOS implementation of the standard C library which is called libSystem. So I'd guess your app does some nasty type confusion somewhere and calls some API passing it a bogus parameter of the wrong type, which is relayed all the way down to the C library. And indeed I see a warning:

%
Apr 04 18:36:23.434 RemoteConsole <stderr>: 2024-04-04 18:36:23.252 LUNAR[26900:11096806] *** -[NSMutableArray addObjectsFromArray:]: array argument is not an NSArray
%

I can't guarantee that it's the cause of the crash, but it's compatible with the symptoms, I'd say. Good luck :-)

P.S. There are a few compiler flags that actually allow automatic transformation of values into other types transparently. These flags are generally dangerous because they tend to hide more problems than they solve, but it's possible your project uses one. If Xcode can build your project without complaining, and if it works on a real iOS device without crashing, it would be interesting to see the Xcode build log and find out which flag is used that makes everything behave correctly.

#2. Stefan Vasilev

This post was deleted by its owner

append delete #3. Stefan Vasilev

Hello, after 4-days-worth of additional investigation and also renting a MacInCloud I think I have a better understanding of what is going on but let's continue this reply in a more structured manner.

About 1: Okay - I suppose I should treat this error as false-positive (or at least not related to my issues). Thanks for looking into that and that you will update it in the next version of the Asset

About 3: Yeah, I did my research about nil in ObjC but I couldn't find a proper flag to disable this behavior - your proposition worked! I used the *-Wno-int-conversion* flag and the build succeeded - kudos to that! Unfortunately, the crash still remained.

About 4: Unfortunately, at the time of writing I shared a log from my App - LUNAR but I later realized that I should share the log from the fresh project that contains only the GoogleMaps Plugin that crashes as well. The log is pretty similar but the "array argument is not an NSArray" errors are not present so the problem is a bit different (read the next point for a better understanding of the actual problem)

About 2: The frameworks I used with "Add Framework" are .xcframeworks which come bundled with the Nineva GoogleMaps Plugin. I double-checked the .plist and confirmed that they contain a variant for iOS/arm64. Just in case, I even downloaded the official .xcframeworks from Google from this link: https://developers.google.com/maps/documentation/ios-sdk/config#manual-installation You can try downloading the `GoogleMaps`, `GoogleMapsBase`, `GoogleMapsCore` since this is what is used by the plugin. Each of them gives me the "This .xcframework directory doesn't seem to support the platform (iOS) and/or architecture(s) for which you are building" error. And here comes the problem - when I saw this message 4 days ago, I decided to link the older .framework libraries which definitely caused a mismatch, thus this low-level error is produced. So, I am currently investigating why this .xcframeworks are not recognized by the Builder. *And this is what I really need help with*

In the meantime, I was able to download Unity on a Mac and create the exact same project with the same plugin, Export from Unity to XCode, and Build and run it successfully without the crash on my Device. I wasn't able to Export the project on Windows and then Build it on the Mac in XCode - I am getting weird errors for which I contacted the Developer of the Plugin and he said that he will investigate when he has time but he mainly supports the Mac-Only Pipeline.

Here is a link to the fresh project with only the plugin added - you can test to see what prevents the Builder from adding the .xcframeworks: https://drive.google.com/file/d/1h93QScIwhf_yh6-QOuAN-NYGgjOlb6cf/view?usp=sharing

:: @Stefan Vasilev added on 17 Apr ’24 · 20:53

Appendix: I tried building with Shift+Click on the Build Button to get a more verbose log. You can find it here: https://pastebin.com/SWvAJFrv

It looks like the .xcframeworks are actually passed as flags with the correct paths but somehow the build produces this error:

```
In file included from Libraries\GoogleMapsView\Editor\Libs\iOS\ObjC\Google-Maps-iOS-Utils\Geometry\Model\GMULineString.m:16:
Libraries/GoogleMapsView/Editor/Libs/iOS/ObjC/Google-Maps-iOS-Utils/Geometry/Model/GMULineString.h(18,9): fatal error: 'GoogleMaps/GoogleMaps.h' file not found
#import <GoogleMaps/GoogleMaps.h>
```

Note: I tried with the *-ObjC* Extra Linker flag and also tried disabling the LLVM linker but with no luck. Could it be that it is not a linker issue but some other flag needs to be added

append delete #4. Pierre-Marie Baty

Hello Stefan

So I found the problem. These .xcframeworks are supplied as *static libraries* (e.g. "GoogleMaps.xcframework/ios-arm64/GoogleMaps.a") instead of the typical dynamically-linked frameworks (e.g. "GoogleMaps.xcframework/ios-arm64/GoogleMaps.framework/GoogleMaps"). And the builder UI checks for the presence of a dynamic framework in the selected .xcframework, doesn't find any, and signals the error you get. I have to update the builder UI code (and possibly the Apple and LLVM linkers code too) so that static .xcframeworks are supported.

I'll be right back with news on this topic.

append delete #5. Stefan Vasilev

Hey Pierre, you are on the right track and I learned what you described the hard way - with a lot of trial and error that I will now share for future developers and for me as well :) I think that if the Builder supports Static Library linking everything will most probably work but there are a few details that I will share that might help you catch an additional issue that could be present even with Static Library linking.

Soo, this is the journey that I went through...

1. After I was sure the Builder understands that the .xclibraries are linked properly (the produced XCode project from Unity has them embedded) I was sure that the Builder just doesn't understand the folder structure correctly (or as you said was expecting dynamic linking instead of static)

2. I decided that I need to find the newest Google Maps SDKs that were not using .xcframeworks but were using .frameworks. It turned out that version 8.3.1 introduced .xcframeworks (see here: https://developers.google.com/maps/documentation/ios-sdk/release-notes) so I was aiming to download 8.3.0 which turned out to be much harder than expected (it wasn't just available online). I tried different methods - like installing it from XCode Package Manager on a new XCode project, etc. but the only thing that worked was installing Cocoapods on the Mac and writing a Podfile that downloads GoogleMaps 8.3.0

3. To my surprise, it still produced .xcframeworks but the folder structure in these .xcframeworks was more similar to what you was explaining it should be (having dynamic libraries under GoogleMaps.xcframework/ios-arm64/GoogleMaps.framework). So I decided to give it a go! I deleted the .xcframeworks from the Plugin folder in the Fresh Project (GoogleMapsView/Editor/Libs/iOS/Frameworks) and pasted the new ones (8.3.0). The build failed just at the end linking phase which meant I was making progress. *And this is where I think you should double-check what is happening* - I think this is a second issue that the builder does not properly link these when they are embedded in the XCode project on Export (the Nineva Google Maps Plugin embeds them). Here is how I proved that:

4. The Builder was actually now accepting the new .xcframeworks (8.3.0) so I tried to forcefully add the 3 .xcframeworks using the "Add extra framework" Button (even though the Nineva Google Maps was adding them in a BuildPostProcessingScript.cs). The Builder asked me if I wanted to include the additional libraries that these frameworks are referencing so I said YES to all the 3 .xcframeworks. *Then everything built properly and the App was not crashing on my iOS Device ANYMORE!*

5. Out of curiosity, I tried to copy the .frameworks OUT of the .xcframeworks. For example, I copied the GoogleMaps.xcframework/ios-arm64/GoogleMaps.framework and directly add it in the Nineva Google Maps folder (instead of the .xcframework). I did that for the other 2 .xcframeworks. I also, needed to change the code of the Nineva BuildPostProcessingScript.cs because it was expecting to add .xcframeworks. *And everything WORKED with this second approach AS WELL!* I didn't need to add extra frameworks in the Builder or anything

I am super curious to hear what your solution will be and I will stay tuned whenever you come up with a new version. The reason being - even though I can build and run the App at the moment on Windows, I am worried that I am using the 8.3.0 Maps SDKs but the Nineva Google Maps Plugin is expecting it to be 8.4.0 - this could potentially produce a Crash in certain scenarios - like before. Currently, I think I am just lucky that 8.3.0 and 8.4.0 are not too different :)

append delete #6. Pierre-Marie Baty

What you did was quite a hack, actually ; you took the compiled binary of a *previous* version of a framework (that was compiled dynamically) and put it in place of the compiled binary of a *newer* version (that was compiled statically), while keeping the header (.h) files associated with the newer version. This has chances to work (and your experiment showed it did in that particular case), but very often will cause problems, because it won't account for API changes in the library. For example if Google decided to swap the order of two parameters in a function provided by their libraries, the new header files would tell the compiler how to deal with it, but the linked framework would still have the old function with the reversed parameters order. And this would cause a crash.

A more suitable hack, if you want to go this way, would be to simply take apart the .xcframework that contains the static library, as well as its associated Headers directory, and add these paths to the compiler and linker flags like this:

% extra compiler flags:
-I"path/to/the/framework/Headers/dir"
%

and

% extra linker flags:
"full/path+name/of/the/framework/.a/file"
%

:: @Pierre-Marie Baty added on 18 Apr ’24 · 19:45

*edit* Anyway, the right thing to do is for the builder to swallow statically linked .xcframeworks, and I'm working on that. Also, take note that according to Google's instructions, to use Google Maps you also need to embed the GoogleMaps.bundle directory in your app - use a pre-packaging script for that (I assume you already figured it out).

:: @Pierre-Marie Baty added on 18 Apr ’24 · 20:21

*edit 2* I got your project to build without modifications using the version I'm working on. It seems to work so I'll release an update soon.

#7. Stefan Vasilev

This post was deleted by its owner

append delete #8. Stefan Vasilev

Thank you very much for the fast reaction! I am not really sure about the `.bundle` situation, though. Since I am using version 8.3.0 currently I think it does not have the bundle or at least does not need it. All these changes and requirements are from version 8.3.1 onwards.

Anyways, super glad that you've been able to build and run it successfully! GOOD JOB!
I am staying tuned for the new version of the Builder :)

append delete #9. Pierre-Marie Baty
append delete #10. Stefan Vasilev

This is what I am trying to say - I think this requirement came with 8.3.1 onwards and I am using 8.3.0 which dodges the bullet. But I am not entirely sure.

Since you are currently building and running my example project (it has 8.4.0 Google Maps SDKs) - I am interested to know how are you handling the .bundle folder - how are you instructing the folder to be added to the root folder of the XCode project?

append delete #11. Pierre-Marie Baty

See step 10 of the documentation: https://www.pmbaty.com/iosbuildenv/documentation/unity.html#prepkgscript

Just a batch script calling xcopy or robocopy, or whichever directory copy tool you're most familiar with.

append delete #12. Stefan Vasilev

Hey Pierre! I downloaded your new version like hot bread and can confirm that now the App builds and runs properly with Google Maps 8.4.0 - so thank you very much! I also didn't even need to use the *-Wno-int-conversion* compiler flag in "Extra compiler flags" - I see that you've added it as a default flag in *build.cmd*. Cool!

There are several things that I am currently struggling to understand but are not blocking my development. In order to build successfully, I still need to manually add the 3 .xcframeworks with the "Add extra frameworks" Button. This shouldn't be necessary because if I open the project that I sent you in XCode these libraries are already linked because the *GoogleMapsIosProjectPostprocessor.cs* that comes bundled with Nineva GoogleMaps Plugin does exactly this job (you can check it yourself - here is the link to the Unity Project: https://drive.google.com/file/d/1WKjGBB7RwKXHuFJqURndqiz-_GgWpkLF/view?usp=sharing - I am using Unity 2022.1.23f). I wonder why the Builder does not catch this detail? You can see that these are included if you open the *project.pbxproj*. I also think that the *GoogleMaps.bundle* is also instructed to be copied in the root directory because it is also described in the *project.pbxproj* and this is why it doesn't fail for me even if I don't copy it? Keep in mind that the project I sent you seems to have paths that are specific to my system so this is why it probably does not work for you out of the box. I advise you to build it yourself using the Unity Project I sent you (so your paths are properly hardcoded in *project.pbxproj*

Cheers!

append delete #13. Stefan Vasilev

For future developers: For some reason, the GoogleMaps.bundle is no longer embedded in my *project.pbxproj* so in one of my recent deploys my App Crashed again on GoogleMaps - I enabled the Remote Debugger Console of the Builder and saw in the log that now I have a warning that *GoogleMaps.bundle* is not found so I decided to use the Pre-Packaging script as you suggested. My script is pretty simple and with it, I was able to run my App without crashing ONCE MORE! Here is the whole script (yes, it is that simple):

robocopy C:\Users\theso\Desktop\GoogleMaps.bundle "%TARGET_BUILD_DIR%\%NAME%.app\Frameworks\UnityFramework.framework\GoogleMaps.bundle" /e /NFL /NDL /NP /NS /NC

I wonder what does your script look like - I feel this is a weird directory to copy the Bundle to but I reverse-engineered it from the fresh project that I sent you

Reply

(Leave this as-is, it’s a trap!)

There is no need to “register”, just enter the same name + password of your choice every time.

Pro tip: Use markup to add links, quotes and more.

Moderators: Pierre-Marie Baty