How to Build with OmniGroup Frameworks - ios

I'm trying to incorporate OmniGroup's frameworks into a project. I'm very new to building with these kinds of dependcies so I've been fumbling my way through this. What I've done so far it.
Created new Xcode project for iOS (iPad) using the Single View Application template.
Edited the Schema and unchecked Parallelize Build and Find Implicit Dependencies.
Added the 'Configurations' directory from the OmniGroup repository to my project.
Created a lib directory in my project's repository.
Copied the OmniBase directory to my lib directory.
Created an Omni Frameworks group in Xcode.
Dragged the lib/OmniBase/OmniBase.xcodeproj file to the Omni Frameworks group.
In my project's Build Phases tab I added 'libOmniBase.a' in the Link Binary With Libraries section.
⌘B to build
Yes, I know OmniBase is useless by itself. I'm just trying to build the minimum amount first and add on from there. But I can't get OmniBase to build. I get one error...
Ld /Users/mluton/Library/Developer/Xcode/DerivedData/CoreTextWithOmni2-dzbwnmvzfbuyhzadnmwrvmfmzyoa/Build/Products/Debug-iphoneos/CoreTextWithOmni2.app/CoreTextWithOmni2 normal armv7
cd /Users/mluton/dev/ios-recipes/CoreTextWithOmni2
setenv IPHONEOS_DEPLOYMENT_TARGET 6.1
setenv PATH "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch armv7 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk -L/Users/mluton/Library/Developer/Xcode/DerivedData/CoreTextWithOmni2-dzbwnmvzfbuyhzadnmwrvmfmzyoa/Build/Products/Debug-iphoneos -F/Users/mluton/Library/Developer/Xcode/DerivedData/CoreTextWithOmni2-dzbwnmvzfbuyhzadnmwrvmfmzyoa/Build/Products/Debug-iphoneos -filelist /Users/mluton/Library/Developer/Xcode/DerivedData/CoreTextWithOmni2-dzbwnmvzfbuyhzadnmwrvmfmzyoa/Build/Intermediates/CoreTextWithOmni2.build/Debug-iphoneos/CoreTextWithOmni2.build/Objects-normal/armv7/CoreTextWithOmni2.LinkFileList -dead_strip -fobjc-arc -fobjc-link-runtime -miphoneos-version-min=6.1 /Users/mluton/Library/Developer/Xcode/DerivedData/CoreTextWithOmni2-dzbwnmvzfbuyhzadnmwrvmfmzyoa/Build/Products/Debug-iphoneos/OmniBase/OmniBase -framework UIKit -framework Foundation -framework CoreGraphics -o /Users/mluton/Library/Developer/Xcode/DerivedData/CoreTextWithOmni2-dzbwnmvzfbuyhzadnmwrvmfmzyoa/Build/Products/Debug-iphoneos/CoreTextWithOmni2.app/CoreTextWithOmni2
clang: error: no such file or directory: '/Users/mluton/Library/Developer/Xcode/DerivedData/CoreTextWithOmni2-dzbwnmvzfbuyhzadnmwrvmfmzyoa/Build/Products/Debug-iphoneos/OmniBase/OmniBase'
I've tried comparing my project to the TextEdit example workspace but I haven't run across any solutions yet. I know there's probably some step or setting I'm missing. Hopefully, this is obvious to someone reading this.

After examining this some more I finally got it to build. Here's the additional steps involved.
Copied the Script directory from the OmniGroup repository to my project.
Added a Build Phase. Run shell script Scripts/CopyLibraryResources. Ordered my Build Phases the same as in the TextEdit example. Target Dependencies, Compile Sources, Link Binary with Libraries, Copy Bundle Resources and Copy Library Resources which is the shell script build phase I added in the previous step.
Converted my project to a workspace.
Add my original project and the FixStringsFile project to the workspace.
Edit the scheme. Under build add FixStringsFile as a dependency. Made sure it was at the top of the list. Add any other library (in this case OmniBaseTouch) as a build dependency as well. Place them after FixStringsFile and Before the application target.
⌘B to build. No Issues!
PS: In both projects I edited Configurations/Target-Mac-Common.xcconfig and commented out OMNI_MAC_CODE_SIGN_IDENTITY = Mac Developer: since I'm not in the Mac Developer program.

Related

iOS Linking library in xcconfig

I'm building a library. And I want it to compile and contain another one (which is googleConversion) but I need to do it with xcconfig files (because for some build I want to not include the library for example)
Following: Link binary with static library in xcconfig
So what I did was add in my xcconfig file:
LIBRARY_SEARCH_PATHS = $(inherited) $(PROJECT_DIR)/../Vendors/Analytics/GoogleConversion/GoogleConversionTrackingSDK-iOS-3.2.0
OTHER_LDFLAGS =$(inherited) -ObjC -L$(PROJECT_DIR)/../Vendors/Analytics/GoogleConversion/GoogleConversionTrackingSDK-iOS-3.2.0 -lGoogleConversionTracking
which let me compile without warning, but don't include the library in my .a
the only way I managed to do it is adding the library in the build phase in Link Binary With Library.
But it's not something I can do if I want to be able to automate my different type of builds
It sounds like it should be very simple ;(
Maybe some other configuration is preventing those lines to work?
I tried checking my logs and I can see in my "check dependencies" in Libtool export path I can see the resolved path of my OTHER_LDFLAGS (which disapear when I remove it from my xcconfig) but not the -lGoogleConversionTracking which exist when I put my lib in the build phase.
(I have more things happening, like nothing in libtool if I completly remove the panel from the build phases, but it could make sense in a way and it's not a big deal)
Thank you in advance!
Finaly got it!!!!
It because of an old xcode bug that was solved in xcode 6.
https://tarunsharmaios.wordpress.com/2014/09/12/xcode6-static-library-linking-broken/
BlockquoteXcode will no longer pass options in the build setting OTHER_LDFLAGS to libtool when building static libraries, nor will it pass options in OTHER_LIBTOOLFLAGS to the Mach-O linker when building any other kind of product. Previously all options in both settings would be passed to both tools. Make sure that options are in the correct build setting for the product type, static library, or other component being built. (4285249)
In my case it looks like:
LIBRARY_SEARCH_PATHS = $(inherited) "${SRCROOT}/thirdparties/CardIO-5.1.0"
OTHER_LDFLAGS = $(inherited) -ObjC -lz -lc++ -lCardIO
But my libs placed inside source folder in a same level with the *.xcodeproj-file.
I think that paths with "\..\" won't work for xcode.
This issue can be resolved with a script phase in your scheme.
Open your scheme via Product->Scheme->Manage Schemes.
Add the New run script action in the Build->Pre-actions
Script should copy file libGoogleConversionTracking.a to the ${SRCROOT}
Set new path for a LIBRARY_SEARCH_PATHS in *.xcconfig file

Xcode build variables for iOS or Mac for carthage support

Overview
I am working on developing multiple cascading set of Dynamic Frameworks that are integrated by Carthage. I'm trying to adapt the principals in this blog post and the WWDC video Sharing code between iOS and OS X
My Situation:
I have 3 Dynamic frameworks who included each other in a cascading format:
Dynamic Framework: DataManager includes Dynamic Framework: GDL90 includes DynamicFramework: EGL96.
Work thus far...
The jist of what I'm doing is taking a single target and having it configured to build frameworks for both iOS and Mac explained here
Base SDK: OSX
Supported Platforms: machos iphoneos iphonesimucator
Valid Architectures: arm64 armv7 armv7s i386 x86_64
And then under your test targets you change the search paths:
Runpath Search Paths: $(inherited) #executable_path/Frameworks #loader_path/Frameworks #executable_path/../Frameworks #loader_path/../Frameworks
Framework Search Paths: $(SDKROOT) $(inherited)
Where the problem starts
I configured the EGM96 project as such to build multiple build for multiple targets. This works nicely and compiles fine. Where the trouble starts is once we get carthage involved.
In my GDL90 project I included EGM96 from carthage
After I run carthage update I end up with the following files:
./Carthage/Build/Mac/EGM96.framework
./Carthage/Build/iOS/EGM96.framework
I've also configured the GDL90 project to do a multi-platform build, but thats where the error starts. I'm unable to dynamically configure the build process (thus far) to pull in the correct framework version based on the correct target (i.e. OS X build pulls from /Carthage/Build/Mac/EGM96.framework).
I've spent some time looking through the build variables for Xcode and I have yet to find a working solution.
The caveat is as these were initially iOS projects i had linked in the iOS framework into Xcode and thus I end up with the entirely appropriate error:
ld: building for OSX, but linking in object file built for iOS, file '/Users/jstein/devel/DigitalCopilot/GDL90/Carthage/Build/iOS/EGM96.framework/EGM96' for architecture x86_64
Is there an easy solution to some hidden build variables I'm missing that would allow at compile time Xcode to pull the framework from the appropriate carthage build path?

How to use Realm (installed with Carthage) with a framework in a Swift app?

I'm working on an iOS App and a Watchkit App.
I read a few things regarding best practices and I decided to create a custom framework, as NathashaTheRobot advise here:
https://realm.io/news/architecting-app-apple-watch-natashatherobot/
So I'm trying to use Realm in my framework.
I followed the installation instructions for Carthage:
Add github "realm/realm-cocoa" to your Cartfile.
Run carthage update.
Drag RealmSwift.framework and Realm.framework from the
Carthage/Build/iOS/ directory to the “Linked Frameworks and
Libraries” section of your Xcode project’s “General” settings.
On your application targets’ “Build Phases” settings tab, click the
“+” icon and choose “New Run Script Phase”. Create a Run Script with
the following contents:
/usr/local/bin/carthage copy-frameworks
and add the paths to the frameworks you want to use under “Input
Files”, e.g.:
$(SRCROOT)/Carthage/Build/iOS/Realm.framework
$(SRCROOT)/Carthage/Build/iOS/RealmSwift.framework
Then I added my framework to the Target Membership of both Realm.framework and RealmSwift.framework.
But when I try to build the project, I get this error:
ld: framework not found Realm for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Then I gave a shot to lipo:
$ lipo -info Carthage/Build/iOS/Realm.framework/Realm
Architectures in the fat file: Carthage/Build/iOS/Realm.framework/Realm are: i386 x86_64 armv7 arm64
Do you have any ideas of what I might be doing wrong here? Thank you.
EDIT:
OK so I found the problem and it was totally unrelated to Realm...
It looks like I deleted the Headers and Resources sections of my framework Build Phases somehow (which were and are still empty). I just put them back and everything compiles/works like it should.
Don't be tempted to delete those two
Is it possible that it's your test target that can't find the frameworks? You'll have to add the parent location of the frameworks to the "Frameworks Search Path" section of your unit tests (likely $(SRCROOT)/Carthage/Build/iOS).
Here's a sample project of a Swift framework bundling RealmSwift as a dependency which you might find useful to compare your build settings against: https://static.realm.io/debug/ParentFramework.tgz

OSX and iOS shared swift module

I have created swift based Cocoa Touch Framework project named TestLib then I have added new target for Cocoa Framework named TestLibOSX. When I use the framework on iOS app it seems to be working without any issue, but when I create OSX console application it XCode is complaining that it couldn't find TestLibOSX module. Am I missing something ?
P.S This is not the same :)
EDIT: Seems this must be possible since I can see Lister is implemented that way.
If you wish to create a single dynamic framework binary, here are the steps you can follow (as outlined in http://colemancda.github.io/programming/2015/02/11/universal-ios-osx-framework/):
1. Change the project's valid architectures and supported platforms.
This should change your framework's and test unit's valid architectures and supported platforms as well. If not, then manually change them to inherit from the project's build settings.
Base SDK: I recommend OS X, but it will work with iOS too. Note that with with iOS as the base SDK, "My Mac" target is separated into 3 different targets.
Supported Platforms: macosx iphoneos iphonesimulator
Valid Architectures: arm64 armv7 armv7s i386 x86_64
2. Change the search paths for the Unit Test bundle
Runpath Search Paths: $(inherited) #executable_path/Frameworks #loader_path/Frameworks #executable_path/../Frameworks #loader_path/../Frameworks
Framework Search Paths: $(SDKROOT) $(inherited)
This will allow you to import it as import MyFramework instead of
#if os(iOS)
import MyFramework
#else
import MyFrameworkOSX
#endif
Alright, universal frameworks are really a pain. Not only for iOS and OSX but also just within iOS since you need 2 frameworks: one for the simulator and one for the devices. The way you handle iOS is with an "Aggregate" target. I believe the same avenue could be exploited to integrate an OS X target.
When you build a framework, you get a .framework (lego block) folder. In there, there are 2 very important things to be had:
The "Executable" file
The "Modules" folder
In both of these places, you have to have implementation to support all the architectures you desire to support. If you where to build your frameworks separately and wanted to fuse them together, you would have to do the following:
Take both executables and merge them with a "lipo" command.
Make sure that all the files in both "Modules" folder are move
together.
In practical terms, it's a mess so here's what I do!
First I build the frameworks. They can be on different targets in the
same project but usually, the same name helps. For iOS only, theres only one framework so one target suffices.
Then I add an "Aggregate" target, it will help create multiple builds for different architectures.
Clicking on the project name and then the Aggregate target, I go to "Build Phases" and click on the little plus to add a "New Run Script Phase".
There I copy paste the code in this GIST.
Finally, changing your scheme to the Aggregate target and building it will do all the merging you need and you end up with a .framework that is universal.
The script is rather straightforward and with a little dabbling, I'm sure it can be tweaked to add OSX support to it. I hope this points you in the right direction :)
Contents of the script:
#!/bin/sh
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
# Step 1. Build Device and Simulator versions
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
# Step 2. Copy the framework structure (from iphoneos build) to the universal folder
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"
# Step 3. Copy Swift modules (from iphonesimulator build) to the copied framework directory
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/." "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule"
# Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"
# Step 5. Convenience step to copy the framework to the project's directory
cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}"
# Step 6. Convenience step to open the project's directory in Finder
open "${PROJECT_DIR}"

.app file not found in Derived Data

When trying to compile my project I am getting this error and am wondering if anyone knows how to fix it?
I've read every answer on SO and elsewhere on the internet pertaining to this kind of linker error. I've tried so many solutions, including the very popular --delete derived data in xcode, quit xcode completely, delete it again on the command line and then restart xcode-- still nothing. This started after I tried to attach a device to my computer (which I've since deleted from the organizer) that was a friends to try to run it on his iPad. I'm at my wits end and can't afford to waste anymore time on this. Any ideas on how to fix it?
The app file in the Products folder is red.
EDIT: More info: The actual app is not being built and put in the Library/Developer/{app}/Build/Product folder. I've tried reconnecting the device and adding the provision profile manually from the apple website, then trying to Build->Archive the app while the device is selected. I still get the error. I've tried changing from debug to release in the Schemes and doing all of that, I still get the error. I tried uninstalling xcode and reinstalling it, deleting the app completely off the computer (including the derived data) pulling back down from Git and I get the same error.
Ld /Users/mischabuckler/Library/Developer/Xcode/DerivedData/TRx-clxlusutxvcrlkddtqwtoxibcmhc/Build/Products/Debug-iphonesimulator/UnitTests.octest/UnitTests normal i386
    cd /Users/mischabuckler/Desktop/Git/TRx
    setenv IPHONEOS_DEPLOYMENT_TARGET 6.1
    setenv PATH "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch i386 -bundle -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.1.sdk -L/Users/mischabuckler/Library/Developer/Xcode/DerivedData/TRx-clxlusutxvcrlkddtqwtoxibcmhc/Build/Products/Debug-iphonesimulator -F/Users/mischabuckler/Library/Developer/Xcode/DerivedData/TRx-clxlusutxvcrlkddtqwtoxibcmhc/Build/Products/Debug-iphonesimulator -F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.1.sdk/Developer/Library/Frameworks -F/Applications/Xcode.app/Contents/Developer/Library/Frameworks -filelist /Users/mischabuckler/Library/Developer/Xcode/DerivedData/TRx-clxlusutxvcrlkddtqwtoxibcmhc/Build/Intermediates/TRx.build/Debug-iphonesimulator/UnitTests.build/Objects-normal/i386/UnitTests.LinkFileList -bundle_loader /Users/mischabuckler/Library/Developer/Xcode/DerivedData/TRx-clxlusutxvcrlkddtqwtoxibcmhc/Build/Products/Debug-iphonesimulator/TRx.app/TRx -Xlinker -objc_abi_version -Xlinker 2 -fobjc-arc -fobjc-link-runtime -Xlinker -no_implicit_dylibs -mios-simulator-version-min=6.1 -framework SenTestingKit -framework UIKit -framework Foundation -o /Users/mischabuckler/Library/Developer/Xcode/DerivedData/TRx-clxlusutxvcrlkddtqwtoxibcmhc/Build/Products/Debug-iphonesimulator/UnitTests.octest/UnitTests
ld: file not found: /Users/mischabuckler/Library/Developer/Xcode/DerivedData/TRx-clxlusutxvcrlkddtqwtoxibcmhc/Build/Products/Debug-iphonesimulator/TRx.app/TRx
clang: error: linker command failed with exit code 1 (use -v to see invocation)
This happens when you rename the main target, and the test target hasn't been updated. Check the build settings in the test target and make sure the paths are pointing to the new folders. For example, if you renamed the target SuperAwesome to just Super, your test target is expecting files in SuperAwesome.app/ folder when it should be updated to Super.app/
Ok, the clue, while difficult to spot, is that the message you posted above isn't one building your app, but your unit tests. It also mentions it at the top of your output window, but one doesn't expect that to change.
You've possibly renamed your scheme, and in doing so the unit test is pointing to your real build or something else. Your app may well actually have built fine, but its your unit test target that fails.
If the problem is that you've been renaming targets then in your UnitTest scheme, go to build settings and search for TEST, which should bring up the settings for TEST HOST. Make sure these values are pointing to whatever you want the test app to be called and not the main executable.
For me it was just a case of appending "test" onto both the debug & release setting of my test target's TEST_HOST.
It all builds for me now, though annoyingly it is actually building both targets - at least they both compile.
So for anyone else who finds this and is frustrated what I ended up doing was deleting the target dependencies for both my app and the unit tests and then building the app once, then re-adding them and building the app again, and it worked fine.
Try duplicating the target, and run using the target's copy.
I hate Mach-o linker errors, its frustrating, anyway, I faced the same issue by creating a new scheme, it worked like magic for me.
Go to Project -- > Build Settings --> Testing --> Test Host
Remove all the paths in Test Host, and do a clean build.
Try to run Clean and then Build/Run the project

Resources