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

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

Related

What cmake command will copy a directory of files to a directory in a post build step

I have a set of resource files that have nothing to do with the build steps of GCC or some other compiler's output. I need them copied from a folder in my project to the cmake build output folder. The goal is for the executable, when run from the build output folder, can see the resources.
How do people typically copy and install resources in cmake builds? Additionally, I want them copied regardless of changes in the build and I want it executed every time I run some cmake command, like build. See below for what I tried to solve this issue.
For example:
I have a bunch of shader files that I want copied. All shaders/* files should be copied into a directory in the build output called "shaders", because that's where the executable for the program lives.
file(GLOB out shaders/*)
foreach (o ${out})
message("${o} was copied to shaders")
file(COPY ${o} DESTINATION shaders)
endforeach ()
This only works sometimes, like when I reload the CMake project, e.g.:
/opt/clion-2021.2.3/bin/cmake/linux/bin/cmake \
-DCMAKE_BUILD_TYPE=Debug -DCMAKE_DEPENDS_USE_COMPILER=FALSE \
-G "CodeBlocks - Unix Makefiles" \
/home/hack/glad
Also, it doesn't execute "POST_BUILD", so the lastest version of the shaders/a.vert file doesn't get copied to the shaders/ directory in the output.
I tried using this, too, but it gave me some headaches:
add_custom_command(TARGET my-executable POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy shaders/* shaders)
I think there's something incorrect with that above, because it wasn't run every POST_BUILD if the build's code didn't change. I don't care if the build's code doesn't change because the files in shaders/* could have changed and should be copied regardless of cmake determining if there was a change in my-executable.
This gist on github was very helpful, here but the gist that applies to my question is included below.
add_custom_target(bar
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/shaders
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/shaders ${CMAKE_BINARY_DIR}/shaders
COMMENT "copying ${CMAKE_SOURCE_DIR}/shaders to ${CMAKE_BINARY_DIR}/shaders"
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
The above code creates a bar cmake target that can be run separately with Make bar; then, if you add another target that requires those resources (the shaders above are resources for this other executable) then you can tie the dependency together using add_dependencies like this:
add_executable(a
main.c
opengl.c)
add_dependencies(a bar)
Now, every time the a target is run, the bar target is run as well, which has the effect of creating the directory and copying the files.
This was good enough for me, but to finish up, you can use this to create the files in a post build step after the other dependency is finished running:
add_custom_command(TARGET bar
# Run after all other rules within the target have been executed
POST_BUILD
COMMAND echo "executing a POST_BUILD command"
COMMENT "This command will be executed after building bar"
VERBATIM
)
Note that ${CMAKE_COMMAND} in the above examples of add_custom_command is a variable that points to the cmake executable, and you can run cmake -E to see the very helpful list of commands that come with cmake.
YIKES the post build step is only running after bar's target is built, not a's target. Hopefully, somebody can help me answer this better. I would still like to know how to copy files after a target is built, unless that's completely unnecessary and nobody should ever want to do that.

How to restrict cmake commands based on which target is built

I have a cmake project which produces several executables. I want to package each executable in seperate Docker containers, so inside the Dockefile, I only built the target that I need:
RUN mkdir build \
&& cd build \
&& cmake /app/project -DCMAKE_BUILD_TYPE=Release
&& make -j 2 myExecutable \
&& make install/fast
This works as expected, but I run into an issue with the conan cmake integration. The installation is done when cmake is called, not during the actual build - this means that no matter which target I want to actually build, all the conan installation calls present in my cmake files are called - so way more packages are installed than necessary.
# for every target
# include conan dependencies (each target has its own conanfile.txt)
conan_cmake_run(CONANFILE conanfile.txt
BASIC_SETUP CMAKE_TARGETS
BUILD_TYPE "${CMAKE_BUILD_TYPE}"
BUILD outdated
${update_conan}
)
conan_target_link_libraries(${PROJECT_NAME})
Is there a way to make the cmake calls dependend on which target I actually want to build?
Unfortunately not, the macro conan_cmake_run has no distinction about which target is involved or even it was executed before. You could use CMake options to run or not conan_cmake_run.
Also, you could comment/vote your request thorough the issue https://github.com/conan-io/cmake-conan/issues/105
Regards!

Can xcodebuild delete the contents of the project's Build Folder?

Back in Xcode 9, there was a build option called "Clean Build Folder..." (⌥⇧⌘K), which deleted all files in the build folder, only leaving the folder behind with no contents. Since then, this behavior was removed, the menu item's title changed to "Clean Build Folder", and now behaving like the old "Clean" used to.
xcodebuild has a build option called clean which simply does the same thing as Xcode's "Clean Build Folder" (⌘⇧K), which leaves stuff around.
Is there any way to delete all files in the build folder via a scriptable command?
What I've tried so far:
xcodebuild clean -workspace "My Workspace.xcworkspace" -scheme "My Scheme"
This, as I said, doesn't actually clean everything up. For that, I added this bodge to my build script:
export IS_XCODE_CACHE_FOLDER_PRESENT="`ls -la ~/Library/Developer/ | grep -x "Xcode"`"
if [ 0 -ne "$IS_XCODE_CACHE_FOLDER_PRESENT" ]; then
echo "Xcode cache folder should not be present at build time! Attempting to delete..."
rm -rf "~/Library/Developer/Xcode"
RM_RESULT=$?
if [ 0 -ne "$RM_RESULT" ]; then
echo "FAILED to remove Xcode cache folder!"
exit $RM_RESULT
fi
fi
I faced a similar requirement. So after trying for several hours, I resolved to a custom script instead of using Xcode's run script.
So instead of using Xcode to run the app on the simulator I use my script which in turn first cleans the build folder, then builds the project, then installs and finally launches the app in the simulator.
Here is what I am using as a quick script:
# Delete Build directory
rm -rf ./build/Build
# pod install
pod install
# Build project
xcrun xcodebuild -scheme Example -workspace Example.xcworkspace -configuration Debug -destination 'platform=iOS Simulator,name=iPhone 11 Pro Max,OS=13.1' -derivedDataPath build
# Install App
xcrun simctl install "iPhone 11 Pro Max" ./build/Build/Products/Debug-iphonesimulator/Example.app/
# Launch in Simulator
xcrun simctl launch "iPhone 11 Pro Max" com.ihak.arpatech.Example
Note: See this question I posted to know the issue I was facing.
You can add clean action.
xcodebuild clean build -workspace "My Workspace.xcworkspace" -scheme "My Scheme"
see more in man xcodebuild
action ...
Specify one or more actions to perform. Available actions are:
build Build the target in the build root (SYMROOT). This is the default action, and is used if no action is given.
build-for-testing Build the target and associated tests in the build root (SYMROOT). This will also produce an xctestrun file in the build root. This requires speci-
fying a scheme.
analyze Build and analyze a target or scheme from the build root (SYMROOT). This requires specifying a scheme.
archive Archive a scheme from the build root (SYMROOT). This requires specifying a scheme.
test Test a scheme from the build root (SYMROOT). This requires specifying a scheme and optionally a destination.
test-without-building Test compiled bundles. If a scheme is provided with -scheme then the command finds bundles in the build root (SRCROOT). If an xctestrun file is
provided with -xctestrun then the command finds bundles at paths specified in the xctestrun file.
installsrc Copy the source of the project to the source root (SRCROOT).
install Build the target and install it into the target's installation directory in the distribution root (DSTROOT).
clean Remove build products and intermediate files from the build root (SYMROOT).

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

xcodebuild far slower than Xcode?

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