The 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. ➤ ➤ ➤ ➤ Build Rules ❘ 359 c16.indd 359c16.indd 359 1/21/10 3:56:17 PM1/21/10 3:56:17 PM Download at getcoolebook.com 360 ❘ CHAPTER 16 TARGETS Creating 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 c16.indd 360c16.indd 360 1/21/10 3:56:27 PM1/21/10 3:56:27 PM Download at getcoolebook.com Customizing 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. ➤ ➤ ➤ Build Rules ❘ 361 c16.indd 361c16.indd 361 1/21/10 3:56:34 PM1/21/10 3:56:34 PM Download at getcoolebook.com 362 ❘ CHAPTER 16 TARGETS The 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 c16.indd 362c16.indd 362 1/21/10 3:56:34 PM1/21/10 3:56:34 PM Download at getcoolebook.com prime 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. Build Rules ❘ 363 FIGURE 16 - 15 The project is now fi nished, and should look something like the one in Figure 16 - 16. c16.indd 363c16.indd 363 1/21/10 3:56:35 PM1/21/10 3:56:35 PM Download at getcoolebook.com 364 ❘ CHAPTER 16 TARGETS FIGURE 16 - 16 FIGURE 16 - 17 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 remove a target, select it in the list and click the - button. c16.indd 364c16.indd 364 1/21/10 3:56:35 PM1/21/10 3:56:35 PM Download at getcoolebook.com . Build Rules ❘ 36 3 FIGURE 16 - 15 The project is now fi nished, and should look something like the one in Figure 16 - 16. c16.indd 36 3c16.indd 36 3 1/21/10 3: 56 :35 PM1/21/10 3: 56 :35 PM Download. target is being constructed. ➤ ➤ ➤ Build Rules ❘ 36 1 c16.indd 36 1c16.indd 36 1 1/21/10 3: 56 :34 PM1/21/10 3: 56 :34 PM Download at getcoolebook.com 36 2 ❘ CHAPTER 16 TARGETS The following is a simple. 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