Using the Shadow Compiler¶
This tutorial is for version 0.8 of the Shadow compiler and may not be accurate for other versions.
The Shadow compiler is required in order to transform written Shadow programs into their executable counterparts. It provides a number of helpful features, including descriptive error-messages and a simple, automated build system. The compiler, along with detailed installation instructions, is available on the Downloads page.
Like many utilities, the Shadow compiler is operated via the command-line. Access to the command-line varies by platform, but is usually available through a terminal emulator. Running the install script included with the Shadow compiler adds its location to the system’s
PATH variable, allowing it to be run from any directory with the command
For simple programs, compilation can be invoked with the following command:
In this case,
Main.shadow is a Shadow source file containing a
main method. This
main method will become the entry point of the program in the resulting executable. The compiler will automatically attempt to resolve any dependencies, both locally and within the standard library.
By default, the resulting executable will bear the same name as the source file (in this case
Main.exe on Windows and
Main on other systems). The executable name can be specified using the
shadowc Main.shadow -o UsefulProgram.exe
When run with the option
--help), the compiler will print a list of all available options and their descriptions. This will also occur if an invalid option or argument is specified, along with a corresponding error message. For reference, the help printout is reproduced below:
usage: shadowc <mainSource.shadow> [-o <output>] [-c <config.xml>] -c,--config <config.xml> Specify optional configuration file If shadow.xml exists, it will be checked -f,--force-recompile Recompile all source files, even if unnecessary -h,--help Display command line options and exit -i,--information Display information about the compiler and exit -n,--nolink Compile Shadow files but do not link -o,--output <file> Place output into <file> -r,--human-readable Generate human-readable IR code -t,--typecheck Parse and type-check the Shadow files -v,--verbose Print detailed information about the compilation process -w,--warning <flag> Specify warning flags
The Shadow compiler ships with tested configuration files. Outside of special cases, most users will not need to worry about creating their own configuration files. If the compiler works as desired on your platform, this section can safely be ignored.
In some cases, it is necessary or convenient to specify additional options in a configuration file. Such cases include cross-compiling (compiling for another platform) and the addition of non-typical include paths (those which the compiler won’t look through on its own). When no configuration file is present, the compiler makes assumptions (either through default values or automatic detection) about the appropriate settings for the given platform. If the file is present but does not make use of all possible options, the same process will be applied to the unspecified fields.
Configuration files are XML-based, and may be passed to the compiler following the option
--config). If the option is not used, the compiler will check for the file
shadow.xml, first in the directory of the given source file and then in the compiler executable’s directory. If neither file exists, the compiler will fall back on default settings. The following is a complete description of all legal tags and attributes within a Shadow configuration file:
Attributes of the
os- The operating system on which the program is being compiled and on which it will run. This determines the choice of system calls to be used by the standard libraries, and may also determine the linker to be used by the compiler (
clang). Any name may be specified, but only those containing the text “Windows”, “Mac”, and “Linux” currently receive special treatment. All others are interpreted as “Linux”.
arch- The addressing mode (32 or 64) used by the target platform’s processor. This information determines pointer size and is used by Shadow’s exception handling system.
target- The target triple used by the LLVM component of the Shadow compiler. See the LLVM Target Triples section for more information
link- The parameters to be passed to the linker.
All of these attributes are optional and will be determined by the compiler if absent. The default values are generally accurate and should not be overridden unless necessary.
The following example demonstrates the general structure of a Shadow configuration file.
<?xml version="1.0" encoding="UTF-8"?> <shadow os="Linux" arch="64" target="x86_64-unknown-linux-gnu"> <system>/home/dave/standardlibs</system> <import>.</import> <import>/usr/local/lib/extralibs</import> </shadow>
In the example above, the user has explicitly specified some platform and directory information. Within the
<shadow> tag, the
os="Linux" attribute ensures that the compiler will use Linux-compliant system calls for standard library functions. The attribute
arch="64" ensures that 64-bit addressing is used. Although the target attribute seems to contain redundant information, it represents a special set of information used by the compiler’s LLVM backend (specifically, the last stages of compilation which output platform-specific machine code). See the section on LLVM Target Triples for more information.
<system> tag is used to specify that the Shadow standard library is located in
/home/dave/standardlibs/. Within this directory, the compiler looks for the directory
shadow/ containing the libraries in question. The tag
<import>.</import> tells the compiler to resolve import statements by searching directories relative to the file being compiled. This tag must always be specified if any other include paths are specified, or the standard libraries (and presumably most user programs) will fail to resolve dependencies. Additional paths, such as the one specified in
<import>/usr/local/lib/extralibs</import> will also be searched when resolving dependencies.
Configuration for Microsoft Windows¶
The configuration file below describes the platform attributes for compiling on (and for) Microsoft Windows.
<?xml version="1.0" encoding="UTF-8"?> <shadow os="Windows" arch="64" target="x86_64-pc-windows-msvc"> <system>.</system> <import>.</import> </shadow>
LLVM target triples¶
During compilation, the Shadow compiler uses a third party tool, the LLVM compiler, to generate the final, platform-specific machine code of an executable. Because the LLVM compiler is an external tool, it requires its own set of platform information to generate valid machine code. During compilation, the contents of the
target attribute (either taken from a configuration file or automatically determined) are handed directly to the LLVM compiler. Thus, the attribute must follow the formatting of an LLVM target “triple.” The following information provides some explanation of how to format these triples:
The canonical form of LLVM target triple is either
unknown is a valid entry in any of these fields. The most critical fields to fill in are those for architecture and operating system.
Many additional options exist for each field. See the beginning of the header file from LLVM’s triple-handling code for a more complete (but still incomplete) listing.
A few useful examples are listed below:
All LLVM tools are capable of automatically detecting the correct triple for a given platform. If LLVM is properly installed, the command
llc --version will display information including the default triple. Linux and macOS installations of Shadow should use package managers to install the LLVM toolchain, and compiled versions of these tools comes with the Windows installation of Shadow.