xcodebuild command line ignoring GCC_PREPROCESSOR_DEFINITIONS - ios

I'm trying to launch xcodebuild with different preprocessing macros.
I've tried :
xcodebuild -scheme myscheme \
-configuration "Archive" \
-sdk "iphoneos5.1"
archive \
CONFIGURATION_BUILD_DIR=../build \
GCC_PREPROCESSOR_DEFINITIONS=ADHOC
but i got a compilation error due to the fact the preprocessor was not used:
I couldn't see it with the -D flag of the compilation command
But it is displayed at the beginning of the script
Build settings from command line:
CONFIGURATION_BUILD_DIR = ../build
GCC_PREPROCESSOR_DEFINITIONS = ADHOC
SDKROOT = iphoneos5.1
The code at the origin of the compilation error is:
#ifdef ADHOC
NSUInteger toto = 0;
#endif
but i get a use of undeclared identifier error for toto
ps : if i do define Preprocessor Macros in Xcode, then these values are used, mine are overridden, and archiving is done. But I do want to make several builds based on different preprocessor definitions (which sounds a better idea than creating new build configurations or schemes to me)

I have to use double quote and remove the $value.
I had,
GCC_PREPROCESSOR_DEFINITIONS='$value ${e}',
which did not work, but
GCC_PREPROCESSOR_DEFINITIONS="${e}"
works.
Where, e is variable inside a loop,
environments=("TEST1" "TEST2" "TEST3" "TEST4" "TEST5" "PROD")
for e in "${environments[#]}"
do
....... commands
done
If I use
GCC_PREPROCESSOR_DEFINITIONS='$value ${e}'
Then I have to use like,
GCC_PREPROCESSOR_DEFINITIONS='$value ADHOC=1'
This worked in one of build script.

Related

XCBuild shows error while calling fastlane gym

I have an app with multiple targets and try to configure fastlane's gym. Also, we use pretty extensively compiler flags in the app.
I get this error FIXME: Implement XCBuild support for macros in overriding parameters with condition sets: DEVELOPMENT_TEAM[config=Release] = ***.
The error appears after gym executes this xcodebuild command:
set -o pipefail && xcodebuild -workspace Workspace.xcworkspace -scheme Scheme -xcconfig Config.xcconfig -sdk 'iphoneos14.5' -destination 'generic/platform=iOS' -archivePath archivePath.xcarchive archive | tee Myapp.log | xcpretty
The app is native, no Ionic or ReactNative or any of that stuff.
Do you have any idea where does come from? Or how I can solve it?
Thanks for the help.
For anybody stumbling upon this question, I found the solution in this blog. Quoting from the blogpost:
Example:
CURRENT_PROJECT_VERSION_app = 15.3.9 // Application version number
CURRENT_PROJECT_VERSION_xctest = 1.0.0 // Unit Test version number
CURRENT_PROJECT_VERSION = $(CURRENT_PROJECT_VERSION_$(WRAPPER_EXTENSION))
where in my case WRAPPER_EXTENSION would be CONFIGURATION variable.

Define a preprocessor macro value from a shell script in iOS

We have an app that we want uploaded to a site with a different app id based on the the environment it's being built in. In the project we have a Release preprocessor macro set to MY_CONFIGURATION=$(MY_CONFIGURATION) and we set a default value to 3 in the user-defined settings. In our define where we assign the app id string value based off the macro define, we also have the fallback that if the value is not defined, use the value 1. The problem is when we build off Jenkins, the script assigned value (2) is overwritten by the default value from the user-defined settings (3).
Here's the line we are using in the build.sh file
xcodebuild -scheme ${SCHEME} -sdk ${SDK} -destination generic/platform=iOS CODE_SIGN_IDENTITY="${PROFILE}" MY_CONFIGURATION="${BUILD_ENV}" build
I know the correct value is being placed, as the console output from Jenkins shows the following
10:58:46 + xcodebuild -scheme MGO -sdk iphoneos9.0 -destination generic/platform=iOS 'CODE_SIGN_IDENTITY=X' MY_CONFIGURATION=2 build
10:58:47 Build settings from command line:
10:58:47 CODE_SIGN_IDENTITY = X
10:58:47 MY_CONFIGURATION = 2
10:58:47 SDKROOT = iphoneos9.0
The build uploads to the correct environment, build the #define within the code that sets the app id based on the value set displays the default value set (3) instead of the script value set (2). Any tips or help would be appreciated.
Note: I've also tried
xcodebuild -scheme ${SCHEME} -sdk ${SDK} -destination generic/platform=iOS CODE_SIGN_IDENTITY="${PROFILE}" OTHER_CFLAGS="-DMY_CONFIGURATION="${BUILD_ENV}"" build
I use xctool to build and it works perfect.
I think it works the same way in your situation and you can give it a try. Here's what I do.
xctool -workspace productname.xcworkspace -scheme "$scheme" archive -archivePath $archivePath GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS="MY_CONFIGURATION=2 MY_ANOTHER_CONFIGURATION=1"
What makes it work is GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS.
GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS="MY_CONFIGURATION=2 MY_ANOTHER_CONFIGURATION=1"
You can try to append this line above to your command. Make sure the value is a number. I failed when tried to use a string value. And there's another related keyword GCC_PREPROCESSOR_DEFINITIONS in the doc.

Accessing user defined variables passed in from xcodebuild command line

I am running my xctests using xcodebuild and need to pass in some environment variables.
In the example below ACCOUNT_ID and HOST_URL.
I tried passing in the variables as both environment variable and accessing them from the test using getenv ("ACCOUNT_ID")
xcodebuild -project CalculatorTestClient.xcodeproj -scheme CalculatorTestClient -destination '%s' ACCOUNT_ID=%s HOST_URL=%s test"
And passing them in as user defaults and accessing them using [[NSUserDefaults standardUserDefaults] valueForKey:#"HOST_URL"];
xcodebuild -project CalculatorTestClient.xcodeproj -scheme CalculatorTestClient -destination '%s' ACCOUNT_ID=%s HOST_URL=%s test"
Neither approach worked for me.
What is easiest way to pass user defined variables from commandline?
Similar to #Paul Young I was able to get this to work, with a couple of modifications to the Scheme. Here's my solution:
For the Scheme in Xcode (Xcode > Your Scheme > Edit Scheme > Test > Arguments tab > Environment Variables):
Name
Value
ACCOUNT_ID
$(ACCOUNT_ID)
HOST_URL
$(HOST_URL)
In Code (Swift 3):
let accountID = ProcessInfo.processInfo.environment["ACCOUNT_ID"]!
let hostURL = ProcessInfo.processInfo.environment["HOST_URL"]!
On the command line:
$ xcodebuild -project YourProject.xcodeproj \
-scheme "Your Scheme" \
-sdk iphonesimulator \
-destination 'platform=iOS Simulator,name=iPhone 7,OS=10.2' \
-derivedDataPath './output' \
ACCOUNT_ID='An Account ID' \
HOST_URL='www.hosturl.com' \
test
For iOS, make sure to do modify the scheme with the following:
Uncheck the Use the Run action's arguments and environment variables
Change the drop down "Expand Variables Based On" to the
Test target in the Test scheme.
What I did for my case is I used the xcodebuild build-for-testing command and create the xctestrun file then using xcodebuild test-without-building to run the test . in this case you can change the xctestrun file which has the environment variables in its plist before running your test .
so you need to run a script by using PlistBuddy to change your plist environment keys . for example to add a key :
/usr/libexec/PlistBuddy -c "add :APPNAME-TARGETNAME:EnvironmentVariables:KEYNAME string 'VALUE'" "(Path to XCTestRun file)"
So far I've only been able to get this approach to work:
$ ACCOUNT_ID=foo HOST_URL=bar xcodebuild -project CalculatorTestClient.xcodeproj -scheme CalculatorTestClient clean test
and accessed them via:
NSDictionary *environment = [[NSProcessInfo processInfo] environment];
NSString *accountID = [environment objectForKey:#"ACCOUNT_ID"];
NSString *hostUrl = [environment objectForKey:#"HOST_URL"];

xcodebuild target name with Umlaut

I am trying to build an iOS App using Jenkins via the xcodebuild command.
The problem is that xcodebuild does not detect the target with the German Umlaut ü.
$ /usr/bin/xcodebuild -target AppNameWithUmlautü -configuration Debug clean build
gives me following error:
xcodebuild: error: The project 'AppNameWithUmlautü.xcodeproj' does not contain a target named 'AppNameWithUmlautü'.
I checked the existence of the target using following command:
xcodebuild -list
Information about project "AppNameWithUmlautü":
Targets:
AppNameWithUmlautü
AppNameWithOutUmlaut
Build Configurations:
Debug
Release
Ad Hoc
If no build configuration is specified and -scheme is not passed then "Release" is used. This project contains no schemes.
The target without Umlaut works.
Xcode uses the "decomposite" UTF-8 representation for Umlauts in the target name: "ü" is represented as 75 CC 88. 75 is "u", and CC 88 is the UTF-8 sequence for the "COMBINING DIAERESIS".
The shell, on the other hand, uses the "composite" UTF-8 representation C3 BC for "ü".
So the target that you give on the command line does not match the target name in the Xcode project (and one could argue that this is a bug in Xcode).
I have no knowledge about Jenkins, but if you somehow can use the output of the xcodebuild -list command to get the decomposite UTF-8 target name and copy that into your Makefile, shell script or whatever you have, then this should help.

Find the ${PROJECT_DIR} for an Xcode project

How do I figure out what my absolute ${PROJECT_DIR} path is for my Xcode project? Is there a way to print this in Terminal? How?
Build Settings -> Preprocess Macros
PROJECT_DIR=#\""$PROJECT_DIR"\"
BUILD_ROOT=#\""$(BUILD_ROOT)"\"
Then you can log it directly
NSLog(#"project dir=%#, BUILD_ROOT_=%#", PROJECT_DIR, BUILD_ROOT);
Run this from Terminal
For a project:
xcodebuild -project yourProject.xcodeproj -target yourTarget -showBuildSettings | grep PROJECT_DIR
For a workspace:
xcodebuild -workspace yourWorkspace.xcworkspace -scheme yourScheme -showBuildSettings | grep PROJECT_DIR
As you can see, you can retrieve any other build settings value
Another interesting method is using a Run Script Phase in Build phases:
Then paste this script that will modify a swift file in your project
fileContent="// DO NOT EDIT,
// THIS IS AUTOMATICALLY GENERATED FILE
// params.swift
//
import Foundation
class Params {
static let srcRoot: String = \"${PROJECT_DIR}\"
}"
echo "${SRCROOT}/YourProjectFolderName/params.swift"
echo "$fileContent" > ${SRCROOT}/YourProjectFolderName/params.swift`
Make sure you added Params.swift in you project.

Resources