xcodebuild far slower than Xcode? - objective-c

Building from the command line with xcodebuild is orders of magnitude slower than building the same project, same scheme, same target from within Xcode. Does anyone know why this might be the case and how I might speed up my xcodebuild build?
I'm invoking xcodebuild as follows:
xcodebuild -scheme <SCHEME> -workspace <WORKSPACE> -configuration Debug -sdk iphonesimulator7.0 -jobs 12 build
for building on a 12-core Mac Pro. I guessed at the -jobs setting but it seems reasonable. Does anyone have any advice? Is there a way, by analyzing Xcode's build log, to tell what settings for xcodebuild most closely map to what Xcode itself is using? Thanks!

While this alone may not explain the slowness of xcodebuild compared to IDE, I've seen some improvements if I disable Spotlight indexing on ~/Library/Developer/Xcode/DerivedData directory.

When using xcodebuild test that will reboot the simulator each time. It is the main reason case the xcodebuild slowly. When you using xcode test directly, The simulator will not boot twice after booted.
You can try this:
xcodebuild -project Example.xcodeproj \
-scheme ExampleTests \
-disable-concurrent-destination-testing \
-destination 'platform=iOS Simulator,name=iPhone 13' \
-sdk iphonesimulator \
CODE_SIGNING_ALLOWED="NO" \
test
-disable-concurrent-destination-testing disable clone simulator in Xcode 14 and test in the same simulator
CODE_SIGNING_ALLOWED="NO" disable signing test target will faster

Related

Fastlane Scan: How to add '--screenshots' (xcpretty flag)?

I need to add my screenshots to html-report after Fastlane Scan runs the tests, but here's the problem: --screenshots is xcpretty's flag, not xcodebuild's.
Scan has no such parameter, like xcpretty_args in Snapshot. So now I'm forced to run my tests without Scan but with next script:
set -o pipefail && env NSUnbufferedIO=YES xcodebuild -workspace ./MyProject.xcworkspace -scheme myScheme -destination 'platform=iOS Simulator,name=iPhone 7 Plus,OS=10.3.1' -derivedDataPath 'build'
-only-testing:myTarget/myTestSuite01 test-without-building| xcpretty -r html --screenshots -r junit
So, is it possible to do it any way with Scan?

Universal framework using Xcode 8.3?

I'm trying to build universal swift framework. When I completed developing framework following several tutorials such as
https://medium.com/swiftindia/build-a-custom-universal-framework-on-ios-swift-549c084de7c8
Creating a universal framework using Xcode 8?
Also by using Aggregate target as well but fail to run in Simulator.
Note: I developed using Swift 3, Xcode Version 8.3
I tried with tutorials scripts too but fail.
Also my framework Xcode extension is xcodeproj.
My question is How to develop universal swift framework which will be release to client where he can test through Simulator as well as with real device?
Thanks in advance.
Edit: I followed this answer instruction and successfully build swift framework.
https://stackoverflow.com/a/26691080/614154
You can also use the following script. Supporting Swift and Simulator as well.
just add the content under Project Settings -> Build Phase as new Run Script Phase
Build Project
Folder will open, showing your zipped framework
https://gist.github.com/PaulEhrhardt/6d2be145c5d1b51c216914e7f032013e
#!/bin/sh
# iOS universal library build script supporting swift modules inclusive simulator slices
# prevention from running xcodebuild in a recusive way
if [ "true" == ${ALREADYINVOKED:-false} ]; then
echo "RECURSION: Detected, stopping"
else
export ALREADYINVOKED="true"
# output directory for universal framework
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}/iOS"
# build both device and simulator versions for iOS
xcodebuild -project "${PROJECT_NAME}.xcodeproj" -scheme "${PROJECT_NAME}" -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 8' ONLY_ACTIVE_ARCH=NO clean build
xcodebuild -project "${PROJECT_NAME}.xcodeproj" -scheme "${PROJECT_NAME}" -sdk iphoneos ONLY_ACTIVE_ARCH=NO clean build
# copy the framework structure from iphoneos build to the universal folder
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/iOS"
# copy existing Swift modules from iphonesimulator build to the universal framework directory
SIMULATOR_SWIFT_MODULES_DIR="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/"
if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]; then
cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${UNIVERSAL_OUTPUTFOLDER}/iOS/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule"
fi
# create universal binary file using lipo and place the combined executable in the universal framework directory
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/iOS/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"
# intermediate step for copying the framework to the project's directory
mkdir -p "${TMPDIR}/${PROJECT_NAME}/Frameworks/iOS"
cp -R "${UNIVERSAL_OUTPUTFOLDER}/iOS/${PROJECT_NAME}.framework" "${TMPDIR}/${PROJECT_NAME}/Frameworks/iOS"
# create a zip file and move it to the project's directory
cd "${TMPDIR}/${PROJECT_NAME}/Frameworks/iOS"
zip -r "${PROJECT_NAME}.framework.zip" "${PROJECT_NAME}.framework"
mkdir -p "${PROJECT_DIR}/universal-framework"
mv "${PROJECT_NAME}.framework.zip" "${PROJECT_DIR}/universal-framework"
# optional: show the project's directory in Finder
open "${PROJECT_DIR}/universal-framework"
fi

How to get the IPAs for multiple targets in a same time (Xcode 7.0 GM)?

I have 10 targets in my project and also added Cocoapods. Its difficult to get individual ipa's and takes too much time. Is there any someother way to get the ipa's in a single time?
Can any one suggest me what is the easy to get the 10 target builds ?
Thanks.
You can use a shell script and call xcodebuild ... archive for each target. If you specify the -archivePath argument you can set the archive folder to a local folder then you have access to all of the .ipa files generated during the build.
For example:
#!/bin/sh
for target in target1 target2 target3
do
xcodebuild -project NameOfProject.xcodeproj -configuration Release -scheme $target -archivePath archive.xcarchive -sdk iphoneos archive
done
You will find the .ipa files for all the targets within the archive.xcarchive folder:
find archive.xcarchive -name \*.ipa -print

How to use OCLint for the Cocoa Framework?

Run the following command in the folder with the project:
$ xcodebuild -target MyCocoaFramework -configuration Debug -scheme MyCocoaFramework clean build | tee xcodebuild.log
$ oclint-xcodebuild
$ oclint-json-compilation-database
$
Nothing is displayed.
This approach works fine for Cocoa Application.
$ xcodebuild -target MyCocoaApplication -configuration Debug -scheme MyCocoaApplication clean build | tee xcodebuild.log
$ oclint-xcodebuild
$ oclint-json-compilation-database
/a/b/c/d.m:181:5: redundant local variable P3
/a/b/c/d/e.m:193:5: redundant local variable P3
/a/b/c/d.m:104:1: long line P3 Line with 112 characters exceeds limit of 100
What should be changed to work for the Cocoa Framework?
OCLint can't support the arm64 architecture: https://github.com/oclint/oclint/issues/190
If your code targets iOS 7, then OCLint may fail silently.

OCUnit Application Test with Simulator in terminal

Is it possible to start an application test that runs in the simulator with a terminal command(s)?
Thanks
Yes, I got it to work. My solution is somehow rough and might not be suitable in every case.
Disclaimer: This solution requires to edit system files. It works for
me, but may mess up XCode's unit testing stack, especially if you
do not understand what you are doing.
In /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Tools/RunPlatformUnitTests
replace
if [ "${TEST_HOST}" != "" ]; then
Warning ${LINENO} "Skipping tests; the iPhoneSimulator platform does not currently support application-hosted tests (TEST_HOST set)."
else
with
if [ "${TEST_HOST}" != "" ]; then
mkdir -p "${BUILT_PRODUCTS_DIR}/Documents"
mkdir -p "${BUILT_PRODUCTS_DIR}/Library/Caches"
mkdir -p "${BUILT_PRODUCTS_DIR}/Library/Preferences"
mkdir -p "${BUILT_PRODUCTS_DIR}/tmp"
export CFFIXED_USER_HOME="${BUILT_PRODUCTS_DIR}/"
RunTestsForApplication "${TEST_HOST}" "${TEST_BUNDLE_PATH}"
else
You may move the fixed user home to a different location, but I think you would need to move the .app and .octest bundles along.
Add -RegisterForSystemEvents to the OTHER_TEST_FLAGS build setting of your test bundle.
Make sure your test bundle contains a run script build phase with the contents
# Run the unit tests in this test bundle.
"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests"
Create a new scheme for your tests.
You should be able to run the tests from the command line using the standard xcodebuild:
xcodebuild -workspace $(WORKSPACE_NAME).xcworkspace -scheme $(TEST_SCHEME) -configuration debug -sdk iphonesimulator
The simulator must not be running, at the time you what to run the tests.
I hope this information is complete, if something doesn't work as expected please ask.
You can ensure that the Simulator isn't running with this:
osascript -e 'tell app "iPhone Simulator" to quit'
You can determine if the Simulator is active with this:
sh -c 'ps -xaco command | grep "iPhone Simulator"'
Worked perfectly, thanks!
Automated testing is back in action on our Jenkins CI-server!
Just had to fix my TEST_HOST=${BUNDLE_LOADER}. Do this if you get errors about "no such file" when running the tests.
It seems that with Xcode 4.5GM, running application tests in the simulator is now supported.