@node Compiling
@chapter Compiling

@cindex compiling
@cindex F9
@cindex compiler message format
@cindex gcc
@cindex make

xwpe integrates with external compilers through a compile-edit-debug
cycle.  The compiler is configured per language (by file extension) and
xwpe parses compiler output to jump to errors in the source code.

This chapter was verified on 2026-06-01 with xwpe 1.6.3 against GCC 15.2,
G++ 15.2, GFortran 15.2, Free Pascal 3.2.2, OpenJDK javac 25, Python 3.13,
Perl 5.40, and pdflatex (TeX Live 2025).

@section The build cycle

@cindex build cycle
@cindex Alt-F9
@cindex Ctrl-F9

The build cycle uses three commands, each building on the previous:

@table @kbd
@item Alt-F9 (Compile)
Compile the current file only.  For GNU compilers (gcc, g++, gfortran),
xwpe invokes the compiler with @code{-c -o @var{file}.o @var{file}.c}.
For non-GNU compilers (fpc, javac), the @code{-c} and @code{-o} flags
are omitted.  Only files modified since the last compilation are
recompiled.

@item F9 (Make)
Recompile all modified files and link the executable.  This is the
most common command.

@item Ctrl-F9 (Run)
Build the executable and then run it.  Program arguments can be set
via @samp{Run @result{} Arguments} (@kbd{Alt-R A}).

For interpreted languages (Python, Perl), @kbd{Ctrl-F9} runs the
script directly via the interpreter (e.g.@: @code{python3 file.py}).
In X11 mode, output is captured to the Messages buffer via
@code{popen}; no xterm is spawned.
@end table

After compilation, errors appear in the Message Window.  Use
@kbd{Alt-T} or @kbd{Alt-F8} (Next Error) and @kbd{Alt-V} or
@kbd{Alt-F7} (Previous Error) to navigate between errors.  The cursor
jumps to the error location in the source code.  These commands are
also available from the @samp{Run} menu as @samp{Next Error} and
@samp{Previous Error}.

@subsection Header dependencies

@cindex header dependencies
@cindex recompilation
@cindex check headers

xwpe recompiles a source file not only when the file itself changes, but
also when any header it @code{#include}s has changed since the last
build.  It finds those headers by scanning the source for @code{#include
"@var{file}"} directives (recursively, through the headers too).

Crucially, it ignores @code{#include}s that are not actually in effect:
those inside a @code{//} or @code{/* @dots{} */} comment, and those
inside a @code{#if 0 @dots{} #endif} block.  A commented-out or disabled
include is not a real dependency, so editing such a header does not force
a needless recompile.

The example @file{docs/examples/headers_test.c} demonstrates this: it
includes the real header @file{headers_test.h}, mentions @file{fake.h}
inside a @code{//} comment, and includes @file{disabled.h} inside an
@code{#if 0} block.  Editing @file{headers_test.h} and pressing @key{F9}
recompiles; editing @file{fake.h} or @file{disabled.h} does not.

@section Configuring the compiler

@cindex compiler configuration
@cindex Options menu

The compiler is configured via @samp{Options @result{} Compiler}
(@kbd{Alt-O C}).  Each language is identified by its file extension
(e.g.@: @file{.c} for C, @file{.cpp} for C++).

Settings per language:
@itemize @bullet
@item @strong{Compiler}: path or name of the compiler (e.g.@: @code{gcc}).
@item @strong{Compiler Options}: flags passed to the compiler
(e.g.@: @code{-Wall -g}).
@item @strong{Loader Options}: flags passed to the linker
(e.g.@: @code{-lm}).
@item @strong{Executable Name}: name of the output binary
(default: derived from the source file name).
@item @strong{Compiler Style}: @code{GNU} or @code{Other}.
@code{GNU} uses the built-in @code{file:line:column:} pattern.
@code{Other} uses a custom interpreter string that you define.
@end itemize

@section Language support

@cindex language support

xwpe selects the compiler automatically based on the file extension.
Ten languages are configured by default.

@subsection Default compilers (v1.6.3)

@multitable @columnfractions .12 .14 .22 .22 .30
@headitem Language @tab Compiler @tab Extensions @tab Error format @tab Notes
@item C @tab gcc @tab .c @tab @code{file:line:col:} @tab
  GNU style.  Cursor jumps to exact column.
@item C++ @tab g++ @tab .cpp .cc .C .cxx @tab @code{file:line:col:} @tab
  Same error format as gcc.
@item Fortran @tab gfortran @tab .f .f90 .f95 .f03 .f08 @tab @code{file:line:col:} @tab
  GNU style.  Blank lines in output are handled.
@item Pascal @tab fpc @tab .p .pas .pp @tab @code{file(line,col)} @tab
  Dedicated pattern.  Cursor jumps to exact column.
@item Java @tab javac @tab .java @tab @code{file:line:} @tab
  No column in javac output.  Cursor goes to start of line.
@item Python @tab python3 @tab .py @tab @code{File file, line N} @tab
  Uses @code{-m py_compile}.  Ctrl-F9 runs the script.
@item LaTeX @tab pdflatex @tab .tex @tab @code{file:line:} @tab
  Uses @code{-interaction=nonstopmode -file-line-error}.
@item Perl @tab perl @tab .pl .pm @tab @code{at file line N} @tab
  Uses @code{-c} for syntax check.  Ctrl-F9 runs the script.
@item COBOL @tab cobc @tab .cob .cbl @tab @code{file:line:} @tab
  GNU COBOL.  GNU style with @code{-g}.
@item Algol 68 @tab ga68 / a68g @tab .a68 .alg @tab (by toolchain) @tab
  Two source-incompatible toolchains; xwpe picks one per file from its
  dialect (see below).  ga68 (GCC front-end) compiles a native binary;
  a68g (Algol 68 Genie) interprets, with @code{--norun} for the F9 check.
@end multitable

@subsection Other GNU-compatible compilers

Any compiler that produces errors in the @code{file:line:column: message}
format works with xwpe's default @code{GNU} compiler style without
configuration.  Known compatible compilers include:

@itemize @bullet
@item clang, clang++ (LLVM C/C++)
@item rustc (Rust)
@item go build (Go)
@item dmd, ldc2 (D)
@item valac (Vala)
@item ghc (Haskell)
@item zig (Zig)
@item nim (Nim)
@item GNU Guile (Scheme)
@end itemize

To use one of these, go to @samp{Options @result{} Compiler}, set the
compiler name and file extension, and select @code{GNU} style.

@quotation Note
Go (@code{.go}), Rust (@code{.rs}) and Scala (@code{.scala}) also have
@emph{source-level debugging} over the Debug Adapter Protocol, where the
build is driven by the debug toolchain itself (Delve builds the Go package,
xwpe compiles Rust with @code{rustc -g}, and Bloop builds the Scala target).
See @ref{Debugging}.  All three are syntax-highlighted -- see
@ref{Configuration} (@file{syntax_def}).
@end quotation

@section The interpreter string (pattern language)
@anchor{Interpreter string}

@cindex interpreter string
@cindex pattern language
@cindex error parsing
@cindex message-string

When @code{Compiler Style} is set to @code{Other}, xwpe uses a custom
@dfn{interpreter string} to parse compiler output.  This is a pattern
that tells xwpe how to extract the filename, line number, and column
from each error message.

@subsection Pattern syntax

The interpreter string is a mix of literal text and special placeholders.
xwpe matches each line of compiler output against this pattern.

@subsubsection Wildcards

@multitable @columnfractions .15 .85
@headitem Pattern @tab Meaning
@item @code{*} @tab Match any sequence of characters (including empty).
@item @code{?} @tab Match any single character.
@item @code{[abc]} @tab Match any one of the characters listed.
@item @code{[!abc]} @tab Match any character NOT listed.
@item @code{[a-z]} @tab Match any character in the range.
@end multitable

@subsubsection Variable placeholders

These capture parts of the error message:

@multitable @columnfractions .40 .60
@headitem Placeholder @tab Meaning
@item @code{$@{FILE@}} @tab Filename containing the error.
@item @code{$@{LINE@}} @tab Line number of the error (must be a digit).
@item @code{$@{LINE+N@}} or @code{$@{LINE-N@}} @tab Line number with
  offset adjustment.
@item @code{$@{COLUMN@}} @tab Column number (numeric).
@item @code{$@{COLUMN+N@}} or @code{$@{COLUMN-N@}} @tab Column with
  offset.
@item @code{$@{COLUMN=BEFORE@}} @tab Column is determined by searching
  for a string that appears BEFORE the error position.  The captured
  text is searched in the source line.
@item @code{$@{COLUMN=AFTER@}} @tab Column is determined by searching
  for a string that appears AFTER the error position.
@item @code{$@{CMPTEXT@}} @tab Captures the compiler's error text
  (used with multi-line formats).
@end multitable

@subsubsection Warning detection

@multitable @columnfractions .40 .60
@headitem Placeholder @tab Meaning
@item @code{$@{?*:STRING@}} @tab If @code{STRING} appears anywhere in
  the line, treat this as a warning rather than an error.  Warnings
  are skipped when navigating with Alt-T/Alt-V unless
  @code{ED_MESSAGES_STOP_AT} is set.
@item @code{$@{?N:STRING@}} @tab Like the above, but @code{STRING}
  must appear at column @var{N} (0-based).
@end multitable

@subsubsection Multi-line patterns

Patterns can span multiple lines of compiler output by using @code{\n}
as a line separator.  Up to 4 lines can be matched.  The first line
must match the filename; subsequent lines can match additional details
like line numbers, column indicators, or error text.

@subsection Built-in patterns

xwpe ships with three built-in pattern strings:

@table @code
@item GNU (default)
@code{$@{?*:warning:@}$@{FILE@}:$@{LINE@}:$@{COLUMN@}:*}

Matches: @code{hello.c:3:29: error: expected ';' before 'ret'}

This pattern is used automatically when Compiler Style is @code{GNU}.
It works with gcc, g++, gfortran, clang, rustc, Go, and any compiler
that uses the @code{file:line:column:} format.

@item cc (classic UNIX cc)
@code{$@{?*:warning:@}"$@{FILE@}", line $@{LINE@}:* at or near * "$@{COLUMN=AFTER@}"}

Matches: @code{"hello.c", line 3: error at or near "foo"}

@item Pascal (Turbo Pascal / old FPC)
Multi-line pattern for the classic Turbo Pascal error format.  Modern
Free Pascal (fpc) uses a different format; see below.
@end table

@subsection Examples

@subsubsection Free Pascal (fpc)

FPC errors look like:

@example
hello.pas(6,10) Error: Incompatible types
hello.pas(7,10) Error: Incompatible types
@end example

Pattern (configured by default in xwpe 1.6.2):

@example
$@{?*:Warning:@}$@{FILE@}($@{LINE@},$@{COLUMN@})*
@end example

Breakdown:
@itemize @bullet
@item @code{$@{?*:Warning:@}} -- if ``Warning:'' appears, treat as
  warning, not error.
@item @code{$@{FILE@}(} -- capture everything before @code{(} as the
  filename.
@item @code{$@{LINE@},} -- capture digits before @code{,} as line
  number.
@item @code{$@{COLUMN@})} -- capture digits before @code{)} as column.
@item @code{*} -- match the rest of the line (the error message).
@end itemize

@subsubsection javac (Java)

javac errors look like:

@example
Hello.java:3: error: incompatible types
        int x = "hello";
                ^
@end example

Pattern (configured by default in xwpe 1.6.2):

@example
$@{?*:warning:@}$@{FILE@}:$@{LINE@}:*
@end example

Note: javac does not report a column number, so the cursor goes to
the beginning of the error line.

@subsubsection Python (python3 -m py_compile)

Python compile errors look like:

@example
  File "/path/to/hello.py", line 3
    x = (1 +
        ^
SyntaxError: '(' was never closed
@end example

Pattern (configured by default):

@example
*$@{FILE@}, line $@{LINE@}
@end example

@noindent
@kbd{Ctrl-F9} runs the Python script directly via @code{python3}
and captures output in the Messages buffer.

@subsubsection Perl (perl -c)

Perl syntax check errors look like:

@example
syntax error at hello.pl line 6, near "print"
@end example

Pattern (configured by default):

@example
*at $@{FILE@} line $@{LINE@}
@end example

@noindent
@kbd{Ctrl-F9} runs the Perl script directly via @code{perl}
and captures output in the Messages buffer.

@subsubsection gfortran (Fortran)

gfortran errors look like:

@example
hello.f90:3:6:

    3 |   a = "x"
      |      1
Error: Cannot convert CHARACTER(1) to INTEGER(4) at (1)
@end example

@noindent
gfortran uses the GNU @code{file:line:column:} format, so the built-in
GNU pattern applies and the cursor jumps to the exact column.

@subsubsection cobc (COBOL)

GnuCOBOL errors look like:

@example
hello.cob:6: error: 'X' is not defined
@end example

Pattern (configured by default):

@example
$@{FILE@}:$@{LINE@}:*
@end example

@noindent
GNU COBOL is GNU-style; xwpe compiles with @code{cobc -x -g}.

@subsubsection pdflatex (LaTeX)

With @code{-file-line-error}, pdflatex errors look like:

@example
./hello.tex:3: Undefined control sequence.
@end example

Pattern (configured by default):

@example
$@{FILE@}:$@{LINE@}:*
@end example

@noindent
xwpe runs @code{pdflatex -interaction=nonstopmode -file-line-error} so
the @code{file:line:} prefix the pattern needs is always present.

@subsubsection Algol 68: two dialects (ga68 and a68g)

@cindex Algol 68
@cindex ga68
@cindex a68g
@cindex stropping

Algol 68 has two free toolchains, and they are @emph{source
incompatible} -- a program written for one will not even parse with the
other, because they use opposite @dfn{stropping} regimes (how reserved
"bold" words and comments are written):

@itemize @bullet
@item
@strong{ga68} -- the GNU Algol 68 front-end (part of GCC).  A native
compiler: @key{F9} Make builds and links a real executable, which
@kbd{Ctrl-F9} runs and gdb debugs.  Uses the @emph{modern} regime.
@item
@strong{a68g} -- Algol 68 Genie, an interpreter with a built-in monitor.
@key{F9} Make runs @code{a68g --norun} as a syntax check; @kbd{Ctrl-F9}
interprets the program.  Uses the @emph{classic} regime.
@end itemize

You do not choose between them: xwpe reads each @file{.a68}/@file{.alg}
file's first lines, detects its dialect, and drives the matching
toolchain for both compiling and debugging.  If only one of the two is
installed, that one is always used.

@noindent
The same ``Hello'' program in each dialect (both ship as samples under
@file{tests/inputs/}):

@need 800
@noindent
@strong{Modern (ga68)} -- lowercase bold words, @code{@{ @}} comments:

@verbatim
{ hello_ga68.a68 -- GNU Algol 68 (ga68), modern stropping. }
begin
   puts ("Hello, GNU Algol 68!'n")
end
@end verbatim

@need 800
@noindent
@strong{Classic (a68g)} -- UPPER bold words, @code{#@dots{}#} comments:

@verbatim
BEGIN
   # hello.a68 -- Algol 68 Genie (a68g), classic stropping. #
   print(("Hello, Algol 68!", new line))
END
@end verbatim

@noindent
At a glance:

@multitable @columnfractions .24 .38 .38
@headitem @tab ga68 (modern) @tab a68g (classic)
@item Bold words @tab lowercase @code{begin}/@code{end}/@code{int}
  @tab UPPER @code{BEGIN}/@code{END}/@code{INT}
@item Comments @tab @code{@{ @dots{} @}} @tab @code{# @dots{} #} or @code{CO @dots{} CO}
@item Print a line @tab @code{puts ("@dots{}'n")} @tab @code{print ((@dots{}, new line))}
@item Toolchain @tab GCC Algol 68 front-end @tab Algol 68 Genie interpreter
@item Make (@key{F9}) @tab compiles + links a binary @tab @code{a68g --norun} (check only)
@item Debug @tab gdb on the binary; breaks at @code{__algol68_main}
  @tab @code{a68g --monitor} on the source
@item Diagnostics @tab GCC @code{file:line:column:} @tab @code{@dots{} in line N} (no file name)
@end multitable

@subsubsection a68g error format

Algol 68 Genie reports type and syntax errors like:

@example
3        INT a := "not an integer";
             1
a68g: error: 1: [] CHAR cannot be coerced to INT in a strong-unit,
in closed-clause starting at "BEGIN" in line 1.
@end example

Pattern (configured by default):

@example
*in line $@{LINE@}*
@end example

@noindent
a68g names no file and reports the enclosing clause's line, so the
cursor jump is best-effort -- read the full diagnostic in Messages.

@subsubsection ga68 error format

ga68 is a GCC front-end, so it emits the standard driver diagnostics
with a @code{file:line:column:} prefix -- the same format as gcc/g++ --
and the error jump lands exactly on the offending token.  Note that
ga68's user entry point is @code{__algol68_main}, not @code{main}; this
matters when debugging (@pxref{Debugging}).

@subsubsection Adding a new compiler

To add support for a compiler not in the default list:

@enumerate
@item
Open @samp{Options @result{} Compiler} (@kbd{Alt-O C}).
@item
Add the language (e.g.@: ``Rust'') with its file extension
(e.g.@: @file{.rs}).
@item
Set the compiler name (e.g.@: @code{rustc}).
@item
If the compiler uses @code{file:line:column:} format, select
@code{GNU} style.  You are done.
@item
If the compiler uses a different format, select @code{Other} and
enter an interpreter string matching the format.  Run the compiler
manually first to see its error output, then construct the pattern.
@end enumerate

@subsubsection Debugging a pattern

If error navigation does not work (Alt-T/Alt-V do nothing after F9):

@enumerate
@item
Check the Messages window -- are compiler errors visible?
@item
Run the compiler manually in a terminal and compare its output
format against your pattern.
@item
Verify the pattern captures @code{$@{FILE@}} and @code{$@{LINE@}}
at minimum.
@item
If the compiler emits blank lines between errors, verify you are
running xwpe 1.6.2 or later (earlier versions truncated output at
blank lines).
@end enumerate

@section Known limitations

@cindex compiler limitations

@itemize @bullet
@item @strong{GNU-style flags}: For @code{GNU} style compilers, xwpe
  automatically adds @code{-c} and @code{-o @var{file}.o} to the
  compile command.  For @code{Other} style compilers, these flags are
  omitted.  If your compiler is GNU-compatible but needs @code{Other}
  style for its error format, add @code{-c} to the Compiler Options
  field manually.
@item @strong{javac column}: javac does not report column numbers in
  its primary error line.  The cursor goes to the start of the error
  line, not the exact position.
@item @strong{Multi-file errors}: error navigation assumes each error
  references a single file.  If the error file is not currently open,
  xwpe opens it automatically.
@end itemize

@noindent
Verified on 2026-06-01 with xwpe @value{VERSION}.
