xcodebuild target name with Umlaut - ios

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.

Related

Turn Package.swift file into binary XCFramework

Someone in my company created a Swift package SDK and now I was tasked to publish it for the customer in a binary way so that the end customers that will use the SDK will not be able to see the source code of it. This is how the SDK is built:
the SDK in xcode (p.s. the build folder is empty)
From my reading on the subject I understand that I need to export the files into an XCFramework file. However, the vast majority of guides I've encountered explain how to make this progress from a framework, and not from a package like in my case..
The only guide I found that seems exactly like what I need is this one, however I get an error right on the first relevant terminal command of xcodebuild -scheme [my scheme name] -sdk iphoneos -configuration Release ARCHS="arm64" BUILD_DIR="./Build". This is the main error line I get: xcodebuild: error: Building a Swift package requires that a destination is provided using the "-destination" option. The "-showdestinations" option can be used to list the available destinations.. Why would I need to specify a destination? I want the SDK to work for all the devices (ios 13+). Non of the forums I searched in online helped me solve this.
I also read Apple's instructions here but got very confused about how the terminal command in step 2 is supposed to look like in my case. Are some of the fields mandatory and some are not?
Any help would be much appreciated!!
Assuming you are working with iOS only and you need an xcframework for both device and simulator architectures, in order to generate an XCFramework from a swift package you need to:
Mark your Package as .dynamic (i.e. .library(name: "Foo", type: .dynamic, targets: ["Foo"]))
Archive the project for both simulator and device. This will generate a .framework file for each architecture.
Copy Modules folders (if any) into the .xcarchive files
Copy the bundles (if any) into the .xcarchive files
Create the xcframework with the frameworks created in step 2
Here's a bash script, based on the one from this swift forums post, to create an XCFramework from a swift package (in my case, I have my package inside an xcworkspace. I didn't try it as a standalone package, not sure if that can be done):
Change the input parameters as needed :), but most importantly replace <Your project name> and <your workspace>.
#!/bin/bash
PROJECT_NAME="<Your project name>"
PROJECT_DIR="./Packages/${PROJECT_NAME}" # Relative path to the directory containing the `Package.swift` file
BUILD_FOLDER="./build"
OUTPUT_DIR="${PROJECT_DIR}/Output"
SIMULATOR_ARCHIVE="${OUTPUT_DIR}/${PROJECT_NAME}-iphonesimulator.xcarchive"
DEVICE_ARCHIVE="${OUTPUT_DIR}/${PROJECT_NAME}-iphoneos.xcarchive"
rm -rf "$OUTPUT_DIR"
mkdir -p "$OUTPUT_DIR"
# 2 iterations: 1 for device arch and another for simulator arch
for PLATFORM in "iOS" "iOS Simulator"; do
case $PLATFORM in
"iOS")
ARCHIVE=$DEVICE_ARCHIVE
SDK=iphoneos
RELEASE_FOLDER="Release-iphoneos"
;;
"iOS Simulator")
ARCHIVE=$SIMULATOR_ARCHIVE
SDK=iphonesimulator
RELEASE_FOLDER="Release-iphonesimulator"
;;
esac
# Step 2
xcodebuild archive \
-workspace <your workspace>.xcworkspace \
-scheme $PROJECT_NAME \
-destination="generic/platform=${PLATFORM}" \
-archivePath $ARCHIVE \
-sdk $SDK \
-derivedDataPath $BUILD_FOLDER \
SKIP_INSTALL=NO \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
FRAMEWORK_PATH="${ARCHIVE}/Products/Library/Frameworks/${PROJECT_NAME}.framework"
MODULES_PATH="$FRAMEWORK_PATH/Modules"
mkdir -p $MODULES_PATH
BUILD_PRODUCTS_PATH="${BUILD_FOLDER}/Build/Intermediates.noindex/ArchiveIntermediates/${PROJECT_NAME}/BuildProductsPath"
RELEASE_PATH="${BUILD_PRODUCTS_PATH}/${RELEASE_FOLDER}"
SWIFT_MODULE_PATH="${RELEASE_PATH}/${PROJECT_NAME}.swiftmodule"
RESOURCES_BUNDLE_PATH="${RELEASE_PATH}/${PROJECT_NAME}_${PROJECT_NAME}.bundle"
# Step 3
if [ -d $SWIFT_MODULE_PATH ]
then
cp -r $SWIFT_MODULE_PATH $MODULES_PATH
fi
# Step 4
if [ -e $RESOURCES_BUNDLE_PATH ]
then
cp -r $RESOURCES_BUNDLE_PATH $FRAMEWORK_PATH
fi
done
# Step 5
xcodebuild -create-xcframework \
-framework "${DEVICE_ARCHIVE}/Products/Library/Frameworks/${PROJECT_NAME}.framework" \
-framework "${SIMULATOR_ARCHIVE}/Products/Library/Frameworks/${PROJECT_NAME}.framework" \
-output "${OUTPUT_DIR}/${PROJECT_NAME}.xcframework"
When the script ends, you will see 3 files in the output folder:
Device xcarchive
Simulator xcarchive
XCFramework
You can remove the xcarchives, as you won't need them anymore (you can also update the script to do that for you).

Export all localizations on the command line in Xcode

I have 26 languages successfully localized and tested. I am able to successfully export all 26 localizations with option: "Editor" -> "Export for Localization...", then selecting all of them.
However, when I use the following xcodebuild command, it exports my default language "en", and nothing else.
xcodebuild -exportLocalizations -localizationPath TempLocalizationExport
How do I export all twenty-six Localizations rather than just "en"?
There are no command line errors outputted from the command.
I've seached everywhere for official xcodebuild commandline command documentation on developer.apple.com, and I can't find a verbose and helpful source that addresses additional -exportLocalizations options and standard behavior.
According to the docs:
To export localizations, enter this command in Terminal, replacing the
dirpath and projectname arguments:
xcodebuild -exportLocalizations -localizationPath <dirpath> -project <projectname> [[-exportLanguage <targetlanguage>]]
The exported XLIFF files are placed in dirpath. Optionally, use the
exportLanguage argument to export other localizations.
UPDATE:
The OP discovered that multiple languages can be exported by repeating the -exportLanguage argument. For example, this command exports two languages:
xcodebuild -exportLocalizations -localizationPath TempLocalizationExport -exportLanguage es -exportLanguage ru
Seems xcodebuild doesn't support auto export all localizations at this time.
But we can do it through Xcode interface.
Also it's possible auto select all localizations with a script. Read knownRegions section in project.pbxproj, loop to argument format.

Xcode 8 and exportPath

Starting with Xcode 8, my TeamCity builds no longer create an Artifact with the proper name. Here is my command line to export archive:
xcodebuild -project "${XCODE_PROJECT}" -exportArchive \
-archivePath "${ARTIFACT_DIR}${ARTIFACT_NAME}.xcarchive" \
-exportPath "${ARTIFACT_DIR}${ARTIFACT_NAME}.ipa" \
-exportOptionsPlist ./export-appstore.plist
If ARTIFACT_DIR and ARTIFACT_NAME result in "/builds/myApp-1.0.1.ipa", for example, xcodebuild will actually create "/builds/myApp-1.0.1.ipa/myApp.ipa".
The "man" documentation for '-exportPath' says "Specifies the destination for the exported product, including the name of the exported file". But clearly it's assuming the file name from the Xcode project and using the entire parameter just for the path.
Is this a known bug that will be fixed, or did they remove functionality with this latest version of Xcode?

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.

Resources