xcodebuild linker failing when custom output directory provided - ios

I have a problem using xcodebuild to build the iOS app to custom directory.
Everything works well if I am building using command:
xcodebuild -workspace MyWorkspace.xcworkspace -scheme MyAppScheme -sdk iphoneos -configuration Release ONLY_ACTIVE_ARCH=NO
...but I would like the .app and .dSYM files to be saved in a specific directory (./build for example). So, I tried adding:
CONFIGURATION_BUILD_DIR=./build
or
OBJROOT=./build SYMROOT=./build
as a xcodebuild parameters. Then I've got this error (output comes from xctool as it's more readable, but the same error occurs when using xcodebuild):
✗ Link MyApp
(...)
ld: library not found for -lPods-MyApp-SomePodName
clang: error: linker command failed with exit code 1 (use -v to see invocation)
As I am using Cocoapods, my workspace contains app's project and "Pods" project. I tried using xcodebuild on several other projects that uses Cocoapods and I am always getting this error (SomePodName differs depending on project's dependencies) when trying to provide custom output directory. Please note, that it works without an issue when CONFIGURATION_BUILD_DIR, OBJROOT and SYMROOT parameters are skipped.
I wonder if anything changed recently, because I am pretty sure that I was able to build to custom directory using xcodebuild in the past. Currently, Travis-CI is still able to do it without an issue, but I have no luck when trying on my local machines.
Perhaps providing CONFIGURATION_BUILD_DIR, OBJROOT or SYMROOT is not the perfect way for specifying custom output directory. I am not sure if the problem is connected directly to Cocoapods, but the errors are always connected with some pod library.
Any hints will be appreciated.
My environment:
OS X 10.10.3
Xcode 6.3
xctool 0.2.3
cocoapods 0.36.3
Update: Problem solved
It looks like xcodebuild requires absolute path for CONFIGURATION_BUILD_DIR, OBJROOT and SYMROOT parameters.
Providing absolute path solved the problem:
CONFIGURATION_BUILD_DIR=/Users/me/Dev/MyApp/build

Related

Linking third party frameworks to my own framework, distributed using Carthage

We have several different proprietary API provided to us as Frameworks that offer similar functionality. The API is of course not identical, so we want to build a wrapper facade Framework around these, so our apps do not need to care which of the API they are using.
As a start, I have created a framework that uses one of these APIs and has unit tests that verifies that it works as expected. We have added the third party framework binary as a part of the project, and the Framework search path is like this:
$(inherited)
$(PROJECT_DIR)/Carthage/Build/iOS
$(PROJECT_DIR)
All non-recursive. The Cartage path is here because we use Quick and Nimble for our unit tests. I have the framework in question stored at the project root.
We want to distribute our framework using Carthage, and later also as a Cocoapod.
The problem is that when I try to build our framework by the command: carthage build --no-skip-current --platform iOS, I get the error:
*** Building scheme "Nimble-iOS" in Nimble.xcodeproj
*** Building scheme "Quick-iOS" in Quick.xcworkspace
*** Building scheme "XXX" in XXX.xcodeproj
Build Failed
Task failed with exit code 65:
/usr/bin/xcrun xcodebuild -project /Users/andre/Development/yyy/xxx/XXX.xcodeproj -scheme XXX -configuration Release -sdk iphonesimulator -destination platform=iOS\ Simulator,id=AE9E3D9D-BE2C-4AE1-AB37-C6BE8948067B -destination-timeout 3 ONLY_ACTIVE_ARCH=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= CARTHAGE=YES build (launched in /Users/andre/Development/yyy/XXX)
And the log contains this:
iphonesimulator/XXX.build/Objects-normal/i386/XXXLockService.o
/Users/andre/Development/yyy/XXX/XXX/LockServiceFactory.swift:7:71: error: 'PinServiceAccessImpl' is unavailable: cannot find Swift declaration for this class
case .xxx: return XXXLockService(lockService: PinServiceAccessImpl.getInstance())
^~~~~~~~~~~~~~~~~~~~
PinServiceAccess.PinServiceAccessImpl:2:12: note: 'PinServiceAccessImpl' has been explicitly marked unavailable here
open class PinServiceAccessImpl : NSObject {
When using a framework from an app, the documentation states that we should add the framework's as an embedded binary, but this option is not available when the project is a framework.
What puzzles me is that the unit tests seems to find the PinServiceAccessImpl.getInstance()!
I guess there are some details about linking that I don't know about that makes the build fails. Does anyone have an idea of what we are missing out?
The problem got solved when updating the deployment target to 11.0.

Error running xcodebuild parallel jobs with same Cocoa Pod in frameworks & app

We have an Xcode workspace (for an iOS app) which consists of multiple frameworks and a reference application which links to and uses the frameworks and the frameworks themselves as well as the reference application use the same pod (or pods).
I've created a simple application that exhibits the same error, it's up on Github (https://github.com/hds/ios-app-with-sdks). I'll just explain everything in terms on the sample application, as it should be easier to follow that way.
The project dependancy chart looks like this:
AppWithSDKs
|- TheSDK
| |- ReactiveCocoa
|- OtherSDK
| |- ReactiveCocoa
|- ReactiveCocoa
ReactiveCocoa is one of the pods that I'm using in multiple places, so I've used in in the sample project as well. I don't think that ReactiveCocoa has anything to do with this error.
Building this project from the command line with xcodebuild produces a variety of errors, always related to the pod used in multiple parts of project. The most common error is in the code signing step, but I get errors related to setting file permissions and ownership as well. The errors always complain about the file that is to be signed (or have its permissions set) not being present.
The build command is:
xcodebuild -verbose -workspace AppWithSDK.xcworkspace -scheme AppWithSDK -sdk iphoneos8.4 -derivedDataPath Build -configuration Release archive -archivePath Build/Products/
An example of an error that I've seen is:
/usr/sbin/chown -RH <user>:<group> /path/to/project/AppWithSDK/Build/Build/Intermediates/ArchiveIntermediates/AppWithSDK/IntermediateBuildFilesPath/UninstalledProducts/ReactiveCocoa.framework
chown: /path/to/project/AppWithSDK/Build/Build/Intermediates/ArchiveIntermediates/AppWithSDK/IntermediateBuildFilesPath/UninstalledProducts/ReactiveCocoa.framework/Headers/UITextView+RACSignalSupport.h: No such file or directory
Command /usr/sbin/chown failed with exit code 1
The suspicion is that xcodebuild is doing something in parallel that shouldn't be performed in parallel, but I don't know what that is. If we run xcodebuild with -jobs 1 then there are no errors. The project also builds fine when it's compiled from the Xcode app.
Obviously the problem isn't a showstopper at the moment, but if we have to build in serial on the command line, it's going to make our Jenkins builds much slower.
Thanks in advance for any guidance or help.

Why when generating .app file, xcode needs to be open?

I'm writing a script to build and generate an .app file from an specific target and scheme (to work with simulator). I was using something like:
DEVELOPER_DIR=$xcode_app_path/Contents/Developer xcodebuild -sdk iphonesimulator -scheme "${SCHEME}" -target "${TARGET}" ONLY_ACTIVE_ARCH=NO CONFIGURATION_BUILD_DIR="${build_folder}" clean build
The problem is, that I need to open XCode for the code above to work, otherwise will show me a message telling me that:
xcodebuild: error: The project 'Project-name' does not contain a scheme named "${SCHEME}"
I still yet, don't understand what is XCode doing in background. But if I open the IDE and run the script, works. If I open and later close it, and run the script works. It's not working if the project hasn't been opened first with XCode ¬¬
Any suggestion would be appreaciated
If someone is facing the same experience, this is what I found out. And works.
Well, apparently when you create a new scheme through command line, by default is not "shared". So when you start to link to the folder
xcshareddata --> xcschemes
(trying to build with command line, for example) there's nothing to link with. Xcode do this automaticaly under the hood when you open your project...
The guys from CocoaPods were facing the same issue, so they created a Ruby gem that shares the scheme and place the file in his xcscheme folder:
This is the repo: https://github.com/CocoaPods/Xcodeproj
Also, thanks to this post and this post I found out how to use xcodeproj gem, and change the shared option with a script that I put downhere:
require 'xcodeproj'
xcproj = Xcodeproj::Project.open("MyProject.xcodeproj")
xcproj.recreate_user_schemes
xcproj.save

Implicit dependencies do not work with xcodebuild

I have a little problem with one of my projects. In my workspace I have my main project and a lot of projects for static libraries. When I build from Xcode, everything works fine, but with xcodebuild, one of my project is not built, it seems that implicit dependencies do not work.k. Maybe I did something wrong with my configuration. So there it is.
My scheme configuration:
My QAPreferences.a information:
My target settings:
From Xcode, if I build with buildAppTarget in debug for iphoneos, it works.
From xcodebuild, with command below, QAPreferences project is not built.
xcodebuild -workspace myProject.xcworkspace -scheme buildApp -configuration Debug -sdk iphoneos
It worked before, but I recently added QAPreferences, and it does work since this moment. Maybe the problem comes from QAPreferences project...
Regards,
Quentin
So I finally found why the QAPreferences was not build through xcodebuild but I still do not understand the reason. In fact QAPreferences 'Build Archive Architecture Only' was set to YES, I just set it to NO and now it works!
I had a similar issue but forgot to specify the -workspace argument to xcodebuild, which led to it seeming like the implicit dependencies weren't working correctly. I realize this wasn't the issue with the original question, but for people having issues with implicit dependencies, this could be helpful.

Xcode 4 - command line target with initial setup

I am implementing an app which has a dependency to a command line tool.
This is because there are some presets to do.
The command line tool is responsible to create a sqlite file with all initial information needed by the app (clearly speaking: its just a tool to add some initial data to the app).
Now the problem is, that during debugging everything works fine but if I'll do a release build, some errors occur.
The first error was
target specifies product type 'com.apple.product-type.tool', but there's no such
product type for the 'iphoneos' platform"
This was because my main app had the command line tool as a target dependency.
I solved this by removing the target dependency and added the build to a run script phase:
#Build the initial setup target
xcodebuild -target InitialCoreDataSetup -sdk macosx -configuration $CONFIGURATION
#Run initializing data target to get current sqlite file
cd "$CONFIGURATION_BUILD_DIR"
cd ..
cd "$CONFIGURATION"
current_dir=$(pwd)
./InitialCoreDataSetup "$current_dir" "$SRCROOT" "$CONFIGURATION"
Now the problem is, that I get the following error:
=== BUILD NATIVE TARGET InitialCoreDataSetup OF PROJECT XY WITH CONFIGURATION AdHoc ===
Check dependencies
SDK Configuration Error: no wrapper for product type #
I have absolutely no idea how to fix this.
Any suggestions?
How do you provide your app with an initial sqlite file?
Thanks in advance for any help!
EDIT
At the moment the build phases of my app target are the following:
BTW: I finally got that working by the following line:
#Build the initial setup target
export DYLD_FRAMEWORK_PATH="$SYMROOT/Debug"
/usr/bin/env -i xcodebuild -target InitialCoreDataSetup -sdk "macosx" -configuration Debug OBJROOT="$SYMROOT/Debug" SYMROOT="$SYMROOT"
echo "$SYMROOT/Debug"
#Run initializing data target to get current sqlite file
cd "$SYMROOT/Debug"
./InitialCoreDataSetup "$SYMROOT/Debug" "$SRCROOT" "$CONFIGURATION"
The trick is to start the initialCoreDataSetup always in DEBUG mode
I would suggest letting Xcode do the build in this situation since you should be able to generate the sqllite file by using a build rule to run a script before the other build rules run.

Resources