# pmcs: preprocessing frontend to mcs pmcs performs search and replace operations on source code before invoking the actual mcs C# compiler. Original input files are not modified by default; rather, temporary files are passed to the compiler containing the preprocessed source code. Search and replace operations are not performed for the entire contents of a file. Instead, the preprocessor is aware of C# comments and string literals. It will only perform replacements on "tokens" in C# code, where a "token" is a group of characters being letters, digits, or one of `_`, `.`, or `:`. ## Command Line Options ## | Option | Description | | ----------------------- | ----------- | | `-h`, `-help` | Show help | | `-v`, `-verbose` | Be verbose with output | | `-compiler:VALUE` | Set the mcs compiler executable to invoke to `VALUE` | | `-P`, `-profile:VALUE` | Load a pmcs XML profile from `VALUE`; see [XML Profiles](#xml-profiles) | | `-ignore:VALUE` | Do not preprocess `VALUE` | | `-global-replace:VALUE` | Define a global replacement where `VALUE` = `PATTERN=REPLACEMENT`; see [Replacement Definitions on the Command Line](#replacement-definitions-on-the-command-line) | | `-enum-replace:VALUE` | Define an enum backing type replacement where `VALUE` = `PATTERN=REPLACEMENT`; see [Replacement Definitions on the Command Line](#replacement-definitions-on-the-command-line) | | `-target:VALUE` | specifies the format of the output assembly | | `-omit-line-directive` | Do not generate a C# `#line` directive at the start of preprocessed files | | `-skip-mdb-rebase` | do not rebase path names in .mdb symbol files (if -debug was specified) | | `-skip-compile` | Do not perform compilation (preprocess only) | | `-keep` | Do not delete preprocessed intermediate files (implied with `-in-place`) | | `-in-place` | Preprocess in place instead of outputting intermediate files. **WARNING:** this can be dangerous -- only use this option if your sources are under version control and do not have local changes or are otherwise backed up. | | `-stdout` | Write preprocessed output to standard output (implies `-skip-compile` and no files on disk are modified) | ## MDB Rebasing ## The paths that pmcs passes to the actual compiler will have a different name from what was passed to pmcs itself - these files will contain the actual preprocessed output. For instance: $ pmcs -profile:foo Bar.cs Here, `Bar.cs` is the original source which needs to be preprocessed. By default (e.g. `-in-place` is not specified), pmcs will generate a file named `~.pmcs-foo.Bar.cs` which will be passed to the actual compiler. When the actual compiler compiles these files, their preprocessed names will end up in the `.mdb` symbol files, which is undesirable. By default pmcs will rebase the symbol files with the original names passed to pmcs. This can be disabled by passing `-skip-mdb-rebase` to pmcs. ## Replacements ## Three replacement kinds are supported: | Kind | Description | | ------ | -------------------------------------------------------------------- | | Exact | Only tokens matching exactly are replaced | | Prefix | Tokens starting with a pattern have the matching prefix replaced | | Regex | Tokens matching a regular expression have the matching part replaced | Additionally, there are two replacement token scopes: | Scope | Description | | ------ | ------------------------------------------------------------------------- | | Global | Perform replacements on any kind of token | | Enum | Perform replacements only on "backing type" tokens for an enum definition | The "enum" token replacement scope is useful for defining an alternate replacement value for enum backing types when a global replacement value is already defined for the same pattern: | Pattern | Global Replacement | Enum Replacement | | ------- | -------------------- | ---------------- | | nint | global::System.Int32 | int | The enum replacement scope has priority over the global scope. ### Replacement Definitions on the Command Line ### Replacements can be defined on the command line by specifying one of the two replacement options: * `-global-replace:PATTERN=REPLACEMENT` * `-enum-replace:PATTERN=REPLACEMENT` Where `PATTERN` is the pattern to be matched against a token, and `REPLACEMENT` is the new value for the matching token or part of the matching token. To define a Regex replacement on the command line, prefix `PATTERN` with `/`: * `-global-replace:"/^(global::System\.|System\.)?nint=global::System.Int32"` To define a Prefix replacement on the command line, prefix `PATTERN` with `^`: * `-global-replace:"^MonoTouch=MonoMac"` An exact replacement does not need a prefix to `PATTERN`: * `-enum-replace:nint=int` ### Replacement Definitions in an XML Profile ### Replacements can also be defined inside a pmcs XML profile with the `` element. Each of these elements must have a `scope` attribute with a value of either `global` or `enum` and can contain child elements named either `exact`, `prefix`, or `regex` with attributes `pattern` and `replacement`. An XML version of the command line replacement definitions above: ```xml ``` ### Replacement Examples Overview ### In the above examples, tokens that are equal to `global::System.nint`, `System.nint`, or `nint` (as matched by the regular expression replacement) are replaced with `global::System.Int32`, effectively translating a fake `nint` type into a real `System.Int32` type. Because enums can only be backed by certain C# keywords (not types), an enum-scoped replacement is defined to translate `nint` to `int`, the C# keyword for `System.Int32`. Finally, a prefix replacement is used for translating the `MonoTouch.*` namespaces into `MonoMac.*` namespaces. Prefix replacements are faster than regular expression replacements. ## XML Profiles ## XML Profiles provide an alternate means to specifying the compiler executable, extra compiler options, and replacement definitions. Each profile must start with a `` root element and can contain any number of the following child elements: ### Ignore Paths ### `VALUE` element: do not preprocess `VALUE` ### Compiler Configuration ### `` container element. No attributes. ##### Child elements: ##### * `VALUE`: specify the compiler executable to be `VALUE` * ``: append `VALUE` as a command line option to the compiler ### Replacements ### `` container element with `scope` attribute; `scope` should be either `global` or `enum`. See [Replacement Definitions in an XML Profile](#replacement-definitions-in-an-xml-profile) for more detail. ##### Child elements: ##### * `` * `` * `` The child elements specify which [kind of replacement to perform](#replacement-definitions-in-an-xml-profile). ### Includes ### `PATH` inline another pmcs profile in `` order. where `PATH` is relative to the parent directory of the current profile. ### Example ### ```xml /usr/local/bin/mcs Compat.cs ```