xcodebuild command with absolute path to SDK - ios

I am using xcodebuild command line tool to build iOS app.
After instaling Xcode45-DP1 it is automatically using 6.0 SDK from the new Xcode45-DP1 app bundle for building applications. There are 2 issues when submitting this app to AppStore.
The app is now automatically built with latest SDK (6.0), which is note yet supported, so app cannot be submitted.
SOLUTION: I copied the old-current SDK (5.1) to Xcode45-DP.app and in command line specified -sdk iphoneos5.1
Second problem is that when ApplicationLoader is verifying app, is sees that SDK is used from unsupported version of Xcode (45-DP1) and rejects to upload app.
SOLUTION: I would like to specify absolute path for SDK, like: xcodebuild -sdk /path/to/5.1sdk...
The problem is that xcodebuild always says that SDK "/path/to/iPhoneOS5.1.sdk/" cannot be located.
Does anyone have an experience with how to use absolute path to sdk and what file/directory should it point to?
Thanks in advance.

I have been searching for this for a while as well and there does not appear to be a direct way of getting the full absolute path to a specific SDK. However, if you set the -sdk switch and -find-library for an arbitrary library and strip the last few path parts off you can get the full sdk path like so:
[ 13:02 jon#MacBookPro ~ ]$ export SYS_ROOT=`xcodebuild -sdk iphoneos6.0 -find-library system`
[ 13:02 jon#MacBookPro ~ ]$ echo "${SYS_ROOT/\/usr\/lib\/libsystem.dylib/}"
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk
[ 13:02 jon#MacBookPro ~ ]$ export SYS_ROOT=`xcodebuild -sdk iphonesimulator6.0 -find-library system`
[ 13:02 jon#MacBookPro ~ ]$ echo "${SYS_ROOT/\/usr\/lib\/libsystem.dylib/}"
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.0.sdk

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).

Qt-creator examples fail to build for iphonesimulator

I've successfully installed Qt 5.7.0 and Qt-creator 4.1.0 on El Capitan with Xcode 8.
I fixed the xcode sdk-version errors from qt, and now I'm trying to build one of the examples for iphonesimulator. None of them work. All of them fail with error message of type:
The following build commands failed:
CopyPNGFile Debug-iphonesimulator/2dpainting.app/Default-568h#2x.png 2dpainting.xcodeproj/Default-568h#2x.png
I can confirm that directory Debug-iphonesimulator/2dpainting.app does not have the png-file, it's actually located somewhere within the qt installation directories. Copying the png to the source folder does not help as the folder gets overwritten upon running 'make'.
Any advice would be appreciated.
Edit:
The build kit warns about the following issue:
"Device type is not supported by the Qt version". Device type is 'iOS simulator'.
I had the same problem after I had updated my Xcode to version 8.0.
My first error was "Project ERROR: Xcode not set up properly. You may need to confirm the license agreement by running /usr/bin/xcodebuild."
To solve this problem, I created a symbolic link:
cd /Applications/Xcode.app/Contents/Developer/usr/bin/
sudo ln -s xcodebuild xcrun
Then I got error "Project ERROR: Current iphonesimulator SDK version (10.0) is too old. Please upgrade Xcode."
I commented two strings out in file QT_DIR/5.7/ios/mkspecs/macx-ios-clang/features/sdk.prf
lessThan(QMAKE_MAC_SDK_VERSION, "8.0"): \
error("Current $$QMAKE_MAC_SDK SDK version ($$QMAKE_MAC_SDK_VERSION) is too old. Please upgrade Xcode.")
Then I got error about emulator. Qt could not find it. I replaced line of code in file QT_DIR/5.7/ios/mkspecs/macx-ios-clang/xcodebuild.mk from:
IPHONESIMULATOR_GENERIC_DESTINATION := "id=$(shell xcrun simctl list devices | grep -E 'iPhone|iPad' | grep -v unavailable | perl -lne 'print $$1 if /((.*?))/' | tail -n 1)"
to:
IPHONESIMULATOR_GENERIC_DESTINATION := "id=$(shell xcrun simctl list devices | grep -E 'iPhone|iPad' | grep -v unavailable | awk 'match ($$0, /\(([A-F0-9\-]*\))/ ) { print substr ($$0, RSTART+1, RLENGTH-2) }' | tail -n 1)"
And finally afer all of it I got error "The following build commands failed:
CopyPNGFile Debug-iphonesimulator/Test01.app/Default-568h#2x.png Test01.xcodeproj/Default-568h#2x.png"
This error occurred due to the fact that the system has two file xcrun. And script /Applications/Xcode.app/Contents/Developer/usr/bin/copypng starts one, which is a symbolic link. Then I changed path in this script
from:
my $PNGCRUSH = `xcrun -f pngcrush`;
to:
my $PNGCRUSH = `/usr/bin/xcrun -f pngcrush`;
And then I finally had built the project without errors and opened it in Xcode.
I had this stupid error and spent two days to nail down. I was about to downgrade Xcode and thought lets try one more time. Finally nailed down.
Symptom:
The simplest project wont build from Qt Creator. The error I would get: CopyPNG failed or something along the line and a hint '-f' unknown parameter.
Reason: xcrun takes both -f and -find from the terminal I can see, but it does not like -f from the script copypng. (copypng is a perl script by the way.)
The solution: Open the file /Applications/Xcode.app/Contents/Developer/usr/bin/copypng and find
my $PNGCRUSH = `xcrun -f pngcrush`;
changed to
my $PNGCRUSH = `xcrun -find pngcrush`;
PS: I dint have path problem with xcrun, if you have it'd be good to put the whole path as advised above.

Check iOS deployment target of a static library

I have many static libs like libBlah.a
With file tool I can check supported architectures. (arm64 or i386)
Is there tool to check iOS Deployment Target of the static lib?
You can use otool to inspect the library file. With some experimentation I found that the flags -lv gave me useful output. Open up a terminal window and switch to the directory your library is in:
cd /path/to/parent/directory
(Hint: you can drag the icon from the title bar of a finder window into the terminal and it will enter the path for you). Then type the following command:
otool -lv myStaticLibrary.a | less
In less, type / (search) and then LC_VERSION_MIN_IPHONEOS. You should see something like this:
Load command 1
cmd LC_VERSION_MIN_IPHONEOS
cmdsize 16
version 7.0
sdk n/a
The deployment target should be the value next to version.
The target OS version is encoded in the LC_VERSION_MIN_IPHONEOS load command in the MachO header of the static library. You can see it via:
otool -l mylib.a | grep -A 3 LC_VERSION
Example output:
cmd LC_VERSION_MIN_IPHONEOS
cmdsize 16
version 9.0
sdk n/a
have you tried using preprocess macros?
#if IPHONEOS_DEPLOYMENT_TARGET (iOS Deployment Target)

Error when export archive

I have problem with using Export function in Xcode ("Your account already have distribution certificate") so I used solution with xcodebuild. It produce IPA file but I see this in console:
### Checking original app
+ /usr/bin/codesign --verify -vvvv /.../My.app
Program /usr/bin/codesign returned 1 : [/.../My.app: resource envelope is obsolete
]
Codesign check fails : /.../My.app: resource envelope is obsolete
Is it a problem from my side and how to solve it?
If you are using Mac OSX 10.9.5 or later, then there is an issue with OS codesigning with V2 signature.
So, use --no-strict flag with codesign --verify to getover this error.
If you're using PackageApplication to create an .ipa file, then
Edit the PackageApplication perl script tool using vi PackageApplication command and update codesign function occurrences to pass "--no-strict" parameter.
Example:
my $result = runCmd("/usr/bin/codesign", "--verify", "--no-strict",
"-vvvv", , $plugin );
I was facing same and got following response from Apple Dev Team. The issue is resolved for me.
The command line tool “codesign” has changed in 10.9.5 and 10.10, you need to pass “--no-strict” option to the command, (the problem has been reported and will be fixed).
To workaround the problem, please save a copy and modify PackageApplication to pass “—no-strict” to codesign, you can locate PackageApplication by running the following:-
xcrun -sdk iphoneos -f PackageApplication

Failed to generate release build of cordova ios app

I am using phonegap CLI 3.1 and XCode5. I am trying to generate the build for release mode through Phonegap CLI and Xcrun. I don't want to use Phonegap Build to upload the mobileprovision or whatever the process of them. I want to do it by xcrun to assign the mobileprovison to release build.
1) cordova build ios --release
Compiling app on platform "ios" via command
"/Applications/MAMP/htdocs/MyTest/MyTestApp/platforms/ios/cordova/build" --release
Platform "ios" compiled successfully.
2) sudo xcrun -sdk iphoneos PackageApplication -v "ios/build/emulator/MyTestApp.app" -o "/Users/mymac/Desktop/Testnew/MyTestApp.ipa" --sign "iPhone Distribution: NAME (TEAM_ID)" --embed "MyTestApp_Dis.mobileprovision"
Packaging application: 'ios/build/emulator/MyTestApp.app'
Arguments: embed=MyTestApp_Dis.mobileprovision verbose=1 output=/Users/mymac/Desktop/Testnew/MyTestApp.ipa sign=iPhone Distribution: NAME (TEAM_ID)
Environment variables:
HOME = /Users/mymac
SUDO_GID = 20
SDKROOT = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk
VERSIONER_PERL_PREFER_32_BIT = no
MAIL = /var/mail/root
SSH_AUTH_SOCK = /tmp/launch-zsBMC8/Listeners
LANG = en_US.UTF-8
USER = root
LOGNAME = root
__CF_USER_TEXT_ENCODING = 0x0:0:0
USERNAME = root
PATH = /usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/git/bin
SUDO_USER = mymac
SHELL = /bin/bash
TERM = xterm-256color
SUDO_COMMAND = /usr/bin/xcrun -sdk iphoneos PackageApplication -v ios/build/emulator/MyTestApp.app -o /Users/mymac/Desktop/Testnew/MyTestApp.ipa --sign iPhone Distribution: NAME (TEAM_ID) --embed MyTestApp_Dis.mobileprovision
SUDO_UID = 501
VERSIONER_PERL_VERSION = 5.12
Output directory: '/Users/mymac/Desktop/Testnew/MyTestApp.ipa'
Temporary Directory: '/tmp/W81FhZ9VAH' (will NOT be deleted on exit when verbose set)
+ /bin/cp -Rp ios/build/emulator/MyTestApp.app /tmp/W81FhZ9VAH/Payload
Program /bin/cp returned 0 : []
Checking original app
/usr/bin/codesign --verify -vvvv ios/build/emulator/MyTestApp.app
Program /usr/bin/codesign returned 1 : [ios/build/emulator/MyTestApp.app: code object is not signed at all
In architecture: i386
]
Codesign check fails : ios/build/emulator/MyTestApp.app: code object is not signed at all
In architecture: i386
Done checking the original app
Embedding 'MyTestApp_Dis.mobileprovision'
/bin/rm -rf /tmp/W81FhZ9VAH/Payload/MyTestApp.app/embedded.mobileprovision
Program /bin/rm returned 0 : []
/bin/cp -rp MyTestApp_Dis.mobileprovision /tmp/W81FhZ9VAH/Payload/MyTestApp.app/embedded.mobileprovision
Program /bin/cp returned 0 : []
/usr/bin/codesign -d --entitlements /tmp/W81FhZ9VAH/entitlements_rawixGWnKhi /tmp/W81FhZ9VAH/Payload/MyTestApp.app
Program /usr/bin/codesign returned 1 : [/tmp/W81FhZ9VAH/Payload/MyTestApp.app: code object is not signed at all
]
error: Failed to read entitlements from '/tmp/W81FhZ9VAH/Payload/MyTestApp.app'
Hmmh, I'm having a similar problem like Shashi.
When running 'cordova buld ios [--release]' from shell and then doing a 'xcrun ...' afterwards it works for me okay.
BUT: When running this sequence from within a script, I receive a "Codesign check fails ..." error too ...
If I insert (like) a "wait" cycle inside my script between the cordova and the xcrun call, it works.
So - to me - it seems, as if cordova returns to shell while it isn't completely finished (?)
Fact is if I code my script like
#!/bin/bash
cordova build ios --release
sleep 5
sh -c "xcrun ..."
it's working for me.
Question: Is it a bug in cordova/phonegap ???
So, finally I got everything to work okay ... :D
The problem of Jenkins complaining about a failed 'codesign ...' run is a MacOS (configuration) issue
The crucial thing is to allow the Jenkins access to the keychain of the system. The allowed access for the Login-shell of the Jenkins user is different from the Jenkins server process running under the Jenkins user account (!)
For now I realize this by running the unlock of the login.keychain within the Jenkins job before running my build script
like: in the Jenkins job for "execute shell"
security unlock-keychain -p password /Users/Shared/Jenkins/Library/Keychains/login.keychain
echo ##### building now ######################
./buildit.sh ios --release -v
This may not be the 100% nicest solution - but for now it works :P
See as well: [1]: Keychain won't unlock from Jenkins script unless user logged in
Meanwhile I found:
Fact is, that - when cordova exits and returns to shell - cordova related activities are NOT completed yet!
It takes a while after the cordova exit, for the 'platforms/ios/AppName/_CodeSignature/CodeResources' file to show up. This file obviously is essential for the 'codesign' which is started by xcrun command to succeed.
So I do in my script (which i call 'buildit.sh')
#!/bin/bash
[...]
cordova build ios --release
signaturefile="platforms/ios/build/device/$appname/_CodeSignature/CodeResources"
echo DEBUG:signatur file is $signaturefile
while [ ! -f $signaturefile ]
do
echo waiting
sleep 1
done
xcrun ...
Then the whole build/packaging process in one script succeeds.
However: Running the script from my ContinuousIntegration server Jenkins, I observe that this criteria may be essential, but not enough. From the CI I still get a
/usr/bin/codesign --verify -vvvv [...]
Program /usr/bin/codesign returned 1 : [...] code object is not signed at all
error!??
EDIT (05.12.2013): This is due to the fact that the Jenkins service couldn't access the keychain. E.g. doing in the Jenkins job an unlock of the keychain prior running the build script sorts it. (May not be the most elegant solution, but at least it prooves the problem not to be in the scripting :)
In order to skip the code signing you can perform a manual build from the console like this:
xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO
Use additionally the -configuration, -target and -sdk parameters in order to define your build settings.
To Disable Code Signing:
*Go to /Applications.
Right click on XCode and select 'Show Package Contents'.
Copy Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/SDKSettings.plist to your desktop. (Make sure to actually copy and paste. No drag and drop)
Open it and under DefaultProperties set CODE_SIGNING_REQUIRED to NO.
Copy it back and replace the original file.
Restart XCode.
Open your project.
In Project Navigator select your project and open Build Settings section of your porject (and not any particular target)
Under Code Signing find Code Signing Identity and for both Debug and Release modes set Any iOS SKD to Don't Code Sign.
Now you should be able to build your project without any errors.*
To make an IPA:
In 'Project Navigator' select Products
Right click on [NameOfYourProject].app and select 'Show in Finder'.
Create a folder and name it Payload
Move [NameOfYourProject].app to Payload.
Compress Payload and rename it to [NameOfYourProject].ipa

Resources