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

How to add the MapBox iOS framework with source code as an Xcode target to my project instead of a precompiled binary #578

Closed
Ernest0-Production opened this issue Dec 7, 2022 · 14 comments
Labels
documentation Improvements or additions to documentation iOS

Comments

@Ernest0-Production
Copy link

Hi! 👋

I'm trying to figure out how to connect the library manually to my project.

I was planning to make a fork of MapLibre and connect it as a sub-module to my application and then add it as a target in the Xcode project.

But after reading INSTALL.md and DEVELOPING.md I still don't understand how to do it.:

  • According to the instructions make iframework creates an already compiled product MapBox.framework.

  • The command make iproj created a separate Xcode Project MapLibre GL Narive and then in the case of the application creates a Framework dynamic, which apparently I need. But how to properly export or generate it in your project - I found no instructions.

@wipfli
Copy link
Contributor

wipfli commented Dec 7, 2022

Huff the documentation is really something we would like to improve. @Ernest0-Production if you find out any good steps, please share them here and if possible, open a pull request to update the readmes. Thanks!

@Ernest0-Production
Copy link
Author

Ernest0-Production commented Dec 7, 2022

@wipfli
I had the idea to move ios.xcproj and Mapbox GL Native.xcproj into the workspace of my project and add dynamic target from ios.xcproj as dependency of my application target.

In theory everything should have worked, but for some reason the dynamic target build crashes with an error:

ld: library not found for -lmbgl-core
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I don't understand much about it, but I decided for the sake of interest to compare what parameters Ld is called with in ios.xcworkspace which was already in platform/iOS:

Ld /Users/ebabayan/Library/Developer/Xcode/DerivedData/MyProject-bgyajkcsaezsvpeqwvzhyewnbjcj/Build/Products/Debug-iphonesimulator/Mapbox.framework/Mapbox normal (in target 'dynamic' from project 'ios')
    cd /Users/ebabayan/Projects/MyProject/maplibre-gl-native/platform/ios/platform/ios
    /Applications/Xcode-13.4.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -target arm64-apple-ios9.0-simulator -dynamiclib -isysroot /Applications/Xcode-13.4.1.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator15.5.sdk -L/Users/ebabayan/Library/Developer/Xcode/DerivedData/MyProject-bgyajkcsaezsvpeqwvzhyewnbjcj/Build/Products/Debug-iphonesimulator -L/Users/ebabayan/Projects/MyProject/maplibre-gl-native/platform/ios/platform/ios -L/Users/ebabayan/Projects/MyProject/maplibre-gl-native/platform/ios/platform/ios/vendor/mapbox-accounts-ios -F/Users/ebabayan/Library/Developer/Xcode/DerivedData/MyProject-bgyajkcsaezsvpeqwvzhyewnbjcj/Build/Products/Debug-iphonesimulator -filelist /Users/ebabayan/Library/Developer/Xcode/DerivedData/MyProject-bgyajkcsaezsvpeqwvzhyewnbjcj/Build/Intermediates.noindex/ios.build/Debug-iphonesimulator/dynamic.build/Objects-normal/arm64/Mapbox.LinkFileList -install_name @rpath/Mapbox.framework/Mapbox -Xlinker -rpath -Xlinker @executable_path/Frameworks -Xlinker -rpath -Xlinker @loader_path/Frameworks -Xlinker -map -Xlinker /Users/ebabayan/Library/Developer/Xcode/DerivedData/MyProject-bgyajkcsaezsvpeqwvzhyewnbjcj/Build/Intermediates.noindex/ios.build/Debug-iphonesimulator/dynamic.build/Mapbox-LinkMap-normal-arm64.txt -dead_strip -Xlinker -object_path_lto -Xlinker /Users/ebabayan/Library/Developer/Xcode/DerivedData/MyProject-bgyajkcsaezsvpeqwvzhyewnbjcj/Build/Intermediates.noindex/ios.build/Debug-iphonesimulator/dynamic.build/Objects-normal/arm64/Mapbox_lto.o -Xlinker -export_dynamic -Xlinker -no_deduplicate -Xlinker -objc_abi_version -Xlinker 2 -stdlib\=libc++ -fobjc-arc -fobjc-link-runtime -lmbgl-core -lz -lmbgl-vendor-csscolorparser -lmbgl-vendor-icu -lmbgl-vendor-parsedate -lsqlite3 -lmbxaccounts -framework GLKit -Xlinker -no_adhoc_codesign -compatibility_version 1 -current_version 15256 -Xlinker -dependency_info -Xlinker /Users/ebabayan/Library/Developer/Xcode/DerivedData/MyProject-bgyajkcsaezsvpeqwvzhyewnbjcj/Build/Intermediates.noindex/ios.build/Debug-iphonesimulator/dynamic.build/Objects-normal/arm64/Mapbox_dependency_info.dat -o /Users/ebabayan/Library/Developer/Xcode/DerivedData/MyProject-bgyajkcsaezsvpeqwvzhyewnbjcj/Build/Products/Debug-iphonesimulator/Mapbox.framework/Mapbox

And noticed that when building from my workspace, the xcode tries link MapBox.framework which is in DerivedData, while in demo workspac MapBox.framework is in /platform/ios/build/iOS:

Ld /Users/ebabayan/Downloads/maplibre-gl-native/**platform/ios/build/ios**/Debug-iphonesimulator/Mapbox.framework/Mapbox normal (in target 'dynamic' from project 'ios')
    cd /Users/ebabayan/Downloads/maplibre-gl-native/platform/ios/platform/ios
    /Applications/Xcode-13.4.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -target arm64-apple-ios9.0-simulator -dynamiclib -isysroot /Applications/Xcode-13.4.1.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator15.5.sdk -L/Users/ebabayan/Downloads/maplibre-gl-native/platform/ios/build/ios/Debug-iphonesimulator -L/Users/ebabayan/Downloads/maplibre-gl-native/platform/ios/platform/ios -L/Users/ebabayan/Downloads/maplibre-gl-native/platform/ios/platform/ios/vendor/mapbox-accounts-ios -F/Users/ebabayan/Downloads/maplibre-gl-native/platform/ios/build/ios/Debug-iphonesimulator -filelist /Users/ebabayan/Downloads/maplibre-gl-native/platform/ios/build/ios/ios.build/Debug-iphonesimulator/dynamic.build/Objects-normal/arm64/Mapbox.LinkFileList -install_name @rpath/Mapbox.framework/Mapbox -Xlinker -rpath -Xlinker @executable_path/Frameworks -Xlinker -rpath -Xlinker @loader_path/Frameworks -Xlinker -map -Xlinker /Users/ebabayan/Downloads/maplibre-gl-native/platform/ios/build/ios/ios.build/Debug-iphonesimulator/dynamic.build/Mapbox-LinkMap-normal-arm64.txt -dead_strip -Xlinker -object_path_lto -Xlinker /Users/ebabayan/Downloads/maplibre-gl-native/platform/ios/build/ios/ios.build/Debug-iphonesimulator/dynamic.build/Objects-normal/arm64/Mapbox_lto.o -Xlinker -export_dynamic -Xlinker -no_deduplicate -Xlinker -objc_abi_version -Xlinker 2 -stdlib\=libc++ -fobjc-arc -fobjc-link-runtime -lmbgl-core -lz -lmbgl-vendor-csscolorparser -lmbgl-vendor-icu -lmbgl-vendor-parsedate -lsqlite3 -lmbxaccounts -framework GLKit -Xlinker -no_adhoc_codesign -compatibility_version 1 -current_version 15256 -Xlinker -dependency_info -Xlinker /Users/ebabayan/Downloads/maplibre-gl-native/platform/ios/build/ios/ios.build/Debug-iphonesimulator/dynamic.build/Objects-normal/arm64/Mapbox_dependency_info.dat -o /Users/ebabayan/Downloads/maplibre-gl-native/platform/ios/build/ios/Debug-iphonesimulator/Mapbox.framework/Mapbox

I can't figure out what I'm missing

@ankb90
Copy link

ankb90 commented Dec 8, 2022

I think,
Select "dynamic" target, go to Build Settings / Search Paths / Librarys Search Paths
Change library search paths to where the static libmbgl-core.a, libmblg-vender-csscolorparser.a .... saved.

If that doesn't work, try the following:

  1. Solution1:
  1. Solution2:
  • Open ios.xcworkspace, choose dynamic targets
  • Build with iOS Simulator -> Mapbox.framework (available for Simulator)
  • Build with Real iOS Device -> Mapbox.framework (available for iOS device)
  • Make a xcframework from 2 file Mapbox.framework (for Simulator) and Mapbox.framework (for iOS device)
  • Get the xcframework then add to your project

@Ernest0-Production
Copy link
Author

Ernest0-Production commented Dec 8, 2022

@ankb9x Hi!

Thanks for the tip. Haven't tried your solution yet, but managed to look at the current LIBRARY_SEARCH_PATHS in the dynamic target:

$(LIBRARY_SEARCH_PATHS)
$(PROJECT_DIR)/vendor/mapbox-accounts-ios

While all the .a files of static libraries (i.e. static library products) were located not in DerivedData, but in the project directory:

/path/to/project/maplibre-gl-native/platform/ios/build/ios/

After which I realized that it turns out that the default Derived Data path in ios.xcworkspace had been overriden to the following line (relative to the workspace location) in xcode>file>workspace settings:

../.../build/ios

In other words, when compiling static project libraries from ios.xcworkspace which was located in /platform/ios/platform/ios, compilation products were located on the path /platform/ios/build/ios (two directories backward ../../ and forward in build/ios)


🤔 However, all this research has not given me an explanation as to why the dynamic target refers in the Library search Path to a path that does not have these .a files? I.e. even when compiling ios.workspace I get the following:

  1. MapBox.framework and all static libraries (.a) are created in /platform/ios/build/ios

  2. When linked (Ld command) it refers to /platform/ios/platform/ios/vendor/mabox-accounts-ios which is listed in LIBRARY_SEARCH_PATHS AND to /platform/ios/build/ios

😬 I'm not good at manual targeting and linking processes, but from what I've been able to find, I can't put the puzzle together yet.
I would like to understand how the dynamic target in ios.workspace finds the path to static libraries if the path to them in LIBRARY_SEARCH_PATHS is missing

@ankb90
Copy link

ankb90 commented Dec 8, 2022

I would like to understand how the dynamic target in ios.workspace finds the path to static libraries if the path to them in LIBRARY_SEARCH_PATHS is missing

I think,

  1. When you embed Mapbox GL Native.xcproj project and ios.xcproj project into ios.workspace workspace then you can add .a files to ios.xcproj project by adding in Frameworks, Libraries and Embedded content( a. file is virtual it's not built yet)
  • You build ios.xcproj project -> trigger build Mapbox GL Native.xcproj project -> create a. files and store in the DerivedData folder (default setting)
  • When Mapbox GL Native.xcproj is complete, ios.xcproj project start to build. It detect a. files at DerivedData folder (default setting of output file of Mapbox GL Native.xcproj)
    -> No need to follow the instructions of LIBRARY_SEARCH_PATHS to find a. files
  1. When add static libraries to project ( add a. files), you need to specify position of 'a.files'. So, you set the path to them by LIBRARY_SEARCH_PATHS

@Ernest0-Production
Copy link
Author

  • When Mapbox GL Native.xcproj is complete, ios.xcproj project start to build. It detect a. files at DerivedData folder (default setting of output file of Mapbox GL Native.xcproj)
    -> No need to follow the instructions of LIBRARY_SEARCH_PATHS to find a. files

It looks strange because it doesn't work 🤔

I tried the following:
Changed Workspace project settings and specified the same path as specified in iOS.workspace.

Yes, now my products are in the project directory in platform/ios/build/ios but the error keeps showing up...

What's amazing is that if I do Clean Build, it removes the compiled .a files, and when building dynamic it causes the static libraries to compile first (in the Products folder the font alternately changes from red to white), but in the end it can't find those libraries....


I decided to explicitly specify Library Search Path, but ran into the fact that I can not figure out how to properly specify the path to the directory. The thing is that depending on the configuration and platform, the .a files are put in the appropriate folder. (Debug-iphonesimulator, Debug-iphoneos, etc)
image

Maybe you know what environment variable in Xcode is suitable for pointing to the path of the libraries?

@Ernest0-Production
Copy link
Author

Ernest0-Production commented Dec 8, 2022

I try to add $(CONFIGURATION_BUILD_DIR) in library search path but it didn't help me...

But when I replace on $(PROJECT_DIR)/../../build/ios/$(CONFIGURATION)${EFFECTIVE_PLATFORM_NAME} it has successfully builded! 🔥

But I still do not understand why it worked, since the resulting path is the same for them 🙂

$(CONFIGURATION_BUILD_DIR) => path/to/maplibre/platform/iOS/platform/iOS/../../build/iOS/Debug-phoneos

$(PROJECT_DIR)/../../build/ios/$(CONFIGURATION)${EFFECTIVE_PLATFORM_NAME} = 
      $(PROJECT_DIR) => path/to/maplibre/platform/iOS/platform/iOS
      + /../../build/ios/
      + $(CONFIGURATION) => Debug or Release or ...
      + ${EFFECTIVE_PLATFORM_NAME} => phoneos or iphonesimulator

I checked several times. These are indeed the same values, but for some reason $(CONFIGURATION_BUILD_DIR) did not fit

@ankb90
Copy link

ankb90 commented Dec 9, 2022

It looks strange because it doesn't work 🤔

I tried the following: Changed Workspace project settings and specified the same path as specified in iOS.workspace.

Yes, now my products are in the project directory in platform/ios/build/ios but the error keeps showing up...

Screenshot 2022-12-09 at 14 01 16

I don't know why you got the error.
I tried adding my project to iOS.workspace, it worked (no errors)

@Ernest0-Production
Copy link
Author

I tried adding my project to iOS.workspace, it worked (no errors)

No, I must have misled you. I was adding ios and MapLibre xcproj to MY workspace, which was located in a directory other than ios workspace

@ankb90
Copy link

ankb90 commented Dec 9, 2022

No, I must have misled you. I was adding ios and MapLibre xcproj to MY workspace, which was located in a directory other than ios workspace

This isn't much different, it's just different config.
I think this is your problem, not the library's problem.

@Ernest0-Production
Copy link
Author

I think this is your problem, not the library's problem.

I can't agree with that. A similar problem was reproduced in ios workspace when I tried to archive the dynamic target. (build is ok)

From what I understand, when building the target, all the compilation products in the ios workspace are transferred to the build/ios directory, including the 'dynamic' Framework and its dependencies static libraries.
AND xcode HAS IMPLICIT BEHAVIOR: It implicitly finds the path to static libraries without explicitly specifying their path in the build settings library search path if these dependencies are in the same directory as the Framework for linking with Ld command.

This makes the project build sensitive and implicit!
But I found a more correct solution than specifying library search path: I noticed that all static libraries have a user defined key in build settings, based on which xcode determines where to put compilation products 'CONFIGURATION_BUILD_DIR'

And I just added this field to the build settings of the dynamic target . And it fixed both:

  • the archiving of the Framework in ios workspace
  • the compilation of the target in my own workspace.

Just adding this line in build settings of dynamic target will fix all problems:

CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/../../build/ios/$(CONFIGURATION)${EFFECTIVE_PLATFORM_NAME}";

@Ernest0-Production
Copy link
Author

Ernest0-Production commented Dec 9, 2022

But I found another problem that could not be solved.

The make xcframework command crashes with the error that the directory with the dSYMs file is empty - and it really is 🤔

I tried manually archiving the dynamic target from ios workspace and the resulting xcarchive has a really empty dsyms folder. At the same time, with a simple build in build/ios/ dsyms is created.

I have not been able to find the cause of the problem yet, but this prevents me from building xcframework with debug symbols

I also decided to try to build xcframework with SYMBOLS=NO and he also swore at the lack of a debug symbols, which was strange -_-
Later I found an error in the xpackage.sh script in which there was a syntax error, after which everything was corrected. 😤

I will try to do PR with this fix, but it makes sense to do this only after the reason is found why the assembly with debugging symbols does not work.

Library integration has never taken so much time and effort from me before 😅

@wipfli
Copy link
Contributor

wipfli commented Dec 9, 2022

Thanks a lot for sharing your insights @Ernest0-Production. I think this will help others in the future...

@louwers louwers added iOS documentation Improvements or additions to documentation labels Jan 25, 2023
@louwers
Copy link
Collaborator

louwers commented Sep 22, 2023

We have completely overhauled the iOS build setup.

Please see the note at the bottom of this comment. Feel free to create a new issue if you run into any problems.

@louwers louwers closed this as completed Sep 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation iOS
Projects
None yet
Development

No branches or pull requests

4 participants