Dynamically adding resources to XCode project, always one cycle behind - xcode

I need to assemble resources for an application depeding on XCode build settings. The easiest way to achieve this, is through a build script phase. Although this works, this somehow always builds my target with resources one version lagging (a second build is needed to get things really up-to-date).
The Resources folder is a reference to a folder in which my script (or rather, custom built command line tool called from script) copies the appropriate resources. The run script build phase is the first (topmost) phase in my target.
A solution I've found on the web somewhere, is to create an "External Target" and add that to the original target's build phases (by dragging the External target onto the original target). This does indeed seem to fix the "one version behind" issue, but I cannot seem to get the current target's environment variables to be passed to this "External target".
Why is XCode not including the just updated resources? What other alternatives are there?

You could try to define an internal target (say, "ResourceTarget") and make the main target dependent on ResourceTarget. Then let your script run in the script build phase of ResourceTarget, so the resources are all updated when the second target is build.
That way, environment variables should be the same.

Related

Change build settings prior to project build

I wrote a ruby script that changes some build settings through a .xcconfig file.
(Don't ask me why, but it improves our workflow quite a bit; different environments etc.)
And I put it in the first row (after 'Target Dependencies') in my Build Phases.
The only problem is when I build my app the variables defined in that xcconfig file are not used for that particular build. But for the build that follows.
The only reasonable explanation would be that the project build parameters are already set when the Build Phases start.
So my question is quite simple:
Is it possible to run a script before the project gets build. So I'm talking about pressing ⌘ + R; first my script runs and then fires up the project build.
Stuff I tried:
Using 'pre-actions' in build schemes
Using an 'External Build System' target
Using an 'Aggregate' target
None of them seem to give me the desired result

How to create Target that always runs at the end of a build

I've got a vxcproj with configuration type Driver and am trying to edit the project file to add a custom target that will always run at the end of building the project. I want it to run even if the standard build system detects it doesn't need to build anything.
I'm having a hard time trying to work out where to attach my target. If I attach to AfterBuild or PostBuildEvent, my target won't run if there's nothing to build.
If you're interested, I need this target to run run StampInf and Inf2Cat tasks as the built in versions of those don't suit my purposes. The built in ones always run and dirty outputs, causing knock on rebuilding which I don't want in an incremental build.
Add a project of type General + Makefile. VS cannot optimize the build for these type of projects, the custom Build Command Line setting you specify always runs. You'll typically need to set the project dependencies to ensure it runs last.

Scheme Script vs. Build Phase Script

After I make a build I want to copy some files into my Xcode project.
I discovered that I could do this either in
In "Build Phases" with a custom build step.
I can also execute scripts before and after the different "tasks" in the Scheme editor:
Build (This is where I could add my script)
Run
Test
Profile
Analyze
Archive
I don't completely understand the differences / possible implications between the two approaches and I am wondering when to choose either approach. Thanks for clarification.
After I make a build I want to copy some files into my Xcode project.
I assume you want to copy files to your build product, not the Xcode project.
There are several subtle differences between scheme and build phase scripts. Here are some of them:
Scheme scripts are part of the scheme, so sharing with other developers is more configurable. Build phase scripts on the other hand are part of the target and cannot be skipped simply by choosing another scheme.
Scheme scripts can run before the dependency checking. So you can use them to modify source files and get up to date results. This is not possible with build phase scripts.
The information passed to the script in environment variables differs slightly. Depending on what information you need you sometimes have to choose right kind of script.
Build phase scripts are run conditionally only if the build process succeeds until their place in the target.
Build phase scripts can be configured to only run when input files changed.
There isn't much difference between the two, however you have more control where, in the build sequence, the build phases scripts are run and so this is preferable (for example you could modify files that have already been copied by standard Xcode build phases).
I always use Build Phases scripts myself and have never used Scheme scripts. They are more visible and more manageable.

In an Xcode 4 workspace, how do I cascade build settings & configs to subprojects

Overview
I'm using static libraries and Xcode 4 workspaces to effect modularity in iOS development, an increasingly common technique. For example, I might have a workspace which contains an App project, and a Library project, like so1:
You would then have a scheme to build these that looked something like this:
What I would like to do is have the "App build" control the "Library build" it initiates, in at least a couple of ways:
Map App configurations (e.g. Debug, AdHoc) to arbitrary Library configurations
Passing through some subset of -D defines, and/or specifying these for the library build.
I'll deal with each of these in their own section, but it's worth making a few clarifications.
Clarifications
I'm using App/Library here as an easy proxy for any Superproject/Subproject relationship you may have.
From what I've seen, Xcode 3 style embedded subprojects don't seem to work any differently in Xcode 4 than workspace "peers". I'd love to be wrong about this.
I know I could do almost anything with a "Run Build Script" build phase, and xcodebuild. But I'm trying to work within the system here, where the dependencies are specified in the scheme, and otherwise somewhat loosely coupled.
The Library exists to be used in more than just this project, and so you cannot arbitrarily load it up with junk specific to this App's build, or reference anything particular to the App or Workspace. For the general case, this rules out including static .xcconfig from the App project as a way to convey build information from the App to the Library.
Building the Library outside the workspace sacrifices too much, not an option.
Configuration Mapping
As I understand it, building a particular App configuration will:
If a configuration exists in the Library of the same name, it will build the Library using that.
Otherwise, it will build the active configuration of the Library, as specified in the Library's project file.
To my knowledge, without resorting to the aforementioned run-build-script hack, that is the extent of the control one has over subproject build configurations. Please tell me different.
Ideally, I would be able to specify (in the scheme, presumably):
AppConfigA -> LibConfig1
AppConfigB -> LibConfig2
While Debug, AdHoc, & Release may be the only configurations some ever use, complex projects often outgrow that.
Defines
I've not yet found way to pass -D defines from the App build to the Library, without resorting to xcodebuild, which can take, e.g., an .xcconfig file.
The App's build settings can be accessed in Library build run-build-script phase. However, doing that introduces a dependency in the Library on the App project, which for good reason is verboten (cf. Clarifications). But even then, I haven't found a way to use those settings to directly control the Library's build (much2).
So crazy it just might...
One scheme I came up with while writing this would be:
The Library bases it's build configurations on an empty (dummy) LibraryExternals.xcconfig file within it's own project.
A clean of Library deletes that file. A standalone build of the Library will create an empty one if it does not already exist.
That file is overwritten by an App Build run-build-script phase, and contains anything the app wants to communicate to the Library build.
Seems kind of complicated, but I'm looking for anything right now. I'll push this to an answer if nothing better comes along.
1 Apps shown are Max OS X. I find command line apps make for simpler tests. Same applies.
2 Cf. Info.plist preprocessing, which I learned about during this investigation.
If you modify your project structure to use a single project with multiple targets then each target's build settings will automatically inherit from the project. From there, you can modify ones that you want to be different, or select an individual setting and press the delete key to set it to the default specified by the project.

Specifying a subproject's Configuration in Xcode

I have an Xcode project (A) referencing another project (B). By default (as far as I understand it) Xcode will implicitly build the configuration for the B dependency that matches the configuration of the A's target (e.g., "Debug"). But what if I want, say, A to build as "Debug" and the B to build as "Release"? How would I go about specifying that in Xcode?
I don't know of any easy approach, but you can brute-force it by calling xcodebuild directly for the dependency with a "Run Script" build phase.
I know it was just an example, but if your real goal is that the sub-project be a Release (no symbols) build, then you may have a better experience by just building the sub-project into a library or framework and checking the resulting binary into your version control system. Whenever I have a piece of the system that seldom changes and that I don't want debug symbols for, I go ahead and build it as a static library and check it in. I often go ahead and move the code elsewhere as well (with a README file with the .a that says where the code is and how it was built). This saves time on both build and checkout and is invaluable for large projects in my experience.
This might help: if the configuration of the project A is not found, Xcode will build Release config as a fallback (or maybe the first config of the list).
Then you can "force" the link using this tip: Xcode custom build configuration causes "library/file not found" for static libraries
Yes, this is not naturally supported by Xcode; when you build a target, it builds one configuration of itself and of all dependent targets.
The workaround, as Rob mentioned, is to have a dependent target that's an Aggregate Target type that comprises a single Run Script build phase, which simply invokes xcodebuild -configuration Release (or whatever).
You can specify the default 'fallback' configuration in the project info.
Change from:
Use 'Release' for command-line builds.
to:
Use 'Debug' for command-line builds.
And default will be 'Debug'.
Diffs of project file:

Resources