Skip to content
PaskalCPP
Build and run

Building

How pcpp turns a main module into an executable or a library: what each kind builds, what the output folder holds, what each optimize level changes, how a target is built and run, and how libraries and the runtime are linked.

What a build makes

module exe builds an executable, module dll a shared library and module lib a static library. A unit is not built on its own: given to pcpp as the main module it is PR0004.

pcpp writes a C++23 header and source for each module and builds them with the bundled Zig toolchain (clang, -std=gnu++23) through zig build, which caches compiles. The toolchain folder is read from build.toml beside pcpp.exe (toolchain_path); the default is $P:res, the res folder beside pcpp.exe.

A successful build prints Build succeeded. and then Output: <path of the artifact>.

The output folder

The output folder is the -o option, else the @outputpath directive, else output under the working folder. It holds:

PathWhat it is
build.zigthe build script pcpp writes
pcpp-output.jsonpcpp's record of the build: format, source, output folder, project
pcpp-installed.txtthe record of the files the build put in bin\ and lib\
generated\<Module>.pcpp.h, .pcpp.cppthe C++ written for each module
pcpp-diag\clang's diagnostics, one file per translation unit
.zig-cache\zig's cache
bin\an exe or a dll
lib\a lib (and a Windows dll's import library)
Kindx86_64-windows-gnux86_64-linux-gnu
exe<name>.exe<name>
dll<name>.dll (import library <name>.lib in lib\)lib<name>.so
lib<name>.liblib<name>.a
  • A Windows debug build writes the program's .pdb beside the exe or dll; a safe, fast or small build writes none, and neither does a Linux build.
  • Every file a build puts in bin\ and lib\ (the program or library, its .pdb, a dll's import library, the @copydll files) is recorded in pcpp-installed.txt in the output folder. Before the next build, a recorded file that build does not produce is removed, with Removing bin/<file>: an earlier build put it there, this build does not produce it: a debug build's .pdb before a fast build, a program or a copy the build no longer makes. A file the record does not name is never removed.
  • An output folder longer than 198 characters is ZB0021 and nothing is built: zig launches its configure program from a folder nested under the output folder.

Optimize levels

With no @optimize (and no -opt) the build is debug.

LevelDefinesHeap report
debugPCPP_DEBUGyes
safe__OPTIMIZE__no
fast__OPTIMIZE__, NDEBUGno
small__OPTIMIZE__, __OPTIMIZE_SIZE__, NDEBUGno

A debug build prints the runtime's heap report, [Heap] Allocs: <n>, Frees: <n>, Leaked: <n>, when the program ends. The level names are zig's own: build.zig writes the level as zig's optimize mode of the same name (small is std.lang.Optimize = .small).

build_debug.pcpp
module exe build_debug;

// What the C++ compiler sees at this optimize level
static const char* build_debug_flag()
{
#ifdef PCPP_DEBUG
  return "yes";
#else
  return "no";
#endif
}

begin
  println("PCPP_DEBUG: {}", build_debug_flag());
end.
output on x86_64-windows-gnu and x86_64-linux-gnu
PCPP_DEBUG: yes
[Heap] Allocs: 0, Frees: 0, Leaked: 0

Targets and running

The same source builds for x86_64-windows-gnu and x86_64-linux-gnu, from Windows: @target in the source (see Target) or pcpp -t.

  • pcpp <file> -r builds the exe and runs it in its own folder; a Linux exe runs through WSL.
  • A program that exits with a code other than 0 under -r is ZB0031 (Program exited with code <n>.), and pcpp exits with that code.
  • -r on a dll or a lib is the warning CMP0002 (a dll cannot be run: auto-run skipped); the build itself succeeds.

Linking libraries

An exe links a PaskalCPP dll by name (@linklibrary) from the folder @addlibrarypath names (Windows: the import library in the dll's lib\; Linux: the .so in its bin\), declares the dll's routines external, and @copydll puts the library beside the exe so it is found at run time.

  • @copydll files are copied before the build; a file an earlier build copied beside the artifact that no @copydll names any more is removed.
  • A routine no linked library defines fails at the link as ZB0016 in the linker's words, reported at the .pcpp line that calls it.

Static libraries and the runtime

  • A lib whose code never calls into the PaskalCPP runtime ships alone, with no startup hook, and a C program links it with a plain C driver.
  • A lib that calls into the runtime (div, mod, a guard, raise, sets, ...) gets a startup hook, and pcpp builds the runtime library and publishes it beside the lib (pcpp_runtime.lib; on Linux libpcpp_runtime.a), printing Publishing ... to ....
  • A lib that no longer calls into the runtime removes the pcpp_runtime an earlier build published beside it.
  • A PaskalCPP program that links such a lib brings its own runtime and never links pcpp_runtime; a raise inside the lib reaches the program's guard.
  • A C program built by another toolchain links the lib, then pcpp_runtime, through a C++ driver; without pcpp_runtime the link fails on pcpp::init.

Resource stamps

@exeicon, and @addverinfo on with the @vi* fields, are stamped on the built Windows binary after the build; where a stamp does not apply it is the warning SM0103 (see Values). A requested stamp that fails is an error (icon ZB0008, version info ZB0009), and nothing is published.