The cartFile creates a MyProject.xworkspace.
It seems that this file is not in the same folder as the MyProject.xcodeproj.
Is it a problem ?
Secondly, when I istall the AWS librairies with Carthage, I have to add :
Under the Build Phases tab in your Target, click the + button on the top left and then select New Run Script Phase. Then setup the build phase as follows. Make sure this phase is below the Embed Frameworks phase.
Shell /bin/sh
bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/AWSCore.framework/strip-frameworks.sh"
When I add "import AWSCore" in a source file, I get "No such modue AWSCore". Could it be that the path is wrong ?
Is it possible to get the value of BUILT_PRODUCTS_DIR ?, of FRAMEWORKS_FOLDE_PATH ?
Related
I have this script:
node src/runlink.js
that I'm running with npm run link but I would like to run it when building my code with Xcode.
is there any way to do that ? I tried to do it with the build phase but haven't succeed
You need to run a script in Build Phases.
On the Project Navigator (left column) select your project.
Then on the Targets select your desired target
Clic on Build Phases tab
Click on the + sign to create New Run Script Phase
Type node "${SRCROOT}/../src/runlink.js"
When I build my project with Xcode 8, it saves the final build in ~/Library/Developer/Xcode/DerivedData/MyProject-[add-lots-of-random-chars-here]/Build/Products/Release-iphoneos. Is there any way to make Xcode copy the app bundle to a user-specified path after building it? e.g. how can I make Xcode copy the built app bundle to /MyBuilds after building it?
I know that I can change the path for storing derived data in my project's settings in Xcode but doing so will of course make Xcode store all data (including intermediate stuff like object code etc) in this location which I don't want. I really only want Xcode to copy the final, ready-for-distribution app bundle to a user-specified location without any intermediate files used in the build process.
How can I do that?
The solution using a script in "Build Phases" does not work properly since Xcode is not finished building the app when running the script. Here is a solution with a script that runs after all build tasks are finished:
Go to "Edit Scheme"
Click on the triangle next to "Build"
Select "Post-action"
Press the + button and select "New Run Script Option"
Select your app name in "Provide build settings from"
Add the following shell script:
Script:
PRODUCT="${BUILT_PRODUCTS_DIR}/${TARGET_NAME}.app"
cp -R "${PRODUCT}" ~/Desktop
Add a shell script to your build phases to copy the product:
Script:
PRODUCT="${BUILT_PRODUCTS_DIR}/${TARGET_NAME}.app"
cp -R "${PRODUCT}" ~/Desktop
Certainly replace ~/Desktop with a target directory of your choice.
I'm probably missing something simple here. I am trying to auto increment my build number in XCode 4.4 only when archiving my application (in preparation for a TestFlight deployment). I have a working shell script that runs on the target and successfully updates the info.plist file for each build. My build configuration for archiving is name 'Ad-Hoc'.
Here is the script:
if [ $CONFIGURATION == Ad-Hoc ]; then
echo "Ad-Hoc build. Bumping build#..."
plist=${PROJECT_DIR}/${INFOPLIST_FILE}
buildnum=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${plist}")
if [[ "${buildnum}" == "" ]]; then
echo "No build number in $plist"
exit 2
fi
buildnum=$(expr $buildnum + 1)
/usr/libexec/Plistbuddy -c "Set CFBundleVersion $buildnum" "${plist}"
echo "Bumped build number to $buildnum"
else
echo $CONFIGURATION " build - Not bumping build number."
fi
This script updates the plist file appropriately and is reflected in XCode each time I archive. The problem is that the .ipa file that comes out of the archive process is still showing the previous build number. I have tried the following solutions with no success:
Clean before build
Clean build folder before build
Move Run Script phase to directly after the Target Dependencies step in Build Phases
Adding the script as a Run Script action in my scheme as a pre-action
No matter what I do, when I look at the build log, I see that the info.plist file is being processed as one of the very first steps. It is always prior to my script running and updating the build number, which is, I assume, why the build number is never current in the .ipa file.
Is there a way to force the Run Script phase to run before the info.plist file is processed?
in Xcode 4.4.1 I create new target and add to this target build phase "Run custom script", which update main target Plist. And also, you should add this target to dependencies for main target
The reason that this happens is that by the time your "Run Script" gets run, the XCode build process has already processed the project's plist file to extract the bundle version number, etc.
You can see this (probably in more detail that you want) by going to the Log Navigator in XCode (View/Navigators/Show Log Navigator), and selecting an "Archive" build.
A detailed list of build actions should appear in your main window, and one of the things near the top should be one called Process <projectname>-Info.plist. If you expand this using the icon at the right hand side, you can see the actual build command that was run.
The way that I got around this was to update both the original plist file, and also the processed one. By doing this, you get your updated build version in the current build rather than the next one.
Here's the script that I use to do this (this is Ruby, so you would need to put "/usr/bin/ruby" in the interpreter box to use this, but the concept works the same with a shell script or any other scripting language):
def incrementBundleVersion(file)
oldVersion = `/usr/libexec/Plistbuddy -c "print :CFBundleVersion" #{file}`.strip
components = oldVersion.split('.')
newBuild = components.pop.to_i + 1
version = components.push(newBuild).join('.')
print "Updating version: #{oldVersion} -> #{version} : #{file}\n"
system("/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion #{version}\" #{file}")
end
incrementBundleVersion("#{ENV['PROJECT_DIR']}/#{ENV['INFOPLIST_FILE']}")
incrementBundleVersion("#{ENV['CODESIGNING_FOLDER_PATH']}/Info.plist")
Note that the processed file #{ENV['CODESIGNING_FOLDER_PATH']}/Info.plist is a binary plist file, so you won't be able to process it with simple text tools - using plistbuddy is the easiest way to handle this, and it automatically works with both text and binary plist files.
Mark (et al), I believe I've run into the same problem you are facing, and i will try to describe it in one sentence and then explain:
I think /usr/libexec/PlistBuddy, when run from inside Xcode, works on cached versions of the Info.plist data, and thus what gets finally written for execution on device or simulator is not always what you want.
I had tried writing post Copy Resource Bundle "Run Scripts" in order to change this info in a way that wouldn't cause it to change within my local git repo, only to discover that, whereas the information would work properly when the PlistBuddy commands were executed in a terminal.app window beside Xcode, if not done, the cached values would get written.
I finally resigned myself to running the version-info generation scripts prior to the Copy Bundle Resources phase and just auto-committing the changes in another Run Script, using the same tags for the git message and for the git tag that get auto-created. for the Settings.bundle/Root.plist file, rather than commit this every time, i preferred to just run a finalization script that would perform a 'git checkout -- ${PROJECT}/Resources/Settings.bundle/Root.plist' (which is where mine exists, but may not be where everyone puts their own system settings resource file).
between the checking for changes, running parts of it at install and parts of it every time, and having the finalization scripts at the end, there are 6 scripts for some targets and 7 for another …
… but the important thing to me is that it's finally properly automated … and gets around whatever PlistBuddy is doing to my plist files when processed inside of Xcode.
I have an Xcode project with a large number of targets where I would like to include a settings bundle for apps built under the Ad-hoc and Debug configurations, but not under the Release configuration.
Build Phases don't seem to allow for making themselves conditional on configuration (they can obviously be conditional on target, but doubling the number of targets in the project would make it completely unusable).
That leaves writing a custom Build Rule. My plan is to exclude the Settings.bundle from all targets, and create a build rule that conditionally copies it into the product package, but applicable examples are really hard to find.
The build rule I've started has the Process setting set to "Source files with names matching:" and Settings.bundle as the name. The Using setting is "Custom script:".
My custom script is as follows (with the caveat that my bash scripting is on a cargo cult level):
if [${CONFIGURATION} = 'Debug'] then
cp -r ${INPUT_FILE_PATH} ${DERIVED_FILES_DIR}/.
fi
Finally, I have ${DERIVED_FILES_DIR}/Settings.bundle listed as an output file.
Since I'm here, it should be obvious that it's not working. My first question is whether there is somewhere I can view the output of the build rules as the execute to make sure that 1) it's actually being executed and that 2) I don't have a stupid syntax error somewhere.
Also, what's the proper location (in the form of an environment variable) to copy the output to?
I finally figured it out.
For each target for which you want to conditionally include the settings bundle, choose its Project from the source list, choose the target, and switch to the "Build Phases" tab.
Click the "Add Build Phase" button and choose "Add Run Script".
Then enter the following for the script:
if [ "${CONFIGURATION}" == "Debug" ]; then
cp -r "${PROJECT_DIR}/Settings.bundle" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app"
fi
I know this question has been answered already, and the answer was very helpful to me, but I wanted to throw my own modified solution out there as well.
My requirement was to have different settings bundles for different build configurations, rather than just not including it at release. Assuming a simplistic approach of only Debug and Release configurations, here's how to do it:
Start by adding 2 settings bundles to the project, named Settings-debug.bundle and Settings-release.bundle and then remove these files from the Copy Bundle Resources build phase. Next add a user defined build setting called SETTINGS_BUNDLE, which has different values for each configuration:
Debug ${PROJECT_DIR}/relative/path/to/Settings-debug.bundle
Release ${PROJECT_DIR}/relative/path/to/Settings-release.bundle
Next add a run-script build phase (after Copy Bundle Resources) named Copy Settings Bundle with a modified version of the script in Frank's solution.
cp -r "${SETTINGS_BUNDLE}/" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Settings.bundle"
The difference here is that the copied bundle is always named Settings.bundle regardless of the source name.
You then need to add another build phase script to prevent code signing errors when the only changes are in the settings bundles. It forces the code signing step to occur on every build. This should run before the Compile Source Files build phase. I called mine Force Codesign.
touch "${PROJECT_DIR}/relative/path/to/main.m"
For complied sources, there is a poorly documented user defined build setting that can be added. Files can be both excluded and included from compilation
Go to your target's Build Settings > Tap the + button > Add User-Defined Setting
The key is either INCLUDED_SOURCE_FILE_NAMES or EXCLUDED_SOURCE_FILE_NAMES
The value is a space separated list of file paths
See reference:
http://lists.apple.com/archives/xcode-users/2009/Jun/msg00153.html
(Tested with Xcode 9.3)
I can't find when Xcode included this feature but EXCLUDED_SOURCE_FILE_NAMES is now directly available in Build Settings > Build Options > Excluded Source File Names.
So you no longer need to create a User-Defined Setting.
See below:
It will automatically add this line in your .pbxproj.
Settings.bundle is always copied into destination area no matter whether Release or Debug configuration. So, maybe you need the following code:
if [ ${CONFIGURATION} == "Release" ]; then
rm -rf ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Settings.bundle
fi
I am no shell script expert but I think you need space between the square brackets and the condition. Also, quoting the variables may help:
if [ "${CONFIGURATION}" = "Debug" ] then
cp -r "${INPUT_FILE_PATH}" "${DERIVED_FILES_DIR}"/.
fi
As for the location, I use "$BUILT_PRODUCTS_DIR"/"$FULL_PRODUCT_NAME" for the root of my OS X app bundle.
In Xcode, how can I call a 'shell script' which is a Perl script that copies the .app and .dsym files to a different directory?
I want to pass the name of the project and/or the project's root directory to the script. I want to have the script called every time I build in release and distribution modes but not in debug mode.
For anyone else who is wondering, you can also do a simple copy via
[Click on Scheme Name] -> Edit Scheme... -> [Select Scheme] -> Run "Target" -> Post-actions
and add a cp command. In my case, for quick testing and ease of use, I wanted to copy my binary back to the project directory so that I could process some data files. I used the following:
cp ${TARGET_BUILD_DIR}/${TARGET_NAME} ${PROJECT_DIR}/"binaryFileName"
Right-click on your target and choose Add->New Build Phase->New Run Script Build Phase.
Inside the "Script" text area, add:
if [ ${CONFIGURATION} != "Debug" ]
then
/usr/bin/perl "${PROJECT_DIR}/myperlscript.pl" "${PRODUCT_NAME}" "${PROJECT_DIR}"
fi
Change the location and name of myperlscript.pl to be the location and name of your script.
Make sure to move the Run Script step to be after Link Binary With Libraries, since you're copying the built .app.
(Might also want to add the "perl" tag to the question)
Instead of a script, Xcode 12.4 has an build phase for copying files:
Show the project navigator (blue folder button)
Click on your project (blueprint icon)
Click "Build Phases" header in the opened settings pane
Click the + in the top left of the settings pane
Click "New Copy Files Phase"
Change Destination to Absolute Path and set your path
Click the + at the bottom to add a file to be copied
Save. If you run without saving, your new phase is ignored.
If you don't want an absolute path or one of the destinations provided, you'll have to use a Run Script Phase instead.