Once I get that upgrade to 36-hour days, I will tackle that. – Mychaeel

Preprocessor

From Unreal Wiki, The Unreal Engine Documentation Site
Jump to: navigation, search

Starting with Unreal Engine 3 The UnrealScript compiler now supports a preprocessor.

The preprocessor works much like the C++ preprocessor and is perfect for supporting conditional compilation via macros. Macros are file-scope, meaning a macro defined on line X of the script class (.uc) file is only usable on lines X+n in that file and not in any other files (unless it is included in another .uc file). However, you can create a .uci file to include macros in your .uc file.

Command-line Switches

-debug

Using a -debug command line option causes a `debug macro to be defined.

-final_release

Using a -final-release command line option causes UPP to define the macro `final_release, as well as disable all wrapper macros (`log, `logd, `warn, `assert). (see below).

-nopreprocess

Using a -nopreprocess command line option turns off all macro and comment preprocessing.

-intermediate

Using a -intermediate command line option will save the processed versions of the files compiled (for tracking down errors in macros) to <My Documents>\PreprocessedFiles\<package>\<class>.uc

Using Macros

`define

`define <macroname>[<(paramA[,paramB...])>] [<macrodefinition>]
Defines the named macro to expand to the given definition. Parameters for the macro are specified in a typeless function parameter list immediately after the name of the macro. In the macro definition, the parameters are referenced by name and prefixed with a backtick. Although I have not yet verified, my research indicated that you can also use the the special macro `# to represent the number of parameters specified, although I have not verified this though. If you don't give the macro a definition, the macro is still defined but expands to an empty string. You can also define a macro to represent a constant value.

Equivalently, the name of the macro can be enclosed in { } after the tick as in `{hello}. This makes it possible to "insert" the expansion of a macro into the middle of text that does not have conveniently placed whitespace.

hippo`{hello}potamus

Other examples:

`define SOME_CONST 1
 
`define   hello   "Hello, World!"
 
`define SomeMacro(param1, param2) CallMyFunction(`param1, `param2)

`if / `else / `endif

`if(<string>)

`else

`endif
Basically, this is conditional compilation. The text between `if and either `else (if present) or `endif are emitted into the processed output if the condition is true (if it is expanded to a non-empty string); if the condition is not true, only the end-of-line characters are emitted so that the line numbers in the processed text match up with those in the original text. The text between the (optional) `else and `endif are emitted if the original condition is false.

This may be obvious, but any macros used in the non-emitted code (in the `else if the statement is true, or before the `else if the statement is true) are not evaluated (except for nested `if blocks).

`if(`isdefined(SOME_CONST))
     // do some code here if SOME_CONST can be expanded to a non-empty string...
`endif
 
`if(`isdefined(SOME_OTHER_CONST))
     // do some code here if SOME_CONST can be expanded to a non-empty string...
`else
     //do some code here if SOME_CONST can NOT be expanded to a non-empty string...
`endif

`include

`include(<filename>)
Includes the text within the file <filename> at the macro's location in the code. By default, <filename> is relative to the directory specified by the EditPackagesInPath of the [Editor.EditorEngine] section of UTGame.ini file. If you specify only the filename (no directory), it will search for the include file in the classes directory for the package being compiled.

`include( MyStuff.uci )
 
`include( MyPackage/Classes/MyGlobals.uci )

`isdefined / `notdefined

`isdefined(<macroname>)
`notdefined(<macroname>)
Evaluates to the string "1" if the macro is (`isdefined) or is not (`notdefined) defined, regardless of the macros definition. This useful for conditional compilation. You can include code only in debug or release builds, or based on other defined constants.

`if(`isdefined(SOME_CONST))
     // do some code here if SOME_CONST is defined...
`endif
 
`if(`notdefined(SOME_CONST))
     // do some code here if SOME_CONST is NOT defined...
`endif

`undefine

undefine(<macroname>)
Remove the current definition of <macroname>.

`undefine(SOME_CONST)

Predefined Macros for Logging

There is a good reason to use the `log and `warn macros instead of LogInternal() and WarnInternal() functions. If you use the -final_release command line option when you "make", it will turn off all logging because `log and `warn are empty defines when using -final_release. However, the LogInternal() and WarnInternal() function(s) will still be called if you use them directly. Using the macro to write to the log for debug info will not incur a function call overhead in a release build.

More importantly, it also appears that calls to LogInternal (or anything *Internal) generate compiler errors when using -final_release.

`log / `warn

`log(string OutputString, optional bool bRequiredCondition, optional name LogTag)
`warn(string OutputString, optional bool bRequiredCondition)

Wrapper macros for the LogInternal and WarnInternal functions declared in Object.uc. If bRequiredCondition is specified, the message will only be logged if the condition is true.

Both macros are disabled if scripts are compiled with the -final_release command line option.

`logd

`logd(string OutputString, optional bool bRequiredCondition, optional name LogTag)

Identical to the `log macro, except that it is only enabled if scripts are compiled in debug mode.

This macro is disabled if scripts are compiled with the -final_release switch.

`assert

`assert(bool bCondition)

Wrapper macro for the Assert intrinsic expression.

This macro is disabled if scripts are compiled with the -final_release switch.