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.6 of PList Compiler.
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.
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 -versionthe 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.
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.
The complete syntax to run the compiler is:
plcompile [-input_encoding enc] [-output_encoding enc] [-input_eol eol] [-output_eol eol] [-dest folder] [-o name] [-plist version] [-prefix file] [-Dmacro[=value]]... [-pkginfo] [-I path]... plcFile
The options have the following meaning:
As a convenience, a string starting with a slash is considered a full path: this is equivalent to setting both the output file and the output folder. For clarity though, it is recommended to use the -dest option when you need to specify a destination folder and use the -o option only to specify the name.
Note:
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.plcThe 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.plcor alternatively change the directory to this directory and execute the script there, like this:
cd /Users/bernardo/Devel/Tools ./plcompile /path/to/MyApp.plcsupposing, in the previous example, that plcompile resides in /Users/bernardo/Devel/Tools.
Since version 0.6, PList Compiler supports symbolic links to designate the plc file. This also applies to prefix files specified with the -prefix option. Note that this concerns Unix symbolic links (created with the ln command) but not Finder aliases.
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
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.plcOnce 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.
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:
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 the compiler is moderately clever to detect these symbols when they are found inside a quoted string (in which case you would not like them to be considered as a comment and wiped out!). The heuristics is as follows: if a line starts with // it is deleted unconditionnally but, if the // is not at the beginning of the line, it is considered as a comment only if there is no double quote after it, otherwise it might be a double slash inside a quoted string. This has been fixed in version 0.5: previous versions failed when a string contained a double slash.
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 list 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). Since version 0.6, one can use a backslash at the end of a line as a line continuator. If a backslash is found as the last character of a line, it is interpreted as a line continuation character: it is removed and the next line is concatenated to the previous one after any initial spaces have been trimmed. This can be useful in order to break very long strings on several lines.
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.
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/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 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 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).
Since version 0.4, the ampersand, greater-than, less-than, quote and apostroph symbols are correctly converted into XML entities (like & etc.) in order to ensure the well-formedness of the output file. Since version 0.5, the escape_entities pragma gives you entire control about this (see the Pragmas section below).
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 -1while 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 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 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 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.
The localized files contain lists of keyed strings localized for a particular language.
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 second one
MyApp.app/Contents/Resources/Spanish.lproj/Dialogs.stringsIt 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 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.
By default, the plist command causes PList Compiler to create a file named by defult 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 TARGET_BUILD_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/Contentswhere SRCROOT is, as usual the folder containing your project file.
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 inside the plc file using the output_filename pragma: see the Pragmas section below. It can also be specified directly from the command line via the -o option (introduced in version 0.5 of Plist Compiler).
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.
#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: " kVersionNumberit 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_nameIf 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.
#include "filename"
#include <filename>
The two forms are not equivalent: the difference is explained below. 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:
#include /Users/bernardo/Devel/MyApp/Rsrc/OtherFile.plc #include OtherFile.plc #include "LocFiles/My Strings_EN.ploc" #include "../Rsrc/My Strings_EN.ploc"
It is also possible to specify a path using a substitutable variable. Here is an example:
#define CURRENT_LOCALE "EN" #include "Strings_" CURRENT_LOCALE ".ploc"
Note: the second form of the #include directive is a code contribution by Franz Detro (thanks) introduced in version 0.2 of PList Compiler. The support for substitutable variables in #include paths is a code contribution by Steve Christensen (thanks) introduced in version 0.6 of PList Compiler.
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. Other more advanced technics involving Tcl instructions are explained in the section Advanced topics.
#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
When testing a condition involving a string value, one must take care of properly quoting the strings. Here is an example (where DEBUGGING_SYMBOLS is an Xcode variable whose value is YES or NO):
#if DEBUGGING_SYMBOLS == \"YES\" #warning "debugging symbols are enabled" #endif
It is not sufficient to just enclose the string YES in double quotes (because of double parsing, first by the preprocessor, then by the interpreter). Another possible syntax is:
#if DEBUGGING_SYMBOLS == {"YES"}
#warning "debugging symbols are enabled"
#endif
#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
#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
#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
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 and #message directives send a message to the console: the text of the message is prepended by the word Warning: or Message: respectively.
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 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, escape_entities.
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.
#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. #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.
#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.
#pragma output_eol lf
plcompile -encodingswhich currently returns:
ascii, big5, cp1250, cp1251, cp1252, cp1253, cp1254, cp1255, cp1256, cp1257, cp1258, cp437, cp737, cp775, cp850, cp852, cp855, cp857, cp860, cp861, cp862, cp863, cp864, cp865, cp866, cp869, cp874, cp932, cp936, cp949, cp950, dingbats, ebcdic, euc-cn, euc-jp, euc-kr, gb12345, gb1988, gb2312, gb2312-raw, identity, iso2022, iso2022-jp, iso2022-kr, iso8859-1, iso8859-10, iso8859-13, iso8859-14, iso8859-15, iso8859-16, iso8859-2, iso8859-3, iso8859-4, iso8859-5, iso8859-6, iso8859-7, iso8859-8, iso8859-9, jis0201, jis0208, jis0212, koi8-r, koi8-u, ksc5601, macCentEuro, macCroatian, macCyrillic, macDingbats, macGreek, macIceland, macJapan, macRoman, macRomania, macThai, macTurkish, macUkraine, shiftjis, symbol, tis-620, unicode, utf-8
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.
#pragma plist_version 0_9yields <plist version="0_9">
This is the same value stored in the __PLIST__ predefined variable (see below).
Since version 0.4, the ampersand, greater-than, less-than, quote and apostroph symbols are automatically converted by PList Compiler into their equivalent XML entities. This pragma allows you to turn this feature on or off during processing. The possible values are 0 or 1, or equivalently off or on (default is 1).
For instance, to turn escaping off:
#pragma escape_entities off
Substitutable variables are variables whose value is inserted when the script is run. These variables can be defined via a #define preprocessor macro in the plc file, or as a shell variable in the shell environment, or with the -D option directly on the command line. There are also some useful predefined variables set by the plc compiler itself.
Variables defined with a #define macro can be invoked directly. 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
Note:
In versions older than 0.6, in order to invoke a variable defined in the shell environment or inherited from Xcode, one had to surround it with double underscores (like __USER__ instead of USER). It is not the case anymore since version 0.6. For backward compatibility, PList Compiler will still check if a variable surrounded by double underscores is an inherited variable but you should update your plc files if you were using this old (and confusing) convention.
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!):
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 panel in Xcode using the Plus button and to give them the desired values corresponding to your project.
Furthermore PList Compiler introduces other useful predefined variables:
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
All the environment variables set by an Xcode project are accessible with PList Compiler. See the Xcode documentation for a complete list. 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 of a particular target. Tip: 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.
Remark:
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.
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-point | Letter |
| 03B1 | GREEK SMALL LETTER ALPHA |
| 03B2 | GREEK SMALL LETTER BETA |
| 03B3 | GREEK SMALL LETTER GAMMA |
| 03B4 | GREEK SMALL LETTER DELTA |
| 03B5 | GREEK SMALL LETTER EPSILON |
| 03B6 | GREEK SMALL LETTER ZETA |
| 03B7 | GREEK SMALL LETTER ETA |
| 03B8 | GREEK SMALL LETTER THETA |
| 03B9 | GREEK SMALL LETTER IOTA |
key "UniString1" value string "\u03B1 \u03B2 \u03B3 \u03B4 \u03B5 \u03B6 \u03B7 \u03B8 \u03B9"and will produce:
<key>UniString1</key>
<string>α β γ δ ε ζ η θ ι</string>
Note: the escape sequence to designate Unicode characters is \u with a lowercase u. This is a difference with the CodeWarrior property list compiler which used \U.
With the -pkginfo command line option, one can ask PList Compiler to generate a PkgInfo file containing the type and signature of the product. This file will be located in the same folder as the Info.plist file. The type and signature are computed like this:
If the type or the signature are shorter than four characters, they are padded with blanks. On the contrary, if the string is longer than four characters, it is trimmed.
Caveat: in order to use the -pkginfo option, the Force Package Info Generation setting in Xcode must be off. If it is on, PList Compiler will raise an error and will not generate the PkgInfo file.
Since PList Compiler is written in Tcl, it is possible to introduce some Tcl code in the #if conditions. One could for instance let an instruction depend on the existence of some file like this:
#if "[file exists /path/to/some/file]" // do something. For instance include it! #include "/path/to/some/file" #endif
The Tcl instruction must be written as a string (with double quotes) and should obviously return a boolean value (0 or 1). Anything which can be eval'ed by the Tcl interpreter is acceptable, even sourcing an external Tcl script, provided it returns a boolean value. Here is a sample:
#if "[source [file join [pwd] script.tcl]]" // do something... #endif
The Tcl instruction could also be built in several pieces to mix it with substitutable variables. For instance:
#define SOME_FILE /path/to/some/file #if "[file exists " SOME_FILE "]" #warning "file exists: " SOME_FILE #else #warning "file does not exist: " SOME_FILE #endif
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://perso.orange.fr/bdesgraupes/DocHTML/plistcompiler.html
The code is under Subversion control. You can retrieve the latest stage of development using any Subversion client. See instructions at:
http://sourceforge.net/svn/?group_id=149940
You can browse the Subversion repository online at
http://plistcompiler.svn.sourceforge.net/viewvc/plistcompiler
Please e-mail any problem or bug you encounter:
bdesgraupes@users.sourceforge.net
Visit my Web page for updates and other recent builds:
http://perso.orange.fr/bdesgraupes/
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
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 2007-09-07 08:25:41