PList Compiler is a property list compiler for XCode. It is developed as an Open Source project coming with a BSD License. The source code is currently hosted and developed on the SourceForge site.

This file documents version 0.2b1 of PList Compiler.


Introduction

PList Compiler is a property list compiler for XCode. It lets you build localized and non-localized plist files from plc and ploc source files. These are the property list files found in packages applications, bundles, frameworks, plugins, etc.

It is modelled on the CodeWarrior property list language: the idea of preparing source files and compiling them during the build process was introduced in CodeWarrior Pro 8. The language used in these source files lets you have the compiler build the property list files for you automatically, substituting the right values during the building process, instead of having to manage manually hard-coded XML files. CodeWarrior Pro 8 introduced a first draft of the plc language together with a dedicated compiler written by Josef W. Wankerl. Unfortunately XCode does not offer such a handy tool. Here comes PList Compiler!

It is a shell script, named plcompile, which is meant to be executed during a Shell Script Build Phase within an XCode project. It can also be run directly as a command line tool if you need to work only with plc files independently from the rest of your project.

PList Compiler uses the same syntax as the original CodeWarrior compiler it supports most of its functionalities and adds many more to take advantage of all the XCode settings.

PList Compiler is written in fact in Tcl (the Tool Command Language): the executable script is a bash script called plcompile which magically redirects the instructions to tclsh which is the Tcl shell. Tcl is installed by default on OSX since version 10.3 (aka Panther) so tclsh is normally present on every MacOSX system starting from this version, and there should be nothing special to do for this script to run there. For version 10.2 systems (aka Jaguar), you will have to install Tcl on your machine: you can, for instance, get Daniel Steffen's Tcl Batteries Included distribution from there.

PList Compiler comes with the same BSD license as Tcl itself. See the file License_terms included in this distribution or the Open Source Initiative (OSI) site.

Usage

The syntax of the plcompile shell script is:

    plcompile options plcFile
    plcompile (-help | -encoding | -version)

The first form executes the compilation of the plc source file plcFile. Traditionnally these files have a .plc extension but this is not required at all. Most of the time you will not have to worry about the options. PList Compiler comes with reasonable defaults for the optional values, corresponding to a normal usage of these files in a project. The available options are explained below.

In the second form

	plcompile -help
	plcompile -encoding
	plcompile -version
the script prints some help in the console window: with -help, you get the usage string and a reminder of the defaults; with -encoding, you get a list of the available encodings; with -version, you get the current version number of the script. Note that one can use abbreviated flags like -h or -v for instance.

Default behavior

By default, plcompile assumes that the input files are encoded in MacRoman and have Mac line endings (cr). The same type of line endings is used to write the output files but the encoding, this time, is the Unicode utf-8 form.

The default destination folder depends on how you execute the compiler:

These are default behaviors which can be modified with options on the command line or pragmas in the source files. See the Location of the output files section below.

Command line options

The complete syntax to run the compiler is:

    plcompile [-input_encoding enc] [-output_encoding enc] [-input_eol eol] 
                    [-output_eol eol] [-dest folder] [-plist version] [-pkginfo] plcFile

The options have the following meaning:

Note: the -pkginfo option has been introduced in version 0.2 of PList Compiler by Franz Detro (thanks).

Howto

Using PList Compiler in an XCode project

The idea is to generate the various plist files and localized strings files during a Shell Script Build Phase within your XCode project. XCode lets you define Shell Script Build Phases: they are shell scripts which can be executed at any stage of the building process.

So, in order to use PList Compiler from XCode, you would normally create, in all the targets for which you want plist files to be generated, a build phase which could take place at the end of the build process. To create a Shell Script Build Phase, select the target you want in the Groups and Files panel of your main project window and select the Shell Script Build Phase command in the New Build Phase submenu of the Project menu. If you open the disclosure triangle located in front of the target's name, you will see your new shell phase (in XCode 2.1, it is called Run Script). Select it and click on the Info button in the toolbar (or select Get Info in the File menu).

XCode displays a window in which you can enter shell commands to execute. If your plc file is named MyApp.plc, you should just have to enter a command like

    plcompile /path/to/MyApp.plc
The only point is to make sure that the shell (Bash shell) can find the plcompile script. This depends on where you have put this script on your machine. If it is in one of the folders of your shell PATH variable, there should be no problem. Otherwise you can specify the complete path of the script, like for instance:
        /Users/bernardo/Devel/Tools/plcompile   /path/to/MyApp.plc
or alternatively change the directory to this directory and execute the script there, like this:
        cd /Users/bernardo/Devel/Tools
        ./plcompile  /path/to/MyApp.plc
supposing, in the previous example, that plcompile resides in /Users/bernardo/Devel/Tools.

Using PList Compiler in Terminal

The plcompile script can be used directly from the command line (in a Terminal window). There is only one caveat with this approach: only the environment variables defined in the current shell window are available. This means that you must make sure, if ever your plc file makes use of environment variables defined by XCode, that they are available in the shell. You could have to define them manually. If your plc file does not need any of the values set by XCode, then you should normally be able to compile your plc files directly. You will probably want, in that case, to specify a destination folder using the -dest command line option.

For instance:

    /Developer/Tools/plcompile -dest ~/Devel/Tests myfile.plc

Troubleshooting

In case the instructions above do not work as expected, here are a few indications to help solving the problem. Make sure that the plcompile script has been saved with Unix line endings (lf) rather than Mac line endings (cr). Some editors tend to change them in your back and the shell expects Unix line endings.

Make sure there is not an already existing Info.plist file in your source files added to your built product during the Copy Bundle Resources phase in order to avoid conflicts or files being overwritten.

Make sure, in the target settings, that no file has been declared in the Info.plist File setting (look in the Packaging section of the General settings).

Make sure of course that Tcl is installed on your machine. It is part of the Panther and Tiger installation.

If you are having trouble with the encodings, it is maybe because the text editor you used to create the .plc source files saved your files in utf-8. If your source file is utf-8 encoded, you will have to tell plcompile and specify the -input_encoding option, like this:

    ./plcompile -input_encoding utf-8 /path/to/MyApp.plc
Once again, the default is to read the source files in macRoman and to write the output files in utf-8.

Make sure you used the proper casing to specify the encodings: it is macRoman and not MacRoman, utf-8 and not UTF-8. If you have a doubt, execute the following command which returns the list of all the available encodings:

    plcompile -encoding

If the script is not found by the shell, read the informations in the section above about executing shell phases in XCode and setting the access paths correctly.

Anatomy of 'plc' files

The .plc source files are regular text files taken as input by PList Compiler in order to produce one or several output files. They contain three types of commands:

Comments

PList Compiler recognizes two kinds of comments: the C-like comments enclosed between /* and */ which can span multiple lines, and, on a single line, portions of text starting with a double slash (//) up to the end of the line. Be careful with the latter because, as of this version, the compiler is not clever enough to detect comment symbols included in a quoted string and which you would not like to be considered as a comment.

The plc commands

Most of these commands correspond to an XML entity in the output Info.plist file. An Info.plist file is an XML document. The format of the plist files is specified by Apple in a DTD which can be found in /System/Library/DTDs/PropertyList.dtd. For a detailed description of property lists files, see for instance Introduction to Property Lists

All the commands must be kept on a separate line (but not necessarily at the beginning of the line).

The 'plist' command

The first command found in a .plc file designed to generate a .plist file is always the plist command. Its argument is a block enclosed inside a pair of curly braces. A minimal property list file, describing a completely empty property list, would look like this:

    plist {}

The plist command corresponds to the <plist> XML tag.

The 'dictionary' command

Directly inside the plist block, there is usually a dictionary command. This is not required by the DTD but all property lists in use are structured like this. Like with the plist command, the argument of a dictionary command is a block enclosed inside a pair of curly braces. So, a minimal valid plc source file would be:

    plist
    {
        dictionary {}
    }

The dictionary command corresponds to the <dict> XML tag.

The dictionary is made up of key/value pairs. The key names must be unique within a single dictionary. The value of a key can have any of the following types: array, boolean, data, date, dictionary, number, or string.

The 'key' command

The key/value pairs are declared by instructions in the following format

    key "name_of_the_key" value "type_of_value" "the_value"

In this instruction, the key and value keywords correspond to the <key> and <value> XML tags respectively.

For instance, here is a valid key statement in a dictionary block:

    key "Victor Hugo" value string "Writer"

The 'array' command

The array command is used to describe an ordered list of property list elements. These elements can be of any of the abovementioned types (array, boolean, data, date, dictionary, number, string).

The original specification of the plc syntax in CodeWarrior stipulated that the argument of an array command is a block enclosed inside a pair of square brackets. With PList Compiler, you can also use curly braces instead of square brackets.

Here is an example of an array containing a dictionary and a boolean value:

    array
    {
        boolean true
        dictionary {
            key "Victor Hugo" value string "Writer"
            key "Ludwig van Beethoven" value string "Composer"
        }
    }

The 'string' command

The string command lets you specify a string value. Strings are enclosed in double quotes in order to distinguish them from a substitutable variable (see below), but this is not required. If there is no risk of ambiguity, you can suppress the quotes. Still it is good programming practice to write them.

The value of a string can be made up of several pieces, mixing quoted strings or variables. For instance:

    string "copyright (c) " __YEAR__ ", all rights reserved" 
where __YEAR__ is one of the predefined variables set by the compiler. This string will be expanded to something like copyright (c) 2005, all rights reserved. The string command corresponds to the <string> XML tag.

Caveat: in order to ensure a better compatibility with the CodeWarrior property list compiler which accepted both single and double quotes to delimit strings, PList Compiler does its best to support the same convention. For instance:

	string 'RSRC'
will produce <string>RSRC</string> as it did with the CodeWarrior property list compiler. As a consequence, this makes it a little more difficult to obtain values enclosed in quotes in the output file. For instance, if you really want to get a string value like 'RSRC' or "RSRC" (including the quotes), you will have to code it like this:
	string "'RSRC'"
	string "\"" RSRC "\""
Be also aware that, in the case where you concatenate several strings or mix strings and variables, single quotes will confuse the compiler and the odds are very high that you won't obtain what you expect, so your best bet is to always use double quotes (and no quotes at all for substitutable variables).

The 'number' command

The number command lets you specify numeric values. There is no XML tag named number in a plist file, but rather two entities named <real> and <integer> corresponding respectively to integer or floating point values. The number command corresponds to both of them: the compiler automatically decides to which type the value belongs. For instance, the following declarations will result in an <integer> tag:

    number 0
    number 1
    number -1
while the following ones will yield <real> tags:
    number 0.0
    number 3.14
    number -2.718
    number .1
    number -.1
    number 6.09e23

The 'date' command

The date command lets you specify a date value. The plist format specification (in /System/Library/DTDs/PropertyList.dtd) suggests that

the contents of a date value should conform to a subset of ISO 8601: in particular, YYYY '-' MM '-' DD 'T' HH ':' MM ':' SS 'Z'. Smaller units may be omitted with a loss of precision.

For instance:

    date "2005-09-15 18:06:03"
    date "2005-09-15T18:06:03Z"
    date __DATE__
where __DATE__ is one of the predefined variables set by the compiler. The date command corresponds to the <date> XML tag.

The 'data' command

The data command is used to store raw binary data. The value of a data type is expressed in the plc file in hexadecimal format, possibly with space characters, like for instance:

    data "64656667"
    data "64 65 66 67"
    data "64 65"  "66 67"
In the output file, the same data is represented in Base64 encoding as recommended in the DTD specifying the plist format (see /System/Library/DTDs/PropertyList.dtd). All the values above are equivalent and are represented like this in Base64 encoding:

<data>ZGVmZw==</data>

The data command corresponds to the <data> XML tag.

Note: the CodeWarrior plist compiler also defined a data file command followed by the name of a file containing raw data. This is not implemented by PList Compiler as of version 0.1.

The 'boolean' command

The boolean command lets you specify a boolean value using any of the usual keywords: true/false, yes/no, and 1/0. Casing does not matter, so TRUE, true or True are all acceptable values. The value can be enclosed in double quotes but this is not required.

For example:

    key "kGcc_Precompile_Prefix_Header" value boolean 1
    key "kGcc_Symbols_Private_Extern" value boolean 0
    key "kGenerate_Profiling_Code" value boolean Yes
    key "kUse_Dynamic_No_Pic" value boolean "false"
    key "kZero_Link" value string __ZERO_LINK__

The last example is correct because XCode defines a ZERO_LINK variable whose value can be either "YES" or "NO" (see below).

The boolean command corresponds to the <boolean> XML tag.

Localized files

The localized files contain lists of keyed strings localized for a particular language.

The 'localize' command

The localize command is used to create and generate localized strings files. It is a top level command like the plist command. There are two possible syntaxes to invoke this command:

    localize "language"
    localize "language" as "localized_file_name"

The first form is used to localize string values present in the main property list dictionary of the plist command. The resulting file is named by default InfoPlist.strings instead of Info.plist, and is located inside the localized folder corresponding to the specified language instead of the Contents folder. For instance:

    /Contents/Resources/Spanish.lproj/InfoPlist.strings

The second form of the localize command specifies the name of the generated file rather than relying on the default name. This allows to create several separate strings files. These files will also be created in the folder corresponding to the specified language.

The argument of the localize command is a block enclosed in a pair of curly braces. Only two commands can be used inside a localize block: key and comment. The key command defines key/value statements of type string. For instance:

    localize "French"
    {
        key "CFBundleGetInfoString" value string "MyApp, (c) 2005, tous droits réservés"
        key "CFBundleHelpBookName" value string "Aide PList Compiler"
    }
    
    localize "Spanish" as "Dialogs.strings"
    {
        key "Number of Recent Items:" value string "Número de ítems recientes:"
        key "General Preference Pane" value string "Panel de preferencias General"
    }
The first instruction generates MyApp.app/Contents/Resources/French.lproj/InfoPlist.strings and the scond one MyApp.app/Contents/Resources/Spanish.lproj/Dialogs.strings

It is current practice to put the localize blocks in separate files and use a .ploc extension in their name to distinguish them from the .plc files. The .ploc files are usually invoked from the main .plc file with an #include preprocessor command. For instance:

    #include "DialogStrings_Spanish.ploc"

The 'comment' command

The comment command lets you insert comments inside the localized strings files. There can be as many commands of this type in a localize block as necessary. The value of the command is a string or concatenation of strings and expandable variables: once concatenated and substituted, it is inserted inside a C-like comment of the form /* */ in the output file. For instance, the following instruction might be found in some .ploc file:

    localize "English" as "Dialogs.strings"
    {
        comment "Generated from " __FILE__ " at " __TIME__
    }

The __FILE__ and the __TIME__ symbols used in this example are predefined variables: __FILE__ always contains the name of the file being currently processed by the compiler and __TIME__ the time at the moment the compiler processes the file. If the instruction above was stored in a file named dialogStrings_EN.ploc, the comment generated in the resulting Dialogs.strings file (in the /Contents/Resources/English.lproj folder inside the bundle) would look like this:

    /* Generated from dialogStrings_EN.ploc at 23:54:25 */

Caveat: the comment command can't be used in a plist block.

Location of the output files

By default, the plist command causes PList Compiler to create a file named Info.plist inside the destination directory. In the case of a packaged application, the default destination directory is the Contents folder inside the bundle. More generally, the path of this destination folder is built by PList Compiler using the values of the BUILT_PRODUCTS_DIR and INFOPLIST_PATH XCode variables.

For instance, with XCode 2.1, if your target is in the Release configuration and your application is MyApp, the destination folder would be (unless you have non standard settings):

    $SRCROOT/build/Release/MyApp.app/Contents 
where SRCROOT is, as usual the folder containing your project file.

By default, the localize command causes PList Compiler to create localized files. The default location for these files depends on the language used for the localization. In the case of a packaged application, the default destination is inside one of the /Contents/Resources/<language>.lproj subfolders of the bundle. For instance /Contents/Resources/English.lproj or /Contents/Resources/French.lproj.

There are two ways of modifying the destination folders:

The output file name (usually Info.plist) can be modified using the output_filename pragma. See the Pragmas section below.

Preprocessor directives

This is the other type of instruction found in plc source files. They are called preprocessor directives by analogy with the C/C++ language. They are also sometimes refered to as preprocessor macros. The preprocessor term is not quite accurate here because there are not two phases like with the ordinary C compilers (a preprocessing phase and a compiling phase): PList Compiler parses the file once, line by line.

The following macros are supported by PList Compiler:

#define #message#if #elif
#include#warning#ifdef #else
#pragma #error #ifndef#endif

Preprocessor directives all occur on their own line. They are characterized by the fact that the first non-whitespace character on the line is a #. There may be whitespace characters between the # mark and the name of the directive too.

Defines

The #define directive lets you define a macro in the property list compiler. The format is:
    #define macro_name macro_text

The compiler adds the macro macro_name to its macro table: if there is already a macro with this name, it emits an error. When macro_name appears in a plc source file as the value of a string type not enclosed between double quotes, it is automatically replaced by macro_text.

For instance, if a macro kVersionNumber is defined like this:

    #define kVersionNumber "1.2.3"
then, when the compiler encounters the following instruction:
    key "CFBundleShortVersionString" value string "kVersionNumber: " kVersionNumber
it expands it to kVersionNumber: 1.2.3

The #undef directive tells the compiler to remove an already existing macro from its macro table. The syntax is:

    #undef macro_name
If macro_name does not exist, the directive is just ignored.

Note: the same remarks as with the string keyword apply here concerning the use of single quotes as string delimiters. They are supported in the case of simple string values but not in concatenations. Use double quotes to be safe.

Includes

The #include directive tells the plist compiler to find another plc source file and start processing it. The syntax of this directive has two forms:

#include "filename"

#include <filename>

The filename value designates a file to include: it can be either an absolute or a relative path. A relative path is resolved by searching relatively to various folders: in the first form, PList Compiler will first try to resolve the path relatively to the folder containing the parent source file (i-e, the file which invokes the #include directive). If this fails, it will try all the paths defined in XCode's HEADER_SEARCH_PATHS variable. In the second form, where the filename is enclosed in angle brackets, only the paths defined in the HEADER_SEARCH_PATHS variable are searched.

The following are all valid examples (the double quotes are necessary only if the filename contains space characters):

    #include /Users/bernardo/Devel/MyApp/Rsrc/OtherFile.plc
    #include OtherFile.plc
    #include "LocFiles/My Strings_EN.ploc"
    #include "../Rsrc/My Strings_EN.ploc"

Note: the second form of the #include directive is a code contribution by Franz Detro (thanks) and has been introduced in version 0.2 of PList Compiler.

Conditional macros

PList Compiler supports the following six conditional directives: #if, #ifdef, #ifndef, #elif, #else, #endif which let you build conditional blocks of instructions depending on the value of a test expression or on the existence or non-existence of a particular variable.

The #ifdef directive tests for the definition of a compiler macro, while the #ifndef directive tests for the non-definition of this macro. Their behavior is the opposite of one another. In the case of #ifdef for instance, if the macro has been previously defined, the property list code immediately following the #ifdef directive is processed until an #else or #endif directive is encountered, but on the contrary, if the macro has not been defined, the property list code immediately following the #ifdef directive is not processed. In that case, if there is an #else directive, instead the code following this #else is processed until the matching #endif directive is found.

Similarly, if the expression in an #if directive evaluates to 1, the instructions immediately following the #if directive are executed until an #else, #elif, or #endif directive is encountered. If the expression evaluates to 0, the property list code immediately following the #if directive is not processed.

Each #if, #ifdef, #ifndef directive must be matched by an #endif directive.

The #elif directive allows for multiple successive #if tests during the preprocessing stage. An #elif test is evaluated only if all the preceding tests have failed.

Here are a few examples of conditional constructs.

Example 1

Note in this example that for testing equality you must use a double equal sign (==). A single equal sign would provoke an error.
    #define kVersionFive 5
    #define kVersionSeven 7
    #define kCurrentVersion kVersionFive
    
    #if kCurrentVersion == kVersionSeven 
        #warning "Current version is " kVersionSeven
    #else
        #warning "Current version is not " kVersionSeven    
    #endif

Example 2

This example demonstrates nested conditional blocks.
    #define kVersionFive 5
    #define kVersionSix 6
    #define kVersionSeven 7
    #define kCurrentVersion kVersionSeven
    
    #if kCurrentVersion == kVersionSeven 
        #warning "Current version is " kVersionSeven
    #else
        #if kCurrentVersion <= kVersionFive 
            #warning "Current version <= " kVersionFive
        #else
            #warning "Current version > " kVersionFive
        #endif
        #warning "Done comparison with kVersionFive"
    #endif

Example 3

Here is an example using #ifdef and #ifndef directives:
    #undef kUndefinedMacro
    #ifdef kUndefinedMacro
    #    define kWillNeverBeDefinedMacro
    #endif
    
    #ifndef kWillNeverBeDefinedMacro
    #    define kHasNotBeenDefined "No, it has not been defined"
    #else
    #    define kHasBeenDefined "Yes, it has been defined"
    #endif

Example 4

Here is an example using the #elif directive:
    #define kVersionFive 5
    #define kVersionSix 6
    #define kVersionSeven 7
    #define kVersionEight 8
    #define kCurrentVersion kVersionSix
    #if kCurrentVersion <= kVersionFive 
    #warning "Current version is <= " kVersionFive
    #elif kCurrentVersion <= kVersionEight 
        #if kCurrentVersion == kVersionSix
            #warning "Current version is " kVersionSix
        #elif kCurrentVersion == kVersionSeven 
            #if kCurrentVersion < 0
                #warning "Current version is negative!"
            #elif kCurrentVersion > 10
                #warning "Current version is > 10"
            #else
                #warning "Current version is between 1 and 10"
            #endif
        #else
            #warning "Current version is " kVersionEight
        #endif
    #else
    #warning "Current version is > " kVersionEight
    #endif

Errors and warnings

The #error directive raises an error and stops the execution of the compiler. This is generally used in combination with #if directives to test for situations that should never occur.

The #warning directive emits a message in the console. The #message directive is just a synonym for #warning.

Here are a few examples:

    #warning "Fix the version number before shipping"
    #message "PList Compiler is great!!!"
    #if __PLIST__ < 1.0
       #error "The property list version is too old"
    #endif

Pragmas

Pragmas are directives used to modify the internal state of the compiler. They let you modify some internal settings during the execution of the plc file. They are most useful to modify locally a global setting: the new value set by a pragma holds until another pragma modifies it again. A pragma is declared with the #pragma directive. The syntax is:

    #pragma pragma_name [pragma_value]

The supported pragmas are explained below. The pragma_name argument can be one of the following keywords: output_filename, in_package_directory, localize_directory, output_eol, output_encoding, plist_version.

Any other pragma encountered will be simply ignored by PList Compiler. In particular the once, notonce, and mark pragmas, defined by the CodeWarrior compiler, are not supported, as of version 0.1.

Caution: a pragma cannot be used inside a plist or a localize block. It must be invoked outside these environments. This is because the internal settings they affect can't be modified once a file has been opened for output. The compiler will emit an error if such a situation occurs.

The 'output_filename' pragma

The output_filename pragma lets you override the default name of the current output file. Its value is a string which is the new name. For instance:
    #pragma output_filename "OtherName.plist"

The new name given with this pragma is used only once and then forgotten, so that the compiler immediately returns to the default naming convention. Note that this does not affect the filename defined in a 'localize as' command. More precisely, if the compiler reads the following inxtructions:

    #pragma output_filename "OtherName.txt"
    localize "Spanish" as "Error.strings"
    {
    }
the pragma will have no effect and the output file will still be named Error.strings. On the other hand, the pragma will remain in effect until it can be applied.

The 'in_package_directory' pragma

The in_package_directory pragma lets you specify where to place the property list file inside the destination folder. It is a string which specifies a directory relative to the destination folder. For instance, if you write:
    #pragma in_package_directory "Infos"
the Info.plist file will be written in an Infos subfolder of the destination folder rather than in the destination folder directly. If the subfolder does not exist, it is created. By default, this will be MyApp.app/Contents/Infos (unless another destination folder has been otherwise specified).

Another valid value for this pragma could be:

    #pragma in_package_directory "../Infos/Properties"
which would write the output file in MyApp.app/Infos/Properties, i-e with the Infos directory at the same level as the Contents directory.

The 'localize_directory' pragma

While the previous pragma affected the final location of the Info.plist files (produced by the plist command), the localize_directory pragma lets you specify where to place the localized strings files produced by the localize command. It is a string which specifies a directory relative to the destination folder. By default, it is the Resources folder inside the destination folder which itself is, by default, the Contents subfolder of the bundle. For instance:
    #pragma localize_directory "Local/Strings/"
will cause the localized strings files to be written in some MyApp.app/Contents/Local/Strings/<language>.lproj folder (depending on the chosen language) instead of MyApp.app/Contents/Resources/<language>.lproj.

The 'output_eol' pragma

The output_eol pragma lets you specify another type of line endings for the output files. The possible values are cr for Mac, lf for Unix and crlf for Windows. This pragma is useful to override a setting made with the -output_eol option on the command line of the plcompile shell script.
    #pragma output_eol lf

The 'output_encoding' pragma

The output_eol pragma lets you specify another encoding for the output files. The possible values are listed when you execute the command:
    plcompile -help

You would normally be interested only in the utf-8 and utf-16 encoding forms which are the only encodings recognized for property list files. PList Compiler is able though to handle all the other encodings.

This pragma is useful to override a setting made with the -output_encoding option on the command line of the plcompile shell script. For instance:

    #pragma output_encoding utf-16

Note that there is no equivalent pragma concerning the input encoding because it does not make sense: the input file would have already been read when the pragma is encountered.

The 'plist_version' pragma

The plist_version pragma lets you specify another version of the property list format. The possible values currently are 0.9 and 1.0. This is the value written in the version attribute of the <plist> tag in the .plist files. For instance:
    #pragma plist_version 0_9
yields <plist version="0_9">

This is the same value stored in the __PLIST__ predefined variable (see below).

Substitutable variables

Substitutable variables are variables whose value is inserted when the script is run. These variables can be defined with a #define preprocessor macro or in the shell environment. There are also some useful predefined variables set by the plc compiler itself.

To invoke a variable defined in the shell environment, you must surround it with double underscores. This concerns in particular all the variables available in an XCode project, but not only: ordinary shell environment variables, such as USER, DISPLAY, SHELL, etc. are also accessible as __USER__, __DISPLAY__, __SHELL__, respectively.

Variables defined with a #define macro can be invoked directly (without the double underscores). For instance, if you define

    #define kBundleShortVersion "1.2.3"
you can then have a key in the plist dictionary declared like this
    key "CFBundleVersion" value string kBundleShortVersion

For variables which can be set at different levels, the order of precedence is the following: an option set by a #define directive or modified by a #pragma directive in the plc source file overrides any option set on the command line which, in turn, overrides an option set by a shell environment variable.

Predefined variables

A few predefined variables are set each time the plcompile script is run.

The five following variables existed in the CodeWarrior property list compiler. They are still available with PList Compiler in order to ensure some compatibility with already existing plc files (and because they are very useful!):

__FILE__
This variable always contains the name of the file currently processed. If another file is included with an #include preprocessor macro, the value of the variable is changed accordingly so that it always designates the file being processed.

__OUTPUT_CREATOR__
This variable contains the creator type of the built product. It corresponds to the MACOS_CREATOR XCode variable.

__OUTPUT_TYPE__
This variable contains the file type of the built product. It corresponds to the MACOS_TYPE XCode variable.

__OUTPUT_FILENAME__
This variable contains the name of the built product. It is equivalent to the concatenation of the PRODUCT_NAME and WRAPPER_EXTENSION XCode variables.

__DATE__
This is the complete date at the moment where the script is executed. It is returned in the format specified by the ISO 8601 standard: YY-MM-DDTHH:MM:SSZ. For instance "2005-10-04T17:12:23Z".

Caveat: one must be aware that the values of the OUTPUT_CREATOR and OUTPUT_TYPE predefined variables are taken from the XCode variables called MACOS_CREATOR and MACOS_TYPE, but that, in certain circumstances, these variables are not displayed in the Target Settings panels in XCode. The variables do exist but simply are not displayed by default. As a consequence, their value in that case is empty. This is a problem with XCode, not with PList Compiler. The remedy, should this situation occur, is to add these variables manually in the Target Settings using the Plus button and to give them the necessary values corresponding to your project.

Furthermore PList Compiler introduces other useful predefined variables:

__YEAR__
The current year (four digits)

__MONTH__
The current month number (01 - 12)

__MONTHNAME__
The full month name (January, etc.)

__DAY__
The current day of month (01 - 31)

__DAYNAME__
The full day name (Monday, etc.)

__SHORTDATE__
The current date as YYYY-MM-DD.

__TIME__
The current time as HH:MM::SS.

__HOURS__
The hours part of the TIME string.

__MINUTES__
The minutes part of the TIME string.

__SECONDS__
The seconds part of the TIME string.

For instance:

    __DATE__      = 2005-10-04T15:54:36Z
    __SHORTDATE__ = 2005-10-04
    __YEAR__      = 2005
    __MONTH__     = 10
    __MONTHNAME__ = October
    __DAY__       = 04
    __DAYNAME__   = Tuesday
    __TIME__      = 15:54:36
    __HOURS__     = 15
    __MINUTES__   = 54
    __SECONDS__   = 36

XCode environment variables

All the environment variables set by an XCode project are accessible with PList Compiler. See the XCode documentation for a complete list. The syntax is the same as for the predefined variables: the name of the environment variable must be surrounded by double underscores. For instance, if you want to invoke the value of the INFOPLIST_PATH variable defined in an XCode project, you would write it as __INFOPLIST_PATH__ in the plc file. For instance

    key "InfoPlistPath" value string __INFOPLIST_PATH__

Some of these variables are set by XCode itself (they are generally meant to be read-only variables) while the others can be set in the info window or a particular target. The name of a variable corresponding to a particular setting is always indicated by XCode between parentheses in the help text displayed when you select this setting in a Target Info window.

Unsupported variables

A few predefined variables available in the CodeWarrior property list compiler are not supported by PList Compiler. This is mainly because they are specific to the CodeWarrior IDE and have no meaning with XCode. Here is the list of these variables:

    __APPLEMACHLINKER__, __MACH__, __MERGELINKER__, 
    __MWMACHLINKER__, __MWPEFLINKER__

The __LINE__ variable is not supported either, as well as the __IDE_TARGET__() and __STRING__() pseudo-macros.

Unicode characters

By default, PList Compiler assumes that the input file is UTF-8 encoded and it generates its output files in the same encoding. So there is no problem for supporting any Unicode character in your plc source files: you just have to use a text editor which handles the UTF-8 encoding form. If you prefer editing your plc source files in macRoman, all you have to do is to specify this to the plcompile script using the -input_encoding option.

Alternatively, if you just need occasionnally to use Unicode characters, you can also embed them in strings using the \u escape sequence: each Unicode character can be designated using the sequence \u followed by the code-point of the character in hexadecimal. For instance, the Unicode code-points for the lowercase letters of the greek alphabet start at 03B1:

Code-pointLetter
03B1GREEK SMALL LETTER ALPHA
03B2GREEK SMALL LETTER BETA
03B3GREEK SMALL LETTER GAMMA
03B4GREEK SMALL LETTER DELTA
03B5GREEK SMALL LETTER EPSILON
03B6GREEK SMALL LETTER ZETA
03B7GREEK SMALL LETTER ETA
03B8GREEK SMALL LETTER THETA
03B9GREEK SMALL LETTER IOTA

A string defined like this
    	key "UniString1" value string "\u03B1 \u03B2 \u03B3 \u03B4 \u03B5 \u03B6 \u03B7 \u03B8 \u03B9"
will produce:

α β γ δ ε ζ η θ ι

Note: the sequence to designate Unicode characters is \u with a lowercase u. This is a difference with the CodeWarrior property list compiler which used \U.

Download

PList Compiler is an Open Source Project. Its source code is freely available and can be found on the SourceForge site at the following address:

http://sourceforge.net/projects/plistcompiler

PList Compiler releases are available at

http://sourceforge.net/project/showfiles.php?group_id=149940

or on my web page at

http://webperso.easyconnect.fr/bdesgraupes/plistcompiler.html

The code is under CVS control. You can retrieve the latest stage of development using any CVS client. See instructions at:

http://sourceforge.net/cvs/?group_id=149940

You can browse the cvs repository online at

http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/plistcompiler

You can also download a nightly tarball from

http://cvs.sourceforge.net/cvstarballs/plistcompiler-cvsroot.tar.bz2

Known problems

Please e-mail any problem or bug you encounter:

bdesgraupes@users.sourceforge.net

Visit my Web page for updates and other recent builds:

http://webperso.easyconnect.fr/bdesgraupes/plistcompiler.html

Visit the PList Compiler project area on the SourceForge site:

http://sourceforge.net/projects/plistcompiler

There is also a mailing list, plistcompiler-users, for discussing any topics related to the usage of PList Compiler and its future development. New versions will be announced on this list too. You can subscribe or unsubscribe from the following address:

http://lists.sourceforge.net/mailman/listinfo/plistcompiler-users To post to this list, send mail to plistcompiler-users@lists.sourceforge.net

Version history

For a detailed list of the changes, see the file Changes_PLC in the CVS repository.

License and disclaimer

PList Compiler is distributed under the same BSD License as the Tcl language itself: see the file License_terms in the distribution or the Open Source Initiative site.


Last updated 2005-11-23 10:03:09


PList Compiler is hosted by

SourceForge.net Logo