If you want to reuse a script in multiple targets and need a variable list of input or output fi les, defi ne them in a custom build setting.. The compiler phase uses the target ’ s buil
Trang 1The fi les in the Input Files list are not passed to the script as parameters, nor are they piped to it via stdin They are used by Xcode solely to determine if the script should be run It is up to the shell script to read the listed Input Files and produce all of the fi les promised in the Output Files If you want to reuse a script
in multiple targets and need a variable list of input or output fi les, defi ne them in
a custom build setting.
BUILD RULES
Build rules defi ne the transformation of source fi les into their compiled results The compiler phase uses the target ’ s build rules to determine which compiler should be used to compile each source
fi le For example, a build rule might specify that all C source fi les (C, C++, and Objective - C) are compiled using the gcc compiler
A build rule applies to all the fi les of a specifi c type The type of a fi le is determined by its extension
or the fi le type assigned to that source fi le A fi le ’ s type is typically in agreement with the fi lename
extensions, but it doesn ’ t have to be You can change the fi le type of a .java source fi le to sourcecode.cpp The Compile Sources phase will then apply the sourcecode.cpp rule to that fi le
as if it were a C++ source fi le — probably without much success
You ’ ll probably never need to alter the build rules in Xcode However, there are several reasons why you might want to:
Force Xcode to use an older, newer, or custom compiler
Add a rule to compile a source type that is not normally compiled by Xcode
Add a pre - or post - processing script to every compilation
Defi ne your own transformation
You can examine and alter the build rules, previously shown in Figure 16 - 4, for a target in the target ’ s Info window When it comes time to compile an input fi le, the fi le is tested against each rule starting from the top of the list The fi rst rule that matches a particular input fi le is the rule used to compile that fi le
Each target has one set of build rules, shared by all of the build phases in that target You cannot create different rules for different phases of the same target
Every set of build rules includes a set of system rules that cannot be edited The system rules are always at the bottom of the list You can add your own custom rules to a target These custom rules can only be added to the top of the list and are always evaluated before any of the system rules
If you defi ne a rule that matches the same type of fi le as a system rule, your custom rule is used instead Click and drag the title of a custom rule to reorder it in the list
➤
➤
➤
➤
Trang 2Creating Custom Build Rules
To add a new rule, click the + button at
the bottom of the screen A new, undefi ned
rule is created Another way to create a
new rule is to modify one of the system
rules; Xcode balks and warns you that you
cannot edit system rules, as shown in
Figure 16 - 13 Click the Make a Copy
button and Xcode duplicates the system as
a new custom rule, which you are free to alter
Choose the type of fi le that the rule will
process from the Process menu This can
be one of the Xcode fi le types, as set in the
source fi le ’ s properties, or it can be a fi lename
pattern To match a fi lename pattern, choose
the Source Files With Names Matching
option at the bottom of the menu and a
fi lename pattern fi eld appears, as shown in
Figure 16 - 14 Enter the fi lename pattern,
such as *.xml This fi eld is a globbing
pattern like you would use in the shell; it
is not a regular expression The pattern is
case - sensitive By using fi lename patterns,
it is possible to partially override system
rules For example, the “ C source fi les ”
type encompasses C ( .c ), C++ ( .cpp ), and
Objective - C ( .m ) fi les By creating a custom rule that matches only *.c fi les, you can redirect plain C
fi les to an alternate compiler while allowing C++ and Objective - C fi les to “ fall through ” and match
the default system rule for compiling any kind of C fi le
In Xcode 3.0 and 3.1, if you want to use a particular version of the compiler, say gcc 3.3 instead of gcc 4.0, you should create a custom build rule that overrides the system build rule for C fi les In other versions of Xcode the GCC_VERSION build setting selects the desired compiler That setting was deprecated in Xcode 3.0, but is supported again in Xcode 3.2 (with many new choices).
If you choose to redefi ne the C compiler by creating a custom build rule, you must duplicate the rule in every target Currently, there is no means by which you can edit the build rules for the entire project; you must create a new build rule in every target that compiles C source fi les Modify the System C rule to quickly create a custom C rule, and then select the desired compiler.
A less refi ned approach is to use the gcc_select tool to change the default gcc compiler for your entire system This will change the default compiler for every project you build on your system See man gcc_select for details
FIGURE 16 - 13
FIGURE 16 - 14
Trang 3Customizing the Build Rule Compiler
With the fi le type selected, choose the compiler that will process each fi le of this type with the Using menu This can be one of the standard Xcode compilers or you can direct compilations to your own script or tool by choosing the Custom Script item When you choose a custom script as the compiler additional fi elds appear, as previously shown in Figure 16 - 14 The fi rst fi eld is the path and fi lename
of the script to execute The path can be an absolute path or a path relative to the project folder
The With Output Files control lets you specify what fi les are produced when your compiler is executed The naming of output fi les is dynamic and requires build rule variables, described in the next section
Build Rule Variables
When your custom script or tool is executed, the following occurs:
The current directory is set to the project ’ s folder
Environment variables are created that describe the fi le that Xcode wants processed and where Xcode expects the output fi le, or fi les, to be written
The rule ’ s script or tool is executed
Note that no parameters are passed to the script The script must determine what to process
by examining its environment variables If you ’ re using an existing compiler or other tool that expects the input fi le to be in an argument, you will need to write a “ wrapper ” script that extracts the environment values and passes them to your compiler The following table lists the key environment variables passed to a custom build script when it is executed:
ENVIRONMENT VARIABLE DESCRIPTION
INPUT_FILE_PATH The full path, including the fi lename, to the source fi le being
processed
INPUT_FILE_DIR Just the directory portion of INPUT_FILE_PATH , without the
fi lename
INPUT_FILE_NAME Just the fi lename portion of INPUT_FILE_PATH , without the
directory
INPUT_FILE_BASE The base name of the fi le; in other words, the value of INPUT_
FILE_NAME without any fi lename extension
INPUT_FILE_SUFFIX Just the fi lename extension of INPUT_FILE_NAME DERIVED_FILES_DIR The complete path to the directory where Xcode expects the
intermediate fi les to be written Intermediate fi les are kept between builds and used to determine if the source fi le needs to
be compiled again by comparing the modifi cation dates of the two
TARGET_BUILD_DIR The complete path to the target ’ s product directory; in other
words, where the fi nal product of this target is being constructed
➤
➤
➤
Trang 4The following is a simple shell script that demonstrates the use of a custom build rule script In
this example, the project includes XML fi les that defi ne patterns of text The project contains an
SXL transform fi le that converts an XML fi le into a LEX fi le describing the pattern The details
are unimportant The key ingredients are that there is some process that converts the input fi le into
one or more output fi les and the shell ’ s environment variables tell the script where the source and
destinations are
#!/bin/bash
# Xcode compile script
# Run the input file through the java XSLT transformer
# The KeyPatternToLEX.sxlt file contains a transform that
# will convert the pattern record into LEX syntax.
XSLT = "Source/Transforms/KeyPatternToLEX.sxlt"
IN = "$INPUT_FILE_PATH"
OUT = "${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.l"
java org.mycompany.patterns.Transformer "$XSLT" "$IN" > "$OUT"
Writing the Build Rule ’ s Output Files
If the fi les produced by the script go into the target ’ s product, they should be written to the
appropriate location in TARGET_BUILD_DIR
If the script produces intermediate output fi les, it should write those to the DERIVED_FILES_DIR
directory Intermediate output fi les are fi les that will be consumed later in this phase If a compiler
produces one or more intermediate output fi les, Xcode takes those fi les and runs them back through
the build rules It continues this process until no rule matches the fi les This example defi ned a
rule that takes an XML fi le and produces a LEX source fi le When built, Xcode will run the XML
fi le though the custom build script, producing a LEX source fi le That LEX source fi le will be run
through the rules again This time, it will match the LEX rule that will compile the LEX fi le into
a C source fi le That C source fi le is again run through the build rules, this time matching the
System C rule, and ultimately producing an object fi le
This brings up an interesting conundrum Xcode has no idea what a custom build script produces
or where You have to communicate that to the build rule by listing the fi les that the script will
produce Under the With Output Files section in the build rule, enter the fi lename that will be
produced by the script You can use any of the environment variables listed in the previous table
For this example, the output fi le is $(DERIVED_FILES_DIR)/$(INPUT_FILE_BASE).l , which agrees
with the output fi lename in the script The syntax for using environment variables in the output fi les
list is $( VAR_NAME , which may be different than the syntax required by your script ’ s interpreter
If the script produces more than one fi le, say a matched pair of .h and .c fi les, add more fi les by
clicking the + button immediately below the list
A Build Rule Example
Assume a hypothetical application, called PrimeRules, that needs a precompiled table of prime
numbers You ’ ve already written a shell script that generates the C source code for a table of
Trang 5prime numbers between 2 and some arbitrary limit Now you could run that script manually, capture the output, save it as a fi le, and add that to the project If the maximum number ever changed, you ’ d have to repeat the process The solution is awkward, and the generated C table could (potentially) be huge
What you ’ d like is simply to set the maximum prime number somewhere in the project and have the build automatically generate the table of primes, compile it, and link the results into your application One solution is to use a custom build rule:
1. Start with a Command Line project that produces a BSD executable
2. Add the compilePrimeTables.sh shell script to your project (Not strictly necessary, but you ’ d want to check it into source control and make it obvious that it ’ s part of the project.) The script should not be included in any targets
3. Add a new build rule to the PrimeRules target, as shown in Figure 16 - 15 The rule takes
*.primetable fi les and uses the compilePrimeTables.sh script to transform them into
C source fi les
4. Create a new knownprimes.primetable fi le and add it to the project Edit the fi le; it should contain nothing except a single number
5. Add the knownprimes.primetable fi le to the PrimeRules target by dragging it into the target ’ s Compile Sources build phase
FIGURE 16 - 15
The project is now fi nished, and should look something like the one in Figure 16 - 16
Trang 6FIGURE 16 - 16
When the PrimeRules target is built, the Compile Sources phase runs each of its source items
through the build rules for the target The main.c fi le gets compiled as you would expect Because
of your custom build rule, the knownprimes.primetable fi le runs the compilePrimeTables.sh
script, which produces an intermediate .c fi le The intermediate fi le is run back through the rules
again, and is eventually compiled by the C compiler
The two fi nal object fi les, main and knownprimes , are linked together to form the fi nished executable
DEPENDENCIES
A target dependency ensures that the targets required by the current target are built fi rst Basic targets
produce a product from one, or possibly thousands, of source fi les These are the atoms from which
you assemble your project ’ s fi nished product When the product of one target is a source fi le in another
target, it creates a dependency; you communicate that relationship to Xcode using target dependencies
You must defi ne your target dependencies; Xcode can ’ t do it automatically You create dependencies
to guarantee that source items produced by other targets are up - to - date before proceeding, as well
as to order and group targets A target can depend on another target in the same project or in a
different project
Adding Target Dependencies
To add a dependency to a target, open the
target ’ s Info window The General tab contains
the Direct Dependencies list Drag a target,
or targets, from the project ’ s Groups & Files
list into the list Or, you can click the + button
just below the list and Xcode presents a list
of targets from which to choose, as shown in
Figure 16 - 17 Select one or more targets from
the list and click the Add Target button To