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

move LLMR from dependent target to statically linked library #9

Closed
3 tasks
incanus opened this issue May 14, 2014 · 31 comments
Closed
3 tasks

move LLMR from dependent target to statically linked library #9

incanus opened this issue May 14, 2014 · 31 comments
Milestone

Comments

@incanus
Copy link
Contributor

incanus commented May 14, 2014

Steps:

  • Create a build script similar to the iOS SDK one which builds the various architectures needed and uses lipo to combine them into a single file
  • Link the new libLLMR.a into this project directly
  • Hide LLMR C++ files from view by getting rid of the Xcode workspace and just provide an Xcode project for building this project
@incanus
Copy link
Contributor Author

incanus commented May 14, 2014

The actual move here is going to happen pretty late in the game since introducing the static library early is a workflow pain for LLMR development.

@incanus incanus added this to the WWDC milestone May 14, 2014
@kkaefer
Copy link
Contributor

kkaefer commented May 18, 2014

FWIF, I wouldn't remove/hide C++ files as that'll make it harder to debug for iOS developers if they choose to dive into the lib.

@incanus
Copy link
Contributor Author

incanus commented May 18, 2014

Hide LLMR C++ files from view

What I mean by this is how it's done for Proj4 here:

https://github.com/mapbox/mapbox-ios-sdk/tree/release/Proj4

Note that all the files, as well as the Xcode project needed to build them, are in the source tree.

However, the SDK Xcode project itself merely links in the libProj4.a as a result of Outdooractive/route-me#85 (comment). This speeds up compile time for the SDK as well as keeps it simple.

We could always provide an Xcode workspace (a way of combining 2+ Xcode projects) that includes the normal toolset project as well as the project used to build the static libs of LLMR for people who want to hack it. I think we can consider them largely exclusive audiences a lot of the time, though.

@incanus
Copy link
Contributor Author

incanus commented May 26, 2014

Related: mapbox/mapbox-gl-native#243 (comment)

@incanus
Copy link
Contributor Author

incanus commented May 29, 2014

Taking a crack at this now.

@incanus
Copy link
Contributor Author

incanus commented May 30, 2014

This is what iOS devs will have to install to get up and running:

screen shot 2014-05-29 at 5 41 05 pm

@incanus
Copy link
Contributor Author

incanus commented May 30, 2014

Happening in https://github.com/mapbox/MVKMapKit/tree/easy-install.

Just need to test inclusion in a fresh Xcode project, then will merge.

@incanus
Copy link
Contributor Author

incanus commented May 30, 2014

Yeah, hitting some walls here. Would appreciate an eyeball, @springmeyer.

Here's my current build process, ideally, encapsulated in ./pkg/package.sh:

  1. Use ./pkg/MVKMapKit.gyp to generate ./pkg/MVKMapKit.xcodeproj.
  2. Use xcodebuild to build sim/device versions of MVKMapKit.
  3. Use xcodebuild to build sim/device versions of libllmr-ios.a.
  4. Use lipo to combine all into a fat static library.
  5. Misc. other stuff like grabbing headers and the resource bundle (non-code).

My problem however is that MVKMapKit can't build as it relies on llmr.hpp. Adding that to the MVKMapKit.gyp gets me a bit further along until:

error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: can't locate file for: -lz
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: -lz is not an object file (not allowed in a library)
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: can't locate file for: -lpthread
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: -lpthread is not an object file (not allowed in a library)
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: can't locate file for: -ldl
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: -ldl is not an object file (not allowed in a library)

My problem is that MVKMapKit relies on linking against llmr-ios, really.

I tried also making MVKMapKit.gyp and its target a dependency of the top-level llmr.gyp but then that has problems with the Cocoa runtime, since these Cocoa files aren't meant to be part of the C++ library.

Am I screwed here? Should I just be putting MVKMapKit into LLMR proper?

My thinking here was to contain the Cocoa code as well as meet the easy clone/install vision described by the screenshot above.

Any ideas?

@springmeyer
Copy link

Can you share the exact command that failed? I'll take a closer look when I can get back online.

On May 29, 2014, at 8:14 PM, "Justin R. Miller" notifications@github.com wrote:

Yeah, hitting some walls here. Would appreciate an eyeball, @springmeyer.

Here's my current build process, ideally, encapsulated in ./pkg/package.sh:

Use ./pkg/MVKMapKit.gyp to generate ./pkg/MVKMapKit.xcodeproj.

Use xcodebuild to build sim/device versions of MVKMapKit.

Use xcodebuild to build sim/device versions of libllmr-ios.a.
Use lipo to combine all into a fat static library.
Misc. other stuff like grabbing headers and the resource bundle (non-code).
My problem however is that MVKMapKit can't build as it relies on llmr.hpp. Adding that to the MVKMapKit.gyp gets me a bit further along until:

error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: can't locate file for: -lz
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: -lz is not an object file (not allowed in a library)
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: can't locate file for: -lpthread
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: -lpthread is not an object file (not allowed in a library)
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: can't locate file for: -ldl
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: -ldl is not an object file (not allowed in a library)
My problem is that MVKMapKit relies on linking against llmr-ios, really.

I tried also making MVKMapKit.gyp and its target a dependency of the top-level llmr.gyp but then that has problems with the Cocoa runtime, since these Cocoa files aren't meant to be part of the C++ library.

Am I screwed here? Should I just be putting MVKMapKit into LLMR proper?

My thinking here was to contain the Cocoa code as well as meet the easy clone/install vision described by the screenshot above.

Any ideas?


Reply to this email directly or view it on GitHub.

@springmeyer
Copy link

error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: can't locate file for: -lz

Replicated this. Its happening because we want to dynamically link zlib but -lz is ending up in the linker args for libMVKMapKit.a. But this won't work because libMVKMapKit.a needs a libz.a around. So, the solution is to not have -lz in the linker args for the creation of libMVKMapKit.a. Rather the final app that links libMVKMapKit.a will need -lz.

Thinking through a fix now.

@incanus
Copy link
Contributor Author

incanus commented May 30, 2014

Having the final app link is ok, btw. Just needs put in the install instructions but it's not a hurdle.

@springmeyer
Copy link

Other potential gocha / way this is different than libProj4.a is that libMapboxGL.a / libMVKMapKit.a also depends on C++ and libuv.a and libpng.a

  • C++ issue should likely be solved by providing a starter project with the right settings for c++/libc++/-stdc++11
  • libuv.a and libpng.a issue could be solved by bundling those as well and having users linke, but I think a more preferable approach would be to blend them into libMapboxGL.a. I'm taking a look at this right now. Basically I think the trick is to break out the object files per arch and them recombine like described at http://stackoverflow.com/questions/9531014/linking-2-static-libs-into-1-for-ios/21225126#21225126

@incanus
Copy link
Contributor Author

incanus commented May 30, 2014

C++ issue should likely be solved by providing a starter project with the right settings for c++/libc++/-stdc++11

I was hoping to avoid the need to build for C++, which (I think) may be unavoidable? Basically, does that mean a user has to make their project an Objective-C++ project? Or can this be per-file?

@springmeyer
Copy link

We should be able to pretend C++ is not involved at compile (so .m rather than .mm files can be used I think). But at link time C++ will need to be involved. Because we need to link a static lib (libMapboxGL.a) the dynamic symbols that static lib depends on also need to be linked at the same time. So, -lz is one (as per above) but also the c++ lib. The shorthand for this is -stdlib=libc++ but it is basically -lc++.

In summary:

I was hoping to avoid the need to build for C++, which (I think) may be unavoidable?

Yes, unavoidable.

Basically, does that mean a user has to make their project an Objective-C++ project?

I don't think so.

@incanus
Copy link
Contributor Author

incanus commented May 30, 2014

Ok, that's helpful. Linker flags in the install docs are also OK™.

@springmeyer
Copy link

Okay, progress:

  • roughly followed https://github.com/mapbox/MVKMapKit/tree/easy-install#installation
  • after creating a blank xcode project with the "Single View Application" template
  • Added -lz to other linker flags
  • Marked one (could have made a dummy) of the .m files as "Objective-C++ Source". This seems like the only way to trick XCode into linking with clang++ instead of clang.
  • Added this to viewDidLoad:

    MVKMapView *mapView = [[MVKMapView alloc] initWithFrame:CGRectMake(100, 100, 500, 500)];
    [self.view addSubview:mapView];
  • After that the app build and linked fine.

Now I'm hitting this at runtime:

Assertion failure in +[MVKMapView resourceImageNamed:], /Users/dane/projects/llmr-native/ios/MVKMapKit/MVKMapKit/MVKMapView.mm:548
2014-05-29 23:41:11.097 tttttest[2281:60b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Resource image not found in application.'

@incanus
Copy link
Contributor Author

incanus commented May 30, 2014

Cool, that's a bundle-related issue, but we're out of the woods on linking, so that's what I really needed.

##     ## ####  ######   ##     ##    ######## 
##     ##  ##  ##    ##  ##     ##    ##       
##     ##  ##  ##        ##     ##    ##       
#########  ##  ##   #### #########    #######  
##     ##  ##  ##    ##  ##     ##          ## 
##     ##  ##  ##    ##  ##     ##    ##    ## 
##     ## ####  ######   ##     ##     ######  

Can you elaborate on:

Marked one (could have made a dummy) of the .m files as "Objective-C++ Source". This seems like the only way to trick XCode into linking with clang++ instead of clang.

@springmeyer
Copy link

regarding making one .m objective c++:

screenshot 2014-05-29 23 52 53

@springmeyer
Copy link

It should be possible to avoid this by instead adding -lc++ and a few other flags to the other linker flags, but it would be more error prone.

@incanus
Copy link
Contributor Author

incanus commented May 30, 2014

Oh, interesting. That's weird. So basically because we aren't compiling in MVKMapKit.mm, there's no hint to use Objective-C++. I will see if I can work around that.

@springmeyer
Copy link

yeah, and I see no way to gently tell xcode to link as a C++ app. silly, but at least the workaround is easy, if odd.

@incanus
Copy link
Contributor Author

incanus commented Jun 4, 2014

Back on this and close.

@incanus
Copy link
Contributor Author

incanus commented Jun 4, 2014

@springmeyer I could possibly use a hand again on a new and wonderfully different task now.

So linking is good and I'm trying to solve the resource bundle issue. What needs to happen is that I need the output of the llmr-ios dependent target build_stylesheet, which is a style.min.js. I need to make that available to this copy phase so that it ends up alongside the image resources.

The build_stylesheet target is already running via llmr-ios, so adding it to mapbox-gl-cocoa.gyp as a dependency doesn't do anything useful. It's more a matter of figuring out how to get at the target result.

@springmeyer
Copy link

What about just:

cp $PARENT/build/DerivedSources/Release/bin/style.min.js $OUTPUT/

@incanus
Copy link
Contributor Author

incanus commented Jun 4, 2014

I did see the file there, but thought that brittle. Works great, though! 👍

@incanus
Copy link
Contributor Author

incanus commented Jun 4, 2014

Ok, as of de9e0d0 we have a shippable static library, resource bundle, and header collection. The last thing I'd like to hit is the wonky Objective-C++ file designation above in #9 (comment), do some quick QA, and tag it.

@incanus
Copy link
Contributor Author

incanus commented Jun 4, 2014

First time I've seen an explicit mention of the .m -> .mm trick being necessary:

http://answers.oreilly.com/topic/631-how-to-get-c-and-objective-c-to-play-nicely-in-xcode/

That's looking to be the way. I may just include a dummy as you suggested @springmeyer -- like maybe a MapboxGL.mm with just comments in it.

@incanus incanus closed this as completed in 31b514a Jun 4, 2014
@incanus
Copy link
Contributor Author

incanus commented Jun 4, 2014

This is done and the entire download-to-live-view install process is encapsulated here:

https://github.com/mapbox/mapbox-gl-cocoa#installation

It's very simple and builds in no time to get up & running with Cocoa - easily a few seconds.

@springmeyer
Copy link

\o/

@springmeyer
Copy link

one other idea on the triggering c++ issue. It would also likely work to provide an xconfig file with GCC_INPUT_FILETYPE = sourcecode.cpp.objcpp in it. But I think the dummy mm is likely the easiest.

@incanus
Copy link
Contributor Author

incanus commented Jun 4, 2014

Interesting. I may explore that if there's feedback on the stub file. But right now it fits nicely alongside the other resources:

https://github.com/mapbox/mapbox-gl-cocoa/tree/master/dist

Thanks a ton for the help & research @springmeyer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants