Skip to content
PaskalCPP
Language

Directives

Every directive starts with @. Build directives describe the build inside the source itself; conditional directives are PaskalCPP's own conditional compilation.

The reference lists every directive with the values it takes, read from the compiler's own tables.

Build directives

There are 25 build directives, written in exact case and each ended with ;:

@optimize @subsystem @target @addverinfo @unitTestMode @vimajor @viminor @vipatch @viproductname @videscription @vifilename @vicompanyname @vicopyright @exeicon @copydll @linklibrary @addlibrarypath @addmodulepath @addincludepath @addsourcefile @cppdefine @cppundef @breakpoint @message @outputpath

An unknown directive is PR0005; a value of the wrong shape (a string where a word belongs, a number where a string belongs) is PR0006.

Where they stand

  • Build directives stand only in the directive prologue, right after module ...; and before the import clause; elsewhere they are PR0008.
  • @breakpoint and @message are also statements and may stand in bodies; @breakpoint in the prologue has no effect and is the warning SM0109.
  • A single-valued directive given twice in one module is SM0102. The list directives (@copydll @linklibrary @addlibrarypath @addmodulepath @addincludepath @addsourcefile @cppdefine @cppundef) accumulate.
  • In an imported unit the main-module-only directives (@optimize @subsystem @target @addverinfo @unitTestMode @vi* @exeicon @addmodulepath @outputpath) are PR0023; the list directives add to the one build, and @breakpoint and @message are allowed.

Values

  • @optimize takes debug, safe, fast or small; @subsystem console or gui; @addverinfo and @unitTestMode on or off. Exact case; any other value is SM0100, naming the accepted ones. What each level does is on Optimize levels.
  • A retired @optimize name (release_safe, release_fast, release_small) is SM0100 naming its new one: 'release_fast' is no longer a value of @optimize: write 'fast'.
  • @vimajor, @viminor and @vipatch take 0..65535; outside is SM0101.
  • Version info is stamped only with @addverinfo on; a @vi* without it is the warning SM0104.
  • A setting the module cannot take is the warning SM0103 and is not applied: @exeicon on a non-exe or a non-Windows target, @addverinfo on on a lib or a non-Windows target, @subsystem gui on a non-exe or a non-Windows target.

Paths and libraries

  • A path directive's value is resolved once; $P: is the folder pcpp.exe is in. A path that cannot be resolved is PR0022.
  • A path directive must name something that exists: @exeicon and @copydll a file (else SM0105), @addlibrarypath, @addincludepath and @addmodulepath a directory (else SM0106).
  • @linklibrary "m"; names a library (m, user32), found by the system linker; a file name or a path is PR0055. A library the linker cannot find is reported at the @linklibrary that names it.
  • @copydll puts a DLL beside the built binary before the build.
  • @addsourcefile adds a C, C++, assembly or LLVM IR file to the build, chosen by its exact-case extension: .c; .C .cc .cp .cpp .CPP .cxx .CXX .c++ .C++; .S .s; .ll. Another name (a header) is SM0114, a missing file SM0105.
  • @outputpath "<path>"; sets the build's output folder (main module only, at most once); pcpp -o wins over it. With neither, it is output under the working folder.

C preprocessor macros

@cppdefine "NAME";, @cppdefine "NAME" "VALUE"; and @cppundef "NAME"; define and undefine a C macro for every translation unit of the build: the generated C++, the runtime and every @addsourcefile file.

  • NAME must be a C macro name (else SM0115); PCPP_ names are reserved (SM0116). One name defined with two values, or defined and undefined, anywhere in the program is SM0118 at the later one.
  • PaskalCPP's @define symbols and C macros never see each other: #ifdef does not see a @define, and @ifdef does not see a @cppdefine.

Target

@target takes an LLVM triple as a string. The official targets are x86_64-windows-gnu (the default) and x86_64-linux-gnu; the four-part spellings x86_64-pc-windows-gnu and x86_64-unknown-linux-gnu are accepted.

  • @target stands in the prologue, outside and before any conditional directive, at most once: CD0005 out of the prologue, CD0006 inside a branch, CD0007 after a conditional, CD0008 twice; not a plain string CD0009, malformed CD0010, another triple CD0011.
  • Only the main module's target applies: an imported unit with a different @target is CD0012. pcpp -t wins over every @target; with --defaults (the editor passes it) it only stands in for a missing one.

Messages

@message hint|warn|error|fatal "text"; reports the text at compile time as SM0108 with that severity, from the prologue or a body; an error or fatal message fails the build. A misspelt severity is PR0007, a missing text PR0006.

Conditional directives

@define X, @undef X, @ifdef X, @ifndef X, @elseif X, @else and @endif are PaskalCPP's own. They take no ;, may stand anywhere (the prologue, module level, inside a statement) and nest; @elseif X means "else, if X is defined".

directives_target.pcpp
module exe directives_target;

@define VERBOSE

begin
@ifdef TARGET_WINDOWS
  println("built for Windows");
@elseif TARGET_LINUX
  println("built for Linux");
@else
  println("built for something else");
@endif
@ifdef VERBOSE
@ifdef TARGET_64BIT
  println("64-bit pointers");
@endif
@endif
end.
output on x86_64-windows-gnu
built for Windows
64-bit pointers
[Heap] Allocs: 0, Frees: 0, Leaked: 0
  • A missing symbol is CD0001, @endif with nothing open CD0002, a second @else CD0003, an @ifdef never closed CD0004.
  • Each file has these symbols defined: PASKALCPP; BUILD_EXE, BUILD_DLL, BUILD_LIB or BUILD_UNIT from the file's own kind; TARGET_<ARCH> (TARGET_X86_64), TARGET_<OS> (TARGET_WINDOWS, TARGET_LINUX), TARGET_<ABI> (TARGET_GNU), the whole triple (TARGET_X86_64_WINDOWS_GNU, TARGET_X86_64_LINUX_GNU), and TARGET_64BIT.
C++ side

C preprocessor lines (#...) are not evaluated by PaskalCPP; they go to clang as written.