Accessing user defined variables passed in from xcodebuild command line - ios

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"];

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.

xcodebuild command in shell script iOS

I have a complete command to deploy the xCode project on real device.
i.e
xcodebuild -workspace jamesAppV2.xcworkspace -scheme jamesAppV2 -configuration Debug -destination 'platform=iOS,name=Shujaat’s iPad' clean test
its working fine using the command line.
Todo: I wanted to execute this command via a shell script.
here is my complete shell script deploy.sh so for.
#!/bin/bash
#My First Script
#Info to be configured
current_path=$(pwd)
appName="jamesApp"
jamesApp_workspace="jamesAppV2.xcworkspace"
echo "Searching for $jamesApp_workspace workspace..."
if [[ $(ls $jamesApp_workspace) ]]; then
echo "$jamesApp_workspace found in current directory."
echo "Listing all installed and connected devices..."
instruments -s devices
echo "Copy + Paste from above devices"
echo "specify name of your decice to launch $appName"
read d_device_name
echo "building workspace for $d_device_name..."
build_cmd=(xcodebuild -workspace jamesAppV2.xcworkspace -scheme jamesAppV2 -configuration Debug)
destination="'platform=iOS,name=$d_device_name'"
build_cmd+=(-destination "$destination" clean test)
echo "${build_cmd[#]}"
# Here it prints the valid command given above
"${build_cmd[#]}"
else
echo "$jamesApp_workspace workspace not found"
echo "Make sure your current path contains the $jamesApp_workspace workspace"
echo "Place this file i.e deploy.sh within the directory containing $jamesApp_workspace workspace"
fi;
Problem:
I have done like
build_cmd=(xcodebuild -workspace jamesAppV2.xcworkspace -scheme jamesAppV2 -configuration Debug)
destination="'platform=iOS,name=$d_device_name'"
build_cmd+=(-destination "$destination" clean test)
echo "${build_cmd[#]}" #Prints valid command
"${build_cmd[#]}"
but gives error on execution
xcodebuild: error: option 'Destination' requires at least one parameter of the form 'key=value'
if I run the above command via command line its working perfectly but If I run this via shell script its not working.
I have referred I want to concatenate arguments of xcodebuild as string, which have space in it ,then run this command to concatenate the xcodebuild command
The shell removes the single quotes in the original command, therefore you should not have any when creating the array either.
I am also trying to execute the command in a similar way by passing it via a string. The command works without the double quotes anywhere on the command for me.
example:
$ xcodebuild -project ~/ios_projects/example.xcodeproj -scheme Xcode9-XCtest destination id=EBCDFH7S-DCJD-EE8D-DSKDKD78

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.

xcodebuild command line ignoring GCC_PREPROCESSOR_DEFINITIONS

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.

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