Operating instruction manual Hilscher Waf Build System Building libraries, applications and netX firmware V1.8

Hilscher Gesellschaft für Systemautomation mbH www.hilscher.com DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public Introduction 2/60

Table of contents

1 Introduction ...... 4 1.1 About this document ...... 4 1.2 List of revisions...... 4 1.3 Terms, abbreviations and definitions ...... 4 1.4 References to documents ...... 4 1.5 Technical information ...... 5 1.6 Limitations ...... 5 2 Overview about Waf ...... 6 2.1 Build system structure ...... 6 2.2 Build Process ...... 7 2.3 Environment objects ...... 7 2.4 Build definition and organization ...... 9 2.5 File system representation ...... 10 3 Usage ...... 11 3.1 Running Waf...... 11 3.2 Preparing a project for Waf ...... 14 3.3 General wscript rules ...... 17 3.4 Selecting / enabling toolchains...... 17 3.5 Compiling a static library ...... 18 3.6 Link a firmware/executable file ...... 20 3.7 Declaring pre-compiled components ...... 21 3.8 Generate a firmware ...... 22 3.8.1 Bootable firmware images for netX10/ netX50/ netX51/ netX52/ netX100/ netX500 ...... 22 3.8.2 Loadable firmware (nxf) for netX10/ netX50/ netX51/ netX52/ netX100/ netX500 ...... 23 3.8.3 Loadable module (nxo) for netX100/netX500 ...... 24 3.8.4 HBoot firmware images for netX90/ netX4000 ...... 25 3.9 Generate a distribution ...... 26 3.9.1 a pre-compiled library distribution ...... 26 3.9.2 Make a firmware file distribution ...... 27 3.9.3 Add arbitrary files to distribution ...... 28 3.10 Preparing a version header file ...... 28 4 Supported toolchains ...... 29 4.1 GCC-based toolchains ...... 29 4.1.1 Common definitions and parameters ...... 29 4.1.1.1 / C++ Source files ...... 29 4.1.1.2 Assembler source files...... 30 4.1.2 Hitex toolchain ...... 31 4.1.3 CodeSourcery toolchain ...... 33 4.1.4 GNU ARM Embedded toolchain ...... 35 4.2 LLVM/Clang-based toolchains ...... 38 4.2.1 Hilscher xPIC toolchain ...... 38 5 Command reference ...... 39 5.1 Common definitions ...... 39 5.1.1 bld. - build commands ...... 39 5.1.2 bld.get_name_prefix – compute task generator name prefix ...... 45 5.2 Build & project structuring ...... 46 5.2.1 .path.ant_glob - make list of files using pattern search ...... 46 5.2.2 .autorecurse - recursively process subdirectories ...... 47 5.2.3 .load - load waf extension modules ...... 48 5.2.4 .recurse - load wscript file from subdirectory ...... 49 5.3 Declarations ...... 50 5.3.1 bld.externalcomponent - declare pre-compiled library ...... 50 5.3.2 bld.sdkcomponent - declare a SDK ...... 51 5.4 Compilation and linking ...... 52 5.4.1 bld.program - link an application / executable ...... 52 5.4.2 bld.stlib - build a static library ...... 53 5.5 Firmware generation ...... 54 5.5.1 bld.bootimage - generate a netX bootimage ...... 54 5.5.2 bld.firmware - generate a loadable firmware ...... 55

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Introduction 3/60 5.5.3 bld.module - generate a loadable module ...... 56 5.5.4 bld.generate_hboot_image - generate a hboot image ...... 57 5.5.5 bld.generate_netx90_intflash2_image - generate a netx90 application image ...... 58 5.6 Distribution ...... 59 5.6.1 bld.install_as - copy file to distribution with renaming ...... 59 5.6.2 bld.install_files - copy multiple files to distribution ...... 59 6 Appendix ...... 60 6.1 List of tables ...... 60 6.2 List of figures ...... 60

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Introduction 4/60 1 Introduction 1.1 About this document Waf is a Python-based framework for configuration, compiling and installing of components. Based on this framework Hilscher has implemented a build system for generation of program libraries, applications and netX firmware. This document describes the usage of the Hilscher Waf build system and some internals. This document describes only features relevant for standard usage of the Hilscher Waf build system. It does not describe rarely used Waf features (e.g. build visualization). Thus the Hilscher Waf build system might be able to perform additional tasks and implement more feature than described here but: The functionality of any task or feature not described within this document cannot be guaranteed and might disappear on updated versions of Hilscher Waf build system silently. It is strongly recommended to not rely on such undocumented functionality. The Hilscher Waf build system can be extended using additional modules. (E.g. Static Code Analysis Module) These extensions might define additional command line arguments, commands, tasks or artefacts. Description of these modules is not part of this document but found in the corresponding extension module documentation.

1.2 List of revisions

Rev Date Name Chapter Revision 2 2018-01-12 AM all Major rework of document. Description extended. Table 1: List of revisions

1.3 Terms, abbreviations and definitions

Term Description Waf Build Framework Table 2: Terms, abbreviations and definitions

1.4 References to documents This document refers to the following documents: [1] The Waf Book, URL: https://waf.io Table 3: References to documents

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Introduction 5/60 1.5 Technical information Waf build system version The Hilscher Waf Build System was created on top of Waf build system V1.6.11 Integrated Python Interpreter A stripped down version of C-Python V2.7.3 was integrated into the Waf tool package provided by Hilscher.

1.6 Limitations Currently there are no know limitations for the Waf build system.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Overview about Waf 6/60 2 Overview about Waf 2.1 Build system structure Typically, Waf build system based projects ship the build system together with the project and require a python interpreter to be installed on the system. Hilscher has modified this structure and integrated the original Waf build system with a python interpreter into a single package. The python interpreter has been stripped down for this to provide only minimum requirements. This allows to distribute the Hilscher Waf build system as a single tool without additional external software requirements. In contrast to that, all Hilscher extensions and modifications to Waf are shipped with the project itself. (Typically within subfolder Waf) This ensures that no unexpected project issues arise when updating the (external) Waf build tool: All settings are provided by the Waf extension scripts within the project itself, so no unexpected changes to flags, memory timings etc. can occur. The projects build definitions itself are contained in wscript files. These files define the build targets, used toolchains and the dependencies between the different targets. Precompiled libraries provided by Hilscher also ship with a wscript file which provides definitions for the precompiled libraries. Typically the project folder structure will be as shown in following table:

Base Path Content Description Project/ Project directory itself wscript Top level wscript defining the toolchain requirements, global settings and structure of project artefact distribution Project/Components/Compon A source software component used in the project. entA Includes Subfolder containing include files Sources Subfolder containing source files wscript wscript file defining the generation of the component artefacts Project/Components/ExtCom A precompiled software component used in the project ponentB Includes Subfolder containing public include files. Lib Subfolder containing pre-compiled library files wscript wscript file defining the precompiled software libraries Project/HBoot Folder containing hboot resources required to build netX90/netX4000 firmwares sniplib Snippet libraries for hboot compiler Project/Targets/TargetC An executable/firmware target generated by the project Includes Target specific includes Sources Target specific source files wscript wscript file defining the generation of the target artefacts. Project/Waf Hilscher Waf extension folder, containing default Waf definitions and extensions by Hilscher. hilscher_netx.py Waf script files … Project/build … This is the default output folder where Waf places all defined and intermediate build artefacts. The folder can be renamed in the top level wscript file and will be created by Waf automatically upon build if it does not exists. Project/dist … This is the default distribution folder where Waf places the project distribution as defined by wscript files. The folder will be created by Waf automatically if it does not exists and can be changed to other location using command line argument with Waf tool. Table 4: Typical file structure of a project using Hilscher Waf build system

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Overview about Waf 7/60 2.2 Build Process When running the Waf build system, the build process is split into three separate stages. 1. In the Option stage the Waf tool evaluates command line arguments. At the very beginning of that stage Waf loads the projects top level wscript file and invokes the option() function within that script in order to get knowledge about project specific command line options and to load extension command line options. Finally, command line arguments are evaluated and validated. 2. After processing the command line options, the optional configure stage takes place. In that stage Waf locates external applications like , linkers, script interpreters or other tools. Based on that paths Waf builds up Environment objects which are basically a collection of build variables and settings. At the end of this stage Waf stores the Environment objects into folder build/c4che. 3. Finally Waf executes the build stage(s). Multiple build stages can occur depending on the command line arguments. Each build stage carries out its associated actions and updates the generated files. Waf tries to optimize and speed up the build stages by skipping already up to date files. For that purpose Waf analyses and uses dependencies of source files and generated files.

2.3 Environment objects Waf uses environment objects to manage paths, settings and parameters associated with a build stage. These environment object use inheritance of variables from parent environment object. That means variables set on a parent environment object are also available in child environment objects. This is shown in the following figure:

Figure 1: Environment object relations

It is important to understand, that, when at build time VAR_A is modified in Root Env, this modification immediately affects all child environments which do not override this variable with own setting. This must be considered when modifying parent environment objects within the wscript files.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Overview about Waf 8/60 Note: Besides from the above statements, Waf has the possibility to detach environments from each other. That means, the child – parent relationship is removed and all variables from parent object are merged into child object. Afterwards both environment objects are independent from each other.

Typically Waf based build systems generate all environment objects in configure stage. When at the end of this stage the environment objects are stored, detached environment objects are created, that means the parent - child relation is removed while all variables from parent objects are added to the child objects if they are not defined within the child object itself. At the beginning of a build stage these detached environments are loaded but stay detached. Thus modifying a (previously) parent environment object from within a build stage does not affect the variable values retrieved from a (previously) child environment object. Hilscher uses the environment objects in a slightly different manner than typical Waf based build systems: Only basic environment preparation is done in configure stage while most of the environments are prepared in build stage. This is shown in the next figure.

Figure 2: Hilscher Waf build environment structure

This figure shows that between configuration and build stage the relation between the Toolchain Envs and the Root Envs are removed and variables are copied. The Root Env still exists in build stage, but modifying it will not change any variable in Toolchain Env, Architecture Envs and Target Envs. The picture also show that the Hilscher Waf Buildsystem will generate Architecture Environments for each Chip and a Build Target Environment for each build target defined by build commands in the wscript files. In this example, if a new variable is added to the CodeSourcery Environment, it will be propagated and available for Build Targets B, C and . In contrast to that, if a variable is added to the CodeSourcery netX51 Environment, it will be propagated and available for Build Targets C and D.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Overview about Waf 9/60 2.4 Build definition and organization Waf based build systems organize the build mainly using the following three items: The smallest entity of a build process is a task. A task consists of a single step like executing external commands: “compile a.c to a.o”, “link a.o to a.exe using lib.a” or running some python code defined by Waf itself. The execution order of tasks is automatically managed using the tasks input, output and additional file dependencies and tasks might be skipped if the output files are already up to date. Tasks are processed in arbitrary order and in parallel if they are not constrained by dependencies. Multiple tasks belonging to one target are typically created by a task generator. A task generator evaluates input parameters and paths, generates filenames for intermediate files and creates all tasks required to build a certain target. Internally, when processing a task generator, Waf sequentially invokes functions on the task generator object. These functions prepare environment objects, handle dependencies and create the tasks. Which functions are to be executed is controlled by the features parameter of a task generator. Each task generator is assigned a name which can be used by other task generators to include its outcome. E.g. a firmware task generator can refer to a static library task generator to use the library in linking step and use it’s include files). The name is used internally only and might be different from the target file name. Pre-compiled libraries are represented using dummy task generators which do not create any task but carry the information about the precompiled libraries with them. Waf processes task generators in arbitrary order, but not in parallel. The task generators are defined in the build() function within wscript files. This step is typically wrapped in a build/configure command which internally performs preprocessing of parameters and creates one or more tasks or task generators. Most of the commands arguments are directly passed to the task generators. The build/configure commands are run at the very beginning of the build stage. They are always run in the order they appear in the wscript file or the recursion occurs. Typically the projects top level wscript defines a recursion into subfolders to process subsequent wscript files.

Note: It is important to understand, that at the very beginning of each build stage, the build() function of the wscript files are evaluated and all task generators and tasks are defined but not yet run. After that, Waf starts with processing of the task generators which define more tasks. Finally the tasks are executed conditionally if required.

In order to allow seamless integration of components which might be providing additional artefacts for targets not used in current project or handle missing dependencies the Hilscher Waf build system implements automatic deactivation of task generators. Such a deactivation of a task is not considered an error in all cases. In any case, if a task generator is disabled by Hilscher Waf build system, a warning printout will be generated. In following cases a task generator is disabled automatically without error: When a task generator depends through its use argument on another task generator which has been deactivated previously. When the compiler toolchain required by the task generator using the toolchain argument is not available.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Overview about Waf 10/60 2.5 File system representation Waf based build system manage the file system using Node objects. Each file or directory is represented by a node object. These node objects are organized in tree structure to represent the file system structure. All functions provided from Waf use such node objects internally, therefore file system functions return node objects or a list of node objects but never paths. Arguments and parameters to function can be given as paths and converted automatically to node objects for internal usage.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 11/60 3 Usage This chapter describes typical use cases and their implementation using the Hilscher Waf build system. For a reference description of the various commands used in the following please refer to section 5. 3.1 Running Waf The Waf build system must be invoked from the folder which contains the project’s root wscript. Global arguments and options of Waf command are described below. Waf relies on environment variables to locate external tools and compilers. The following settings are recommended: The PATH variable should include the folder of the Waf tool. This folder contains the waf.bat file. If required by the project, the variable must contain the path to a python interpreter (python.exe) and the subversion executable (svn.exe). These tools might be required when building firmwares.

Optionally, the variable can contain the path to the executables of the Hitex toolchain (arm-hitex-elf- gcc.exe) and the CodeSourcery toolchain. (arm-none-eabi-gcc.exe).These paths will be used as fallback if the toolchain related environment variables are not set. The PATH_GNU_ARM variable is interpreted as the location of the Hitex Compiler toolchain. Set the variable to the installation directory of the Hitex compiler toolchain. (This directory contains the file “bin/arm-hitex-elf.gcc.exe”) If the variable is not set, Waf will try to lookup the Hitex compiler toolchain via PATH variable. The CS_PATH variable is evaluated to find the CodeSourcery Toolchain. The variable shall point to the installation directory. (This directory contains the file “bin/arm-none-eabi-gcc.exe”). If the variable is not set, Waf tries to locate the toolchain using the windows registry, and if that fails too, the toolchain will be located using the PATH environment variable. In order to use the GCC ARM Embedded toolchain the variable GCC_ARM_PATH must be set to point to the toolchains installation directory. (This directory contains the file “bin/arm-none-eabi- gcc.exe”) This variable must be set if the project uses this toolchain. There is no fallback using the windows registry or the PATH environment variable. The PATH_LLVM_XPIC environment variable is used to locate the Hilscher xPIC toolchain. The variable should point to the installation directory. (This directory contains the file “bin/xpic-llvm.exe”) If the variable is not set, the executable will be looked up in the directories specified in PATH environment variable.

Note: Waf can be extended with additional modules. These modules may define additional build options and commands. For a description of these please refer to the corresponding module documentation.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 12/60 The command is defined as follows: Synopsis waf.bat [options] command… Description command The command argument is mandatory and specifies which build steps/stages shall be run. Multiple command arguments can be specified and will be executed by in order they appear on the command line. The following commands are defined The configure command will run the configure stage and locate and prepare the toolchains as defined by the projects top level wscript. This command must always be run before the project is build the first time and when any wscript within the project changes. It is strongly recommended to always run the configure command together with the build commands. The build command generates all artifacts defined by the project, including but not limited to object files, static libraries, linked applications, binary images and firmware files. This output is typically generated within the build/${condition} subfolder of the project. The install command is an extension of the build command. In addition to the actions carried out by the build command some or all of the artifacts are deployed into a distribution folder structure. The default distribution folder is the dist subfolder within the project. The clean command can be used to remove all build artefacts without removing the build subfolder while the distclean command will remove also the build subfolder. A compressed tar archive can be generated from project using the dist command. Please note that this command is an original Waf build system command and might not integrate properly with Hilscher Waf. It is recommended not to use this command. The list command does not generate any build output but prints a list of all a artefacts defined by the wscripts in this project. options The optional options parameter is defined as follows:

--conditions= The conditions options is used to choose between three sets of predefined build options which affect the code generation. The build options may depend on the compiler and build target, but in general the following settings will be used: The debug conditions disable all kind of optimization and enable debugging information. With release conditions the generated code will be optimized for size and no debug information will be generated. The debugrel condition uses same optimization settings as release conditions but additionally enables debug information. When the option is not given, the conditions option default will be the release configuration.

--destdir=destination_directory Change the destination directory for generating the distribution folder. Defaults to subfolder dist within project folder.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 13/60 --dump-environment=variables,… When this option is given, a text file containing the final values of build variables is generated along with the build artefacts. The information will be broken down to each single task exectued. Commonly used variables are: CFLAGS, CXXFLAGS, LINKFLAGS, DEFINES, LIB, INCLUDES and STLIB.

--generate-report=reports,… Along with the build process reports can be generated for certain build artefacts. This parameter is a comma separated list of values selecting which reports to generate. The following values can be used: • all: Generate all known reports • size: Generate a report of the allocated size of functions, global variables and size statistics of an elf file. This is useful when the firmware size shall be optimized.

-j jobs, --jobs=jobs Specifies how many processes should be run in parallel. Whenever possible Waf tries to run jobs in parallel to speed up the build process. The default value for this option is the number of CPUs on the build system.

--targets=target,… If this option is specified only the specified targets and their dependencies will be build. By default all targets defined in the project are build.

Examples Executing the command $ waf.bat -–conditions=debug configure build within the project folder will generate a debug build where the build artefacts are located in build/debug subfolder within the project. The command: $ waf.bat configure install generates a release distribution in dist subfolder within the project.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 14/60 3.2 Preparing a project for Waf This section describes basic steps to setup a project for uses with the Hilscher Waf build system. While some of the steps are identical to standard Waf based builds, some Hilscher specific settings have to be made. The folder/file structure used in the following description is based on Hilscher definitions for the development. These might not fully apply in all cases. The following listing shows which steps are required to prepare the project for use with the Waf build system: 1. A copy of the Hilscher Waf build scripts shall be added to the project as a subdirectory. (Typically subfolder ‘Waf’ is used). The file structure should look as follows, depending on the Hilscher Waf version additional files or subdirectories might exists within the Hilscher Waf build scripts directory:

MyProject/Waf MyProject/Waf/__init__.py MyProject/Waf/hilscher_dist.py MyProject/Waf/hilscher_extras.py MyProject/Waf/hilscher_firmware.py MyProject/Waf/hilscher_netx.py MyProject/Waf/hilscher_toolchains.py MyProject/Waf/… It is good practice to provide this subfolder using a change management system and include it into the project as external (subversion) or submodule. (git) 2. A top level wscript file with path “MyProject/wscript” shall be created which initializes basic settings and recurses into subdirectories to locate and load other wscript files. The initial content of this file should be as follows:

top = '.' out = 'build'

# List of toolchains used by the project. This variable should # be set according the toolchains used by libraries/firmwares # generated by this project REQUIRED_TOOLCHAINS = [ # "hitex", # Legacy netX50/netX100/netX500 "codesourcery", # netX10/netX50/netX51/netX52/netX100/netX500 # "gccarmemb", # netX90/netX4000 # "llvm-xpic", # xPIC in netX10/netX51/netX52/netX90/netX4000 ]

def options(opt): # prepare waf.bat command line arguments from modules # additional extensions might be added here opt.load('hilscher_netx hilscher_firmware hilscher_extras', tooldir='Waf')

def configure(conf): # load basic Hilscher waf extension modules # additional extensions might be added here conf.load('hilscher_netx hilscher_firmware hilscher_extras', tooldir='Waf')

# load subdirectory wscripts and run their configure() function # if available. Do not recurse into “dist” or “build” subfolder. They # are generated upon build and might contain generated wscripts

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 15/60

conf.autorecurse(mandatory = False, excl= ["dist", "build"])

def build(bld): # load subdirectory wscripts and run their build() function # fails if wscript files without build() function is found # Do not recurse into “dist” or “build” subfolder. They # are generated upon build and might contain generated wscripts bld.autorecurse(excl= ["dist", "build"])

3. For libraries and targets of the project itself wscript files need to be created. These files define the artefacts of the project and how they are generated. If the default Hilscher project file system structure is used this might look as follows:

MyProject/wscript MyProject/Components/MyApp/Includes MyProject/Components/MyApp/Sources MyProject/Components/MyApp/wscript MyProject/Components/rcX_V2.1/… MyProject/Components/… MyProject/Targets/MyFirmware/Sources MyProject/Targets/MyFirmware/wscript MyProject/Targets/MyFirmware/netx100.ld Hilscher supplied code or pre-compiled libraries must be placed within the project structure as well. (E.g. rcX , protocol stack libraries) These are usually shipped with wscript files setting up the library or code for use with Waf. For project components a wscript file’s build() function will typically compile the component into a library which can later be used by targets or other components. Such a wscript file might be started from the following template:

def build(bld): # compute prefix for names “//” # for rcX independent libraries # lib_prefix = bld.get_name_prefix(toolchain = "codesourcery")

# compute prefix for names “//rcX_V2.1/” # for rcx dependent libraries lib_prefix_rcx21 = bld.get_name_prefix( toolchain = "codesourcery", suffix="rcX_V2.1")

bld.stlib( target = "myapp", # library file will be named libmyapp.a name = lib_prefix_rcx21 + "myapp", # task generator name toolchain = "codesourcery", platform = "netx", description = "My Application library", source = [ "Sources/MyApp_Body.c", "Sources/MyApp_Resources.c", "Sources/MyApp_Process.c", "Sources/MyApp_Functions.c", ], includes = [ Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 16/60

"Includes" ], defines = [ "RX_COMPILE_CPU_INDEPENDENT" ], use = [ 'arm-none-eabi/*/rcX_V2.1/rcx_sdk' ], export_includes = [ "Includes" ], ) The firmware for a target is generated by a target wscript file with content similar to following template:

def build(bld): bld.program( target = 'nxio', # output elf will be named nxio.elf platform = 'netx500', toolchain = 'codesourcery', source = [ 'Sources/config.c', ], use = [ 'arm-none-eabi/*/rcX_V2.1/myapp', # link using myapp task generator 'arm-none-eabi/*/rcX_V2.1/rcx_mid',# link in rcx operating system 'arm-none-eabi/*/rcX_V2.1/rcx_vol', 'arm-none-eabi/*/rcX_V2.1/rcx_netx100', 'arm-none-eabi/*/rcX_V2.1/rcx', ], linkerscript = 'netx100.ld', features = ['buildstamp', 'libsused'] )

bld.bootimage( target = 'netx.rom', # output image file will be named netx.rom name = 'nxio.rom', # name of this task generator is nxio.rom description = 'Boot image for NX-IO', use = ['nxio'], # image should be build from task generator # named “nxio” which is the bld.program from # above (if name is omitted the value for the # task generator’s name is equal to the value # of the target argument BOOTBLOCKERFLAGS = [ # Flags for bootimage creation with '-ct', 'netx500', # bootblocker tool. Waf integrates its '-s', 'SPI_gen_10', # own bootblocker implementation but '-d', 'SD_MT48LC2M32B2', # emulates the command line flags from ], # original tool )

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 17/60 3.3 General wscript rules When writing a wscript file, the following rules apply: wscript files are written in the python script language as Waf itself is. Thus special care must be taken regarding the indentation of a statement. In python language the beginning or end of a block (function, conditional, loop) is marked by indentation. All statements belonging to a block must be using the same indent after the block has been opened by the corresponding python keyword. The amount of indent does not matter, for readability four spaces are considered good practice. Lines following an opening brace are considered part of the statement of the opening brace itself until the corresponding closing brace is encountered. Here indent has no special meaning. Opening braces must occur on the same line as the statement they belong to, they must not be moved to the next line. If required lines can be continued using the backslash (‘\’) at the end of the line Multiple build commands within a single wscript file must be put into a single build() function. It is not possible to define multiple functions with same name within a single wscript file. Beware that this is not considered as a syntax error in python. The last definition found just overwrites all previous definitions. Paths specified within a wscript file are always relative to the directory containing the wscript file itself. Waf build system supports modular projects with separate wscript files for components and/or targets. Waf does not automatically search and load all wscript files within a project. For that purpose the functions .recurse - load wscript file from subdirectory and .autorecurse - recursively process subdirectories shall be used

3.4 Selecting / enabling toolchains Waf based build systems support building targets using multiple toolchains at the same time. Thus a project with different target architectures can be built in a single step. By default the Hilscher Waf build system will check availability of the hitex and codesourcery toolchain. If other toolchains or combinations of them are required by the project the required toolchains shall be specified in top level wscript using the REQUIRED_TOOLCHAINS parameter: top = '.' out = 'build'

# List of toolchains used by the project. REQUIRED_TOOLCHAINS = ['codesourcery', ‘gccarmemb’] …

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 18/60 3.5 Compiling a static library A static library is generated using the build command stlib. Static libraries can be an artefact of the project to be used by other projects or used within the project itself to group parts of the application. They also help to avoid multiple compilation of same file within one project if the files are used by multiple targets of a project and compiled with same settings all the time. The following example shows how to declare a static library in a wscript file. The declaration must occur within the build() function in the wscript file. Besides the static library itself an additional “SDK” task generator should be defined if the static library is a dependency of other libraries: def build(bld): # compute prefix for names “//” # for rcX independent libraries # lib_prefix = bld.get_name_prefix(toolchain = "codesourcery")

# compute prefix for names “//rcX_V2.1/” # for rcx dependent libraries lib_prefix_rcx21 = bld.get_name_prefix( toolchain = "codesourcery", suffix="rcX_V2.1")

# a rcx dependant static library SDK bld.sdkcomponent( name = lib_prefix_rcx21 + "mylib_sdk", # SDK task generator name description = "My Static library SDK", export_includes = ['Includes'], use = [ 'arm-none-eabi/*/rcX_V2.1/rcx_sdk', ], )

bld.stlib( target = "mylib", # library file will be named libmylib.a name = lib_prefix_rcx21 + "mylib", # task generator name toolchain = "codesourcery", platform = "netx", description = "My Static library", source = [ "Sources/MyLib_Source1.c", "Sources/MyLib_Source2.c", "Sources/MyLib_Source3.c", ], includes = [ "Includes" ], defines = [ "RX_COMPILE_CPU_INDEPENDENT" ], use = [ lib_prefix_rcx21 + "mylib_sdk", # refer to our own sdk ], ) This static library can then be used by another static library as shown in the following wscript file listing. The library in the following is not used by any other library but only linked into the final firmware, thus no SDK is declared.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 19/60 def build(bld): lib_prefix_rcx21 = bld.get_name_prefix( toolchain = "codesourcery", suffix="rcX_V2.1")

bld.stlib( target = "myapp", # library file will be named libmyapp.a name = lib_prefix_rcx21 + "myapp", # task generator name toolchain = "codesourcery", platform = "netx", description = "My Application library", source = [ "Sources/MyApp_Source1.c", "Sources/MyApp_Source2.c", "Sources/MyApp_Source3.c", ], includes = [ "Includes" ], defines = [ "RX_COMPILE_CPU_INDEPENDENT" ], use = [ "arm-none-eabi/*/rcX_V2.1/mylib_sdk", # refer to sdk defined above "arm-none-eabi/*/rcX_V2.1/protocol_sdk", # refer to Hilscher library sdk ], )

A static library might depend on other libraries. Such dependencies are declared with the use argument. Its value is a list of names of other task generators which this task generator depends on.

Note: When declaring static libraries it is recommended to not refer to other static library task generators directly but to their associated SDK task generators. This helps to solve link library order issues in the final firmware linking step.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 20/60 3.6 Link a firmware/executable file The command program() builds a linked firmware or executable file. This file can be either loaded into the target using a debugger or just executed. The following listing shows an example declaration of a netx51 firmware using rcX V2.1: def build(bld) lib_prefix_rcx21 = bld.get_name_prefix( toolchain = "codesourcery", suffix="rcX_V2.1")

bld.program( target = 'myfirmware', # output file will be named myfirmware.elf name = lib_prefix + 'myfirmware', # used later when generating a bootable # image platform = 'netx51', toolchain = "codesourcery", description = 'My firmware for netX51', source = [ "Sources/config.c", ], use= [ ‘arm-none-eabi/*/rcX_V2.1/mylib', ‘arm-none-eabi/*/rcX_V2.1/myapp', 'arm-none-eabi/*/rcX_V2.1/rcx_mid', 'arm-none-eabi/*/rcX_V2.1/rcx_vol', 'arm-none-eabi/*/rcX_V2.1/rcx_netx51', 'arm-none-eabi/*/rcX_V2.1/rcx', ], linkerscript = "netX51_sdram.ld", )

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 21/60 3.7 Declaring pre-compiled components In some case it might be required to integrate pre-compiled components into a project. E.g libraries provided by external sources. For this use case, the libraries and header files should be placed in a directory structure like shown in the following example MyProject/Components/ExtCom/Includes MyProject/Components/ExtCom/Includes/ExtCom.h MyProject/Components/ExtCom/Lib/libextcom.a A manually created wscript in MyProject/Components/ExtCom/wscript Provides the necessary information to Waf. The wscript should declare SDK task generators for header files and external library task generators as shown in following example: def build(bld): bld.sdkcomponent( name = "arm-none-eabi/*/extcom_sdk", description = "My pre-compiled library SDK", export_includes = ['Includes'], use = [], )

bld.externalcomponent( name = "arm-none-eabi/*/extcom", target = "extcom", # Extended to filename libextcom.a path = "Lib/", # Path to look for library file description = "My pre-compiled library ", version = "4.0.0.3", # declare version of pre-compiled library export_includes = ["Includes",], )

Note: If the pre-compiled library is created in context of another project also using the Hilscher Waf build system it is not required to manually create the project distribution file structure and wscript file. For such a case the Hilscher Waf build system provides functionality to generate a project distribution and wscript file.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 22/60 3.8 Generate a firmware The generation of the firmware image depends on the platform and kind of firmware to be generated. 3.8.1 Bootable firmware images for netX10/ netX50/ netX51/ netX52/ netX100/ netX500 A bootable firmware image is loaded by the netX rom loader implemented in netX ROM code. It is typically loaded from serial flash but can also started from MMC card formatted with FAT file system. In the latter case the firmware image is placed as file name “netx.rom” in root directory of MMC card. Historically the bootable firmware image was created by a tool called bootblocker. This functionality has been integrated into the Hilscher Waf build system itself. The name of the command and its arguments are still based on this tool. The bootimage itself is created from a previously build elf image.

Note: In order to build a working boot image from a linked elf file, the elf file must obey some rules. These have impact on the linkerscript.

The following listing shows an example how to generate a bootable firmware image for an NX-IO board. Details about bootimage/bootblocker arguments can be found in bootblocker documentation. Def build(bld): bld.bootimage( target = 'netx.rom', # output image file will be named netx.rom name = 'nxio.rom', # name of this task generator is nxio.rom # only required if different boot images with same target # name are defined description = 'Boot image for NX-IO', use = [ 'arm-none-eabi/*/rcX_V2.1/myfirmware'], # reference to elf/application # the bootimage shall be build # from BOOTBLOCKERFLAGS = [ # Flags for bootimage creation with '-ct', 'netx500', # bootblocker tool. Waf integrates its '-s', 'SPI_gen_10', # own bootblocker implementation but '-d', 'SD_MT48LC2M32B2', # emulates the command line flags from ], # original tool )

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 23/60 3.8.2 Loadable firmware (nxf) for netX10/ netX50/ netX51/ netX52/ netX100/ netX500 A loadable firmware is used in a two stage boot process. After Power On the netX rom loader loads and executes the second stage loader (e.g. from serial flash, via DPM…). The second stage loader initializes some of the netX hardware (e.g. SDRAM). Afterwards it locates a loadable firmware file in file systems on permanent storage devices (flash based boot mode) or expects a loadable firmware via DPM (ram based boot mode). If a firmware was found or provided it will be loaded and executed. Loadable firmware files are identified by file extension “.nxf”. The build process of such a file is strongly coupled to the linking process of the firmware. Thus the build command is derived from the firmware link step and replaces this step also. The following listing shows how a loadable firmware file can be generated: def build(bld) bld.firmware( target = 'myfirmware.nxf', # firmware file will be named myfirmware.nxf # linked elf file will be named myfirmware.elf platform = 'netx51', toolchain = "codesourcery", description = 'My loadable firmware for netX51', source = [ "Sources/config.c", ], use= [ ‘arm-none-eabi/*/rcX_V2.1/mylib', ‘arm-none-eabi/*/rcX_V2.1/myapp', 'arm-none-eabi/*/rcX_V2.1/rcx_mid', 'arm-none-eabi/*/rcX_V2.1/rcx_vol', 'arm-none-eabi/*/rcX_V2.1/rcx_netx51', 'arm-none-eabi/*/rcX_V2.1/rcx', ], linkerscript = "netX51_sdram.ld", BOOTBLOCKERFLAGS = [ # Flags for bootimage creation with '-ct', 'netx51_52', # bootblocker tool. Waf integrates its '-s', 'SPI_gen_10', # own bootblocker implementation but '-d', 'SD_MT48LC2M32B2-7IT', # emulates the command line flags from ], # original tool ) In contrast to standard linking build command the target name is the file name of the loadable firmware name. The name of the linked elf file will be derived from that name by replacing the extension. As loadable firmwares contain a boot header identical to a bootable firmware image, the integrated bootblocker tool is also run and the BOOTBLOCKERFLAGS argument must be specified.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 24/60 3.8.3 Loadable module (nxo) for netX100/netX500 A loadable module is dynamically linked firmware module which is loaded and executed by an operating system running on the netX. In order to use a loadable module, the netX must be running a base firmware containing the operating system which in turn can load, link and execute the firmware module. Generation of a loadable module is a more complex process which requires various information and a special prepared linker file. The following example shows how to generate a loadable module: def build(bld): bld.module( target = 'mymodule.nxo', # module file will be named mymodule.nxo platform = 'netx100', toolchain = "codesourcery", description = 'My loadable firmware for netX51', source = [ "Sources/config.c", ], fileheader_source = ‘Sources/FileHeader.c”, taglist_source = ‘Sources/Taglist.c”, use= [ ‘arm-none-eabi/*/rcX_V2.1/mylib', ‘arm-none-eabi/*/rcX_V2.1/myapp', 'arm-none-eabi/*/rcX_V2.1/rcx_module_netx100', 'arm-none-eabi/*/rcX_V2.1/c_module', ], linkerscript = "nxo.ld", ) Note: Loadable modules are usually not linked with default operating system libraries. Instead special module libraries must be used. Due to the recursive nature of the use argument it might still happen that default operating system libraries are used in linking step. This will break the linking step of a loadable module. Such a problem arises if a static library referenced by the module depends on an operating system library instead of the operating systems SDK. Therefore it is strongly recommended that static libraries never depend on other static libraries but only on their associated SDK task generators. This avoids such unexpected linking problems.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 25/60 3.8.4 HBoot firmware images for netX90/ netX4000 For netX90 and netX4000 chipsets a new format for bootable images has been defined. This format is called “hboot”. The following two hboot file formats are known:  netX90 communication side images and netX4000 images: This (full) hboot image contains chunks of various content, e.g. executable code, hardware parameters and more. In order to create such a hboot image, the HBoot compiler has been integrated into the Hilscher Waf build system.  netX90 application side image: For the application side of the netX90 chipset a simplified boot image has been defined allowing a simple one to one memory to file mapping. This file has a fixed location of interrupt vector table and an image header (for checksumming the firmware). The waf build system contains a small helper tool to generate such an image. The generation of a full hboot boot image is controlled by an hboot xml file which describes the firmware structure. A description of this file format can be found in hboot manual. The following example shows a simple file for an application using the communication CPU (Cortex R7) and DDR ram:

If the hboot.xml file imports snippets from a sniplib, the path to the snippet library must be passed to the hboot command as well. The previous shown hboot xml file is used in the build command as follows: def build(bld): bld.generate_hboot_image( target = 'netx.rom', # output file name name = 'netx4000/myfirmware_ddr', # name of this task generator netx_type = 'netx4000', # netx type to generate the # firmware for hboot_xml = 'netx4000_ddr600_hboot.xml', # hboot xml describing the firmware sniplib = '../../HBoot/sniplib', # path to snippet library use = [ 'armv7r-none-eabi/*/rcX_V2.1/myfirmware', # bld.program target to use ], ) Note: The firmware structure defined in hboot xml file and the linker description files used to generate the input elf files of the hboot command must match in order to generate a working bootable image.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 26/60 The simplified netX90 application side firmware image can be created as shown in the following example: def build(bld): bld.generate_netx90_intflash2_image( target = 'netx90_app.bin', use = ['netx90_app.elf'], ) Note: The linker description file must written properly to correctly locate the interrupt vector tables, the file header and the application in the image

3.9 Generate a distribution The artefacts defined in project can be deployed in a structured manner within distribution directory by running the Waf tool using “install” command line argument. By default the dist subdirectory of the project is used as destination for distribution output. The location of the distribution directory can be changed using command line arguments when invoking the Waf build system. In order to assists with generation of the project distribution, special build commands have been defined according to Hilscher definitions for distribution folders.

3.9.1 Make a pre-compiled library distribution Pre-compiled library distributions are used when a projects artefacts like static libraries and public header files are integrated into other project. For that purpose the artefacts to be distributed are placed in a directory structure and a wscript declaring the artefacts is generated. This procedure can be automated as shown in the following example listing: def build(bld): bld.distribute_lib( install_path = 'SVN', # Distribution will be generated in directory # “/SVN/”. A. wscript file is # generated in /SVN/wscript

use = [ # all artefacts to include in generated wscript # must be declared by use argument. Static libraries # will be automatically copied to location # /SVN/Lib// # // 'arm-none-eabi/*/rcX_V2.1/mylib_sdk', 'arm-none-eabi/*/rcX_V2.1/mylib',

'arm-none-eabi/*/extcom_sdk', 'arm-none-eabi/*/extcom', ], dist_includes = [ # Include files to be distributed must be explicitly # listed here. Files will be searched in include folders # defined by the distributed task generators. 'MyLib_Public.h', ], ) Such a distribution command is typically placed within the projects top level wscript, as the distribution is a project specific and not component/target specific definition. The distribution command can also be used to re-distribute pre-compiled libraries used by the project itself.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 27/60 3.9.2 Make a firmware file distribution Firmware distributions require a more flexible distribution structure. For that purpose an own command has been defined which extends the use argument with a destination directory. The following listing shows how firmware files could be distributed using the Hilscher firmware distribution file system structure: def build(bld): bld.distribute_firmware( install_path = 'NXF', # Distribution will be generated in directory # “/NXF/”.

use = [ # all artefacts to distribute must be declared # by use argument. This command extends the use argument # to be a list of referenced names and their # distribution location: # (“task_generator”,”distribute_folder”), # The firmware files will be copied to location # /NXF/Firmware/ # /target_filename>

('myfirmware.nxf', 'NXIO/netx100/'), ], dist_includes = [ # Include files to be distributed must be explicitly # listed here. Files will be searched in include folders # defined by the distributed task generators. 'MyFw_Public.h', ], ) In addition to distributing the firmware files itself, the used-libs firmware meta information file will be copied too, if the firmware is built with the “libsused” feature. Similar to library distribution commands, this command is typically used in the top-level wscript file of the project.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Usage 28/60 3.9.3 Add arbitrary files to distribution In many case it is required to add additional files like device description files, documentation or example to a projects distribution. For that purpose the build commands install_files and install_as are available. They can be used follows: def build(bld): bld.install_files( "DeviceDescription", # Files will be added to directory # /DeviceDescription [ 'Misc/MyDevice.xml’, # Files are taken from /Misc/ 'Misc/MySecondDevice.xml’, ], )

bld.install_as( “Doc/MyDevice_Manual.pdf”, # File will be copied to # /Doc/MyDevice_Manual.pdf “Misc/Manual.pdf”, # Path to source file ) If it is required to automatically scan for files to add to a distribution, and ant syntax compatible file search command is available. It can be used as follows: def build(bld): # make a list of waf node objects by scanning for device description # files device_description_nodes = \ bld.path.ant_glob("DeviceDescription/**/*.xml") + \ bld.path.ant_glob("DeviceDescription/**/*.bmp") + \ bld.path.ant_glob("DeviceDescription/**/*.ico")

bld.install_files( "NXF/DeviceDescription", device_description_nodes )

3.10 Preparing a version header file The Hilscher Waf build system can parse the version information associated with a task generator / artefact from a header file. The version header file to parse is specified via the version_include argument accepted by most of the build commands. This version header will be searched in all include folders defined by the task generator itself and in all include directories exported by task generators used/referenced in this task generator by means of use argument. The version header file will be parsed and a major, minor build and revision number are extracted from define statements which follow a specific format. From these information a version number according Hilscher protocol software format “...” is generated. For successful parsing the following version header file content shall be used: (The token XXX can be chosen arbitrarily and is ignored when parsing): #ifndef XXX_VERSION_H_ #define XXX_VERSION_H_

#define XXX_VERSION_MAJOR 1 #define XXX_VERSION_MINOR 1 #define XXX_VERSION_BUILD 5 #define XXX_VERSION_REVISION 0

#endif /* XXX_VERSION_H_ */

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Supported toolchains 29/60 4 Supported toolchains This sections describes the toolchains supported by the Hilscher Waf build systems and the parameters used with them.

Note: The Hilscher Waf build system might accept other toolchain names not listed here. These toolchains are implemented for internal evaluation purposes only. They are officially not supported and shall not be used. Support of these toolchains is incomplete, untested and might be dropped silently.

Generally, Waf based build systems combine arguments and options from various places when an external tool is invoked. In order to see the final arguments passed to an external tool, the command line argument --dump-environment=variables,… shall be passed to waf.bat.

4.1 GCC-based toolchains 4.1.1 Common definitions and parameters 4.1.1.1 C / C++ Source files When the Hilscher Waf build system compiles C source files into object files the gcc.exe command is used. In order to compile C++ source files the g++.exe command is used. The following command line argument are passed to the GCC compiler by default when compiling C or C++ source files: -Wall -Wredundant-decls -Wno-inline -Winit-self If the feature warninglevel1 is used, the following command line arguments are passed in addition to the arguments listed above: -Wsystem-headers -Wbad-function-cast -Wsign-compare -Wswitch-default -Wstrict-prototypes -Wpointer-arith Further command line arguments might be passed to the compiler command depending on the specific toolchain and target. These arguments are described below.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Supported toolchains 30/60 4.1.1.2 Assembler source files Assembler source files are processed with the gcc.exe command as well to support preprocessor macro expansion.

Note: In order to run the cpp preprocessor on assembler source files before running the assembler, the file extension must be an uppercase “S”, e.g. init_gnu.S. A lower case “s” implies not running the preprocessor.

The following command line arguments are used with gcc.exe when processing assembler files: -Wall -Wredundant-decls -Wno-inline

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Supported toolchains 31/60 4.1.2 Hitex toolchain The Hitex toolchain is based on GCC V4.0.3 and supports code generation for ARMv5 architecture compatible CPUs. It is identified by toolchain name “hitex”. The code generated by this toolchain uses a pre EABI binary format and thus can only be linked with code generated by Hitex toolchain. Depending on the target, the following compiler arguments are used with the Hitex toolchain. For netX based targets the following command line arguments are combined and passed to the toolchain: When invoking the compiler for C or C++ source files using debug build conditions: -O0 -g -gdwarf-2 When invoking the compiler for C or C++ source files using debugrel build conditions: -Os -g -gdwarf-2 When invoking the compiler for C or C++ source files using release build conditions: -Os When invoking the compiler for assembler source files using debug or debugrel build conditions: -Wa,-gdwarf2 When invoking the compiler for C or C++ source files independent of build conditions: -mlong-calls -mapcs -mthumb-interwork -fshort-enums -fno-common When invoking the compiler for assembler source files independent of build conditions: -mapcs -mthumb-interwork -fshort-enums When invoking the linker: -mthumb-interwork -nostdlib Additionally, depending on the specified task generator platform the following command line arguments are used: When compiling or linking for “netx” platform: -D_NETX_ -march=armv5te -msoft-float -mfpu-vfp -mfloat-abi=soft When compiling or linking for “netx50” platform: -D_NETX_ -D__NETX50 Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Supported toolchains 32/60 -mcpu=arm9e -msoft-float -mfpu-vfp -mfloat-abi=soft When compiling or linking for “netx100” or “netx500” platform: -D_NETX_ -D__NETX100 or -D__NETX500 -mcpu=arm926ej-s -msoft-float -mfpu-vfp -mfloat-abi=soft

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Supported toolchains 33/60 4.1.3 CodeSourcery toolchain The CodeSourcery toolchain is based on GCC V4.5.2 and supports code generation for ARMv5 and ARMv6 architecture compatible CPUs. It is identified by toolchain name “codesourcery”. The code generated by this toolchain is ARM EABI compatible and can be linked with any external provided ARM EABI conforming binary code. Depending on the target, the following compiler arguments are used with the CodeSourcery toolchain. For netX based targets the following command line arguments are combined and passed to the toolchain: When invoking the compiler for C or C++ source files using debug build conditions: -O0 -g -gdwarf-2 When invoking the compiler for C or C++ source files using debugrel build conditions: -Os -g -gdwarf-2 When invoking the compiler for C or C++ source files using release build conditions: -Os When invoking the compiler for assembler source files using debug or debugrel build conditions: -Wa,-gdwarf2 When invoking the compiler for C or C++ source files independent of build conditions: -mlong-calls -mapcs -mthumb-interwork -fshort-enums -fno-common When invoking the compiler for C or C++ source files independent of build conditions and if feature “disable_gc_sections” is not used: -ffunctions-sections -fdata-sections When invoking the compiler for assembler source files independent of build conditions: -mapcs -mthumb-interwork -fshort-enums When invoking the linker: -mthumb-interwork -nostdlib -Wl,-gc-sections

Additionally, depending on the specified task generator platform the following command line arguments are used: When compiling or linking for “netx” platform: -D_NETX_

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Supported toolchains 34/60 -march=armv5te -msoft-float -mfpu-vfp -mfloat-abi=soft When compiling or linking for “netx50” platform: -D_NETX_ -D__NETX50 -mcpu=arm966e-s -msoft-float -mfpu-vfp -mfloat-abi=soft When compiling or linking for “netx10”, “netx51” or “netx52” platform: -D_NETX_ -D__NETX10, -D__NETX51 or -D__NETX52 -mcpu=arm966e-s -msoft-float -mfpu-vfp -mfloat-abi=soft When compiling or linking for “netx100” or “netx500” platform: -D_NETX_ -D__NETX100 or -D__NETX500 -mcpu=arm926ej-s -msoft-float -mfpu-vfp -mfloat-abi=soft

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Supported toolchains 35/60 4.1.4 GNU ARM Embedded toolchain The GNU ARM Embedded toolchain is based on GCC V4.9.3 and supports code generation for ARMv5, ARMv6 and ARMv7 architecture compatible CPUs. It is identified by toolchain name “gccarmemb”. The code generated by this toolchain is ARM EABI compatible and can be linked with any external provided ARM EABI conforming binary code. Depending on the target, the following compiler arguments are used with the GNU ARM Embedded toolchain. For netX based targets the following command line arguments are combined and passed to the toolchain: When invoking the compiler for C or C++ source files using debug build conditions: -O0 -g -gdwarf-2 When invoking the compiler for C or C++ source files using debugrel build conditions: -Os -g -gdwarf-2 When invoking the compiler for C or C++ source files using release build conditions: -Os When invoking the compiler for assembler source files using debug or debugrel build conditions: -Wa,-gdwarf2 When invoking the compiler for C or C++ source files independent of build conditions: -mlong-calls -mapcs -fno-common When invoking the compiler for C or C++ source files independent of build conditions and if feature “disable_gc_sections” is not used: -ffunctions-sections -fdata-sections When invoking the compiler for C or C++ source files independent of build conditions and if feature “enable_unaligned_access” is not used: -mno-unaligned-access When invoking the compiler for assembler source files independent of build conditions: -mapcs -mthumb-interwork -fshort-enums When invoking the linker: -mthumb-interwork -nostdlib -Wl,-gc-sections

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Supported toolchains 36/60 Additionally, depending on the specified task generator platform the following command line arguments are used: When compiling or linking for “netx” platform: -D_NETX_ -march=armv5te -msoft-float -mfpu-vfp -mfloat-abi=soft -mthumb-interwork -fshort-enums When compiling or linking for “netx50” platform: -D_NETX_ -D__NETX50 -mcpu=arm966e-s -msoft-float -mfpu-vfp -mfloat-abi=soft -mthumb-interwork -fshort-enums When compiling or linking for “netx10”, “netx51” or “netx52” platform: -D_NETX_ -D__NETX10, -D__NETX51 or -D__NETX52 -mcpu=arm966e-s -msoft-float -mfpu-vfp -mfloat-abi=soft -mthumb-interwork -fshort-enums When compiling or linking for “netx100” or “netx500” platform: -D_NETX_ -D__NETX100 or -D__NETX500 -mcpu=arm926ej-s -msoft-float -mfpu-vfp -mfloat-abi=soft -mthumb-interwork -fshort-enums When compiling or linking for “netx90” platform: -D_NETX_ -D__NETX90 -march=armv7e-m -mfloat-abi=soft

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Supported toolchains 37/60 -mthumb When compiling or linking for “netx4000” platform: -D_NETX_ -D__NETX4000 -march=armv7-r -mfloat-abi=soft -mthumb-interwork

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Supported toolchains 38/60 4.2 LLVM/Clang-based toolchains 4.2.1 Hilscher xPIC toolchain The Hilscher xPIC toolchain is a LLVM/Clang based toolchain used for the xPIC units within the netX10/netX51/netX52/netX90/netX4000 devices. The following command line arguments are used with this toolchain: When invoking the compiler for C or C++ source files using debug build conditions: -O0 -g -gdwarf-4 When invoking the compiler for C or C++ source files using debugrel build conditions: -Os -g -gdwarf-4 When invoking the compiler for C or C++ source files using release build conditions: -Os Additionally, depending on the platform the following command line arguments are used: When compiling for “xpic” platform (netX10): -Wa,-mmcu=xpic When linking for “xpic” platform (netX10): -mcpu=xpic When compiling for “xpic2” platform (netX51/netX52/netX90/netX4000): -Wa,-mmcu=xpic2 When linking for “xpic2” platform (netX51/netX52/netX90/netX4000): -mcpu=xpic2

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 39/60 5 Command reference 5.1 Common definitions Many of the commands defined by Hilscher Waf build system have similar arguments. This section describes these common arguments to avoid redundant descriptions afterwards. Refinements to the arguments are described for each command separately within its reference section.

5.1.1 bld. - build commands Build commands are used within the build() function of a wscript file to declare build steps. These commands are small wrapper functions hiding the generation of task generators associated with the corresponding build steps. Arguments accepted by multiple build commands are described within this section. Unused arguments should be omitted for better readability of the wscript files.

Note: Not all arguments described below are used by all build commands and might be silently ignored.

Synopsis def build(bld): bld.( export_includes = [“include_path”,…], export_defines = [“define=value”,…], cflags = [“cflag”,…], cxxflags = [“cxxflag”,…], defines = [ „define=value“,…], description = “description_string”, displaygroup = “displaygroup_name”, features = “feature …”, hidden_from_list = True | False, includes = [“include_path”,…], install_path = “path”, linkerscript = „linkerscript_path“, linkflags = [“linkerflag”,…], name = “taskgenerator_name”, source = [ “file”,…], source_arm = [ “file_arm”,…], source_thumb = [ “file_thumb”,…], platform = “platform_name”, target = “target_path/target_name”, toolchain = “toolchain”, use = [ “name”,…], version_include = “version_headerfile_name”, ) Description cmd Is the build command. Valid values for cmd are defined in next sections. includes = [ “include_path”,…] Paths to include folders required to compile the source files are defined using the includes argument. Its value shall be set to a comma separated list of paths to include folders. The paths should be relative to the wscript containing the command but can be absolute as well.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 40/60 cflags = [“cflag”,…] Additional C-Compiler flags required to compile the component can be specified using the cflags argument as comma separated list. Preprocessor-Defines should not be set using this argument. For that purpose the defines argument described below shall be used. Using this argument is not portable and requires knowledge about the used toolchain and compiler as these flags are compiler specific. cxxflags = [“cxxflag”,…] This argument is similar to cflags argument described above but for C++ Compiler flags. defines = [ „define=value“,…] Preprocessor-Defines are specified using a comma separated list with the defines argument. The Waf build system will set up proper arguments for assembler, C compiler or C++ compiler depending on used toolchain. description = “description_string” A human readable string describing the task generators artefact. Used when printing available targets / task generators when Waf is run using the list command. displaygroup = “displaygroup_name” A human readable string naming the group this task generator belongs too. Used when printing available targets / task generators when Waf is run using the list command. export_includes = [“include_path”,…] List of comma separated paths to include directories which shall be exported to other task generators. If this task generator is referenced by another task generator using the use argument all directories declared with this argument are added to the include path list of referencing task generator. The paths should be relative to the wscript containing the definition. export_defines = [“define=value”,…] Similar to exporting include directories to other task generators, pre-processor defines can be propagated to other task generators. All pre-processor defines which shall be set for task generators referencing this task generator shall be specified as comma separated list with this argument. features= “feature …” The features argument is a space separated string or comma separated list of features that request additional actions when the task generator is processed. This argument is extended by the build command wrapper functions with task generator specific entries. (e.g. “stlib” for static libraries, “program” for executables, “c” for c source code) These values should not be used within the wscript files to avoid unexpected behaviour. The following values can be used for the features argument: buildstamp: will add pre-processor defines BUILDSTAMP_BUILD_DATE_YEAR, BUILDSTAMP_BUILD_DATE_MONTH and BUILDSTAMP_BUILD_DATE_DAY which are set to current date group_lib: will add grouped library linking options to linker command if supported. By default linker uses non grouped linking which requires that input libraries must be in correct order. Otherwise the linker might not be able to resolve symbols. If this feature is specified, the linker command will be modified to use library grouping: the linker will look for a symbol in all library files regardless of the order they appear. Using this feature can cause unexpected issues with weak symbols and will prevent detection of multiply defined symbols. It is recommended to fix the link library order instead of using this features when unresolved symbols occur in linking step.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 41/60 libsused: will generate a text file “_usedlibs.txt” which contains meta- information about the referenced task generators used when generating the artefact. warninglevel1: will enable additional compiler code checking flags. Details about this can be found in the toolchain section. hidden_from_list = True|False When this argument is set to true the task generator will not be printed when Waf is invoked with the list command. Also the task generator will be omitted in meta-information files generated for project distribution folder. The argument is useful to hide e.g. debug libraries or sdk components. install_path = “distribution_subdirectory” If the artefact build by the task generator should be part of the projects distribution the install_path argument shall be set to the desired destination path. The path is interpreted as directory relative to to distribution directory. (by default “dist”, so artefact will be placed in “/dist/”). linkerscript = „linkerscript_path“ For embedded applications the linker process is controlled by a target and project specific linker script. The linkerscript argument is used to specify the path to this file. It is interpreted relative to current wscript file. linkflags = [“linkerflag”,…] Target specific command line options which shall be passed to the linker are specified as comma separated list using the linkflags argument. The argument is not portable and correct linkerflag encoding depends on the used toolchain.

Note: For GCC based toolchains the Hilscher Waf build system will use the compiler for linking. Therefore flags to be passed to GNU ld must be prefixed with “-Wl,”. name = “taskgenerator_name” The name of a task generator is either equal to target_name or explicitly set using this argument. This name is used in other task generator in use argument to refer to the task generator, e.g. include the library when linking or to add include paths.

Note: The name of a task generator is a global symbol in Waf. It is not possible to define multiple task generators with the same name. The last defined task generator with equal name will replace previous ones. This must be considered especially when the name argument is omitted.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 42/60 platform = “platform_name” The platform argument is used to choose the correct compiler flags for the desired target platform. Additional the pre-processor define “__” will be set in order to detect the target type in source code files. Valid values for platform depend on the toolchain and the Hilscher Waf Build System version. At the time of writing the following platform names are valid: netx platform (generic ARM926/966 compatible with netX10, netX50, netX51 netX52, netX100 and netX500) can be used in conjunction with hitex, codesourcery or gccarmemb toolchain. netx50, netx100, netx500 platforms can be used in conjunction with hitex, codesourcery or gccarmemb toolchain netx10, netx51, netx52 platforms can be used in conjunction with codesourcery or gccarmemb toolchain netx90, netx4000 platforms can be used in conjunction with gccarmemb toolchain.  xpic, xpic2 platform can be used in conjunction with llvm-xpic toolchain For detailed information about the compiler flags used for each toolchain and platform please refer to the Toolchain section.

Note: Binary code generated by codesourcery and gccarmemb toolchain using the same platform can be linked together as both toolchains generate binary code compatible with ARM EABI. Hitex toolchain binary code cannot be linked with binary code generated by other toolchains due to different ABIs. source, source_thumb, source_arm = [ “file_path”,…] The source arguments are used to define the source files needed to build the target. The value is a comma separated list of paths to the source files. Paths must be specified relative to the wscript file containing the command. The source parameters have been adapted to the requirements of ARM processors: Source files specified using parameters source or source_thumb will be compiled using thumb mode while source files specified using parameter source_arm are compiled in ARM mode. When the target architecture does not support thumb or arm mode all parameters are equivalent. It is recommended to use the suffixed arguments only in case of special requirements. (e.g. arm interrupt handling) All source arguments can be used at the same time to compile different source files of same target in different modes. target = “target_path/target_name” The target argument sets the name of the artefact defined by the task generator. The target_path if exists is a slash separated subdirectory path to place the target file within. This is e.g. used to separate targets with same file name generated using different toolchains. Taking the build directory and the build conditions into account, the output file will be placed by the Hilscher Waf build system at path //// Depending on the task generator type and the toolchain the target_file_name of the artefact is derived from the target_name value as follows: (inconclusive list) For static libraries “lib.a” For dynamic libraries: “lib.so” For linked firmware executables: “.elf” For linked applications on windows: “.exe” For linked applications on linux: “” For bootable (bootblocker, nxf) netx firmwares: “” Details are described in reference of each build command.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 43/60 Note: The default and recommended naming convention for the target_path is “/” for non os dependent libraries and “//” for os dependent targets. This convention has been defined to avoid task generator naming clash when generating the same target_name for different toolchains. toolchain = “toolchain” The toolchain argument is used to specify the compiler toolchain to use. The argument is mandatory. Currently implemented toolchains are: hitex toolchain is the Hitex GCC V4.0.3 toolchain using a.out elf format. This toolchain shall be used with legacy products only. codesourcery toolchain is an gcc toolchain formerly provided by CodeSourcery, now part of Mentor Graphics. The toolchain is based on GCC V4.5.2 and generates ARM EABI compatible binary output. gccarmemb toolchain selects the GNU ARM Embedded Toolchain provided by ARM which generates ARM EABI compatible binary output. Hilscher firmwares are build using a GCC 4.9.2 based version of this toolchain. llvm-xpic toolchain is a LLVM based toolchain from Hilscher supporting the xPIC and xPIC2 processors found on netX10, netX51, netX52, netX90 and netX4000. use = [“name”,…] References or dependencies to other task generators (build target) are specified using the use argument. The argument is a list of names of the task generators required by the build command. Dependencies and inputs to tasks will be added according to relationships defined by this argument: Include paths exported by listed task generators using the export_includes argument are added to include search paths for all tasks created by this build command Static or dynamic libraries build by referenced task generators are added to linker library list recursively for tasks created from this build command. That means if referenced library references other libraries itself these are also added. Order of linking libraries is prepared according to interdependencies between all referenced libraries. If no direct library interdependencies are known to Waf (typically if SDK task generators are used) the order of libraries on the linker command line is determined by the order of the values of this argument. Thus reordering the values can be used to setup correct library order for linker. The use arguments are processed recursively. Thus variables or artefacts exported from task generators that are referenced from a referenced task generator are also added.

Note: By default Hilscher task generator names for libraries follow the scheme “toolchain_prefix/toolchain_version/library_name”. In order to support linking independent from knowledge of the version of the toolchain, the use argument accepts a wildcard reference “toolchain_prefix/*/library_name” if only a single “/” variant of the generator is available within the project.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 44/60 version_include = “version_headerfile_name” When generating the project distribution folder the Hilscher Waf build system requires knowledge about the (software) version of the generated artefact. This information is used to prepare various meta-information files. The version can be either specified in wscript file using the deprecated version argument or defined in a header file using a specific format. The build system will parse the header file to extract the version information using the regular expression: ^#define\s+\w+_VERSION_(MAJOR|MINOR|BUILD|REVISION)\s+(\S.*)$ This expression will match the following version header file content: (Everything before _VERSION_* is ignored) #ifndef MY_VERSION_H_ #define MY_VERSION_H_

#define MY_VERSION_MAJOR 4 #define MY_VERSION_MINOR 3 #define MY_VERSION_BUILD 1 #define MY_VERSION_REVISION 0

#endif /* MY_VERSION_H_ */ A version number according to Hilscher protocol software version scheme “...” is generated. (In this example the result would be “4.3.1.0”) The version header file will be looked up in all include paths including include paths from task generators referenced via use argument. Thus a firmware task generator can use the application library version header file to get its version information from.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 45/60 5.1.2 bld.get_name_prefix – compute task generator name prefix Synopsis def build(bld): name_prefix = bld.get_name_prefix( toolchain = “toolchain”, suffix = “suffix”, )

bld.( name = name_prefix + “name”, … ) Description According to internal Hilscher definitions, a task generator’s name shall be formatted as slash separated string as follows: “///”. The os_identifier field is optional. The prefix should reflect the proper toolchain prefix and toolchain version. To assist in this requirement the function get_name_prefix() is available. It returns the proper prefix according to selected toolchain and optional suffix. suffix = ”suffix” The optional suffix argument is used to specify the operating system dependend suffix. If the target does not depend on any operating system, no suffix shall be used. toolchain = “toolchain” The toolchain argument is used to specify the compiler toolchain the prefix shall be computed for. See above for valid values.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 46/60 5.2 Build & project structuring 5.2.1 .path.ant_glob - make list of files using pattern search Synopsis def configure(conf): nodes = conf.path.ant_glob([“pattern”,…]) def build(bld): nodes = bld.path.ant_glob([“pattern”,…])

Description The ant_glob function is used to recursively match all files and subdirectories within a directory with a pattern and return a list of matching nodes. The function is invoked using on an existing (directory) node object. The path attribute of the conf or bld object is the directory node containing the current wscript. Combination of this can be used to generate a list of files and/or directories matching a pattern nodes = The function returns a list of Waf node objects representing all files and subdirectories matching any of the specified patterns

[“pattern”, …] This mandatory argument is a list of ant patterns. Patterns are to be specified using the ant file set syntax: Path components like directory names and file names are separated by a slash (“/”). A single star (“*”) matches everything except multiple path components. E.g. the pattern “*” does not match on “directory_a/file_b” while the pattern “*/*” does A double star (“**”) matches an arbitrary number of directories. E.g. “**/*” will match everything within the directory

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 47/60 5.2.2 .autorecurse - recursively process subdirectories Synopsis def options(opt): opt.autorecurse( mandatory = True|False excl = [ “exclude_path”,…] ) def configure(conf): conf.autorecurse( mandatory = True|False excl = [ “exclude_path”,…] ) def build(bld): bld.autorecurse( mandatory = True|False excl = [ “exclude_path”,…] ) Description The Waf build system supports modular project structures where each module/part of the project is described using an own wscript associated with that component. The build system will not automatically scan the project directory for additional wscript files. The autorecurse command is used to recursively search and load all found wscript files in all subdirectories.

Note: Automatic recursing will load and process all wscript files found. If a found wscript file contains the autorecurse or recurse command by itself, other wscript files might be processed multiple times with unexpected results. excl = [ “exclude_path”,…] Directories specified by the excl argument are not included and not recursively processed when searching for wscript files. Typically this argument is set to value [“build”, “dist”] to avoid inclusion of wscript files built during the build or install commands. mandatory = True|False If this argument is set to True or not specified the command will fail if the wscript files does not contain the options()/configure() or build() function. (depending on the function the recurse function was invoked from). If set to False missing functions will be silently ignored. This argument is typically set to True when recursing from within the options() or configure() function as most wscripts don’t define these functions.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 48/60 5.2.3 .load - load waf extension modules Synopsis def options(opt): opt.load(“extension_module …”, tooldir = “extension_directory”) def configure(conf): conf.load(“extension_module …”, tooldir = “extension_directory”) def build(bld): bld.load(“extension_module …”, tooldir = “extension_directory”)

Description Waf build systems can be modified or extended with “waf tools”. E.g. the Hilscher Waf build system is such an extension to Waf build system. An extension can add, modify or remove functionality of the Waf build system in a very flexible and transparent way. The load command is used to load an extension for use with the Waf build system. An extension must be loaded in a wscript from options() and configure() function. Loading from build() function is not necessary when already loaded in configure() function as Waf automatically loads all extensions in build stage which have been previously loaded in configure stage.

“extension_module …” This mandatory argument is a space separated list of extension modules to load from the directory specified by the tooldir argument. tooldir = “extension_directory” Path to directory where the extension modules are located.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 49/60 5.2.4 .recurse - load wscript file from subdirectory Synopsis def options(opt): opt.recurse(“subdirectory_path”, mandatory = True|False) def configure(conf): conf.recurse(“subdirectory_path”, mandatory = True|False) def build(bld): bld.recurse(“subdirectory_path”, mandatory = True|False) Description The recurse command is used to load a wscript file from a specific directory. Despite its name, it does not recursively load all wscript files found within the specified directory. See autorecurse command for this purpose.

“subdirectory_path” This mandatory argument is the path to the directory containing the wscript to load. mandatory=True|False If this argument is set to True or not specified the command will fail if no wscript file is found in the specified directory or if the wscript does not contain the options()/configure() or build() function. (Depending on the function the recurse function was invoked from). If set to False a missing wscript file or function will be silently ignored.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 50/60 5.3 Declarations 5.3.1 bld.externalcomponent - declare pre-compiled library Synopsis def build(bld): bld.externalcomponent( description = “description_string”, displaygroup = “displaygroup_name”, export_includes = [“include_path”,…], name = “taskgenerator_name”, target = "library_name", path = "path_to_directory", use = [ “name”,…], version = "version_string", ) Description name = “taskgenerator_name” The name of the external component task generator is used by other components to include the external component in linking step. The name should conform to standard Hilscher Waf build system naming scheme for task generators “//”. If the toolchain version is not known, it might be replaced with a star (‘*’).

Note: The name of a task generator is a global symbol in Waf. It is not possible to define multiple task generators with the same name. The last defined task generator with equal name will replace previous ones path = “path_to_directory” Path to directory where to find the library file associated with this external component. The path is relative to the declaring wscript file. target = “library_name” Basename of the library file associated with this external component. The library filename will be derived from this argument as follows: • For static libraries “lib.a” • For dynamic libraries: “lib.so” Waf will look for the library file in directory pointed to by argument path. version = “version_string” The version argument can be used to specify the version of the external component. The version is expected to be a string made of four numbers separated by a dot (.): “...”.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 51/60 5.3.2 bld.sdkcomponent - declare a SDK Synopsis def build(bld): bld.sdkcomponent( description = “description_string”, displaygroup = “displaygroup_name”, export_includes = [“include_path”,…], name = “taskgenerator_name”, use = [ “name”,…], version = "version_string", version_include = “version_headerfile_name”, ) Description name = “taskgenerator_name” The name of the SDK task generator is used by other components to declare a dependency on this SDK. The name should conform to standard Hilscher Waf build system naming scheme for SDK task generators “//_sdk”. If the toolchain version is not known, it might be replaced with a star (‘*’).

Note: The name of a task generator is a global symbol in Waf. It is not possible to define multiple task generators with the same name. The last defined task generator with equal name will replace previous ones version = “version_string” The version argument can be used to specify the version of the SDK task generator. The version is expected to be a string made of four numbers separated by a dot (.): “...”.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 52/60 5.4 Compilation and linking The functions described in this section are used to compile and linke firmware files and applications from input files and libraries. 5.4.1 bld.program - link an application / executable Synopsis def build(bld) bld.program( includes = [“include_path”,…], cflags = [“cflag”,…], cxxflags = [“cxxflag”,…], defines = [ „define=value“,…], description = “description_string”, displaygroup = “displaygroup_name”, features = “feature …”, hidden_from_list = True | False, install_path = “path”, linkerscript = „linkerscript_path“, linkflags = [“linkerflag”,…], name = “taskgenerator_name”, source = [ “file”,…], source_arm = [ “file_arm”,…], source_thumb = [ “file_thumb”,…], platform = “platform_name”, target = “target_path/target_name”, toolchain = “toolchain”, use = [ “name”,…], version_include = “version_headerfile_name”, ) Description The program() build command generates a linked application file which can either be loaded into an embedded target using a debugger or executed as application. The command accepts all standard arguments which are described in section 5.1.1. The command can compile target specific source files and add them to the linking step. In case of embedded targets it is mandatory to specify a linkerscript. This linkerscript is passed to the toolchains linker tool and thus is toolchain dependent. target = “target_path/target_name” The target argument defines the base name of the linked object file generated in final linking step. The file name and path will be derived from the argument depending on the toolchain. The following naming rules are defined: For hitex, codesourcery, gccarmemb and llvm-xpic the file name will be “/.elf”. For mingw, mingw32 and ming64 toolchains the filename will be “/.exe”

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 53/60 5.4.2 bld.stlib - build a static library Synopsis def build(bld): bld.stlib( includes = [“include_path”,…], export_includes = [“include_path”,…], export_defines = [“define=value”,…], cflags = [“cflag”,…], cxxflags = [“cxxflag”,…], defines = [ „define=value“,…], description = “description_string”, displaygroup = “displaygroup_name”, features = “feature …”, hidden_from_list = True | False, install_path = “path”, name = “taskgenerator_name”, source = [ “file”,…], source_arm = [ “file_arm”,…], source_thumb = [ “file_thumb”,…], platform = “platform_name”, target = “target_path/target_name”, toolchain = “toolchain”, use = [ “name”,…], version_include = “version_headerfile_name”, ) Description The stlib() build command defines the build of a static library. The command accepts all standard arguments which are described in section 5.1.1. The library file name is derived from the target name using toolchain specific naming rule: For hitex, codesourcery, gccarmemb and llvm-xpic the file name will be lib.a For mingw, mingw32 and ming64 toolchains the filename will be lib.a

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 54/60 5.5 Firmware generation 5.5.1 bld.bootimage - generate a netX bootimage Synopsis def build(bld): bld.bootimage( BOOTBLOCKERFLAGS = [ 'bootblock_arg',…], description = “description_string”, hidden_from_list = True | False, install_path = “path”, name = “taskgenerator_name”, target = “target_path/target_name”, use = [ 'application_name'], ) Description The bootimage() build command generates a bootable firmware image for netX processors. The command was derived from the bootblocker tool. In order to generate a valid bootimage, chip type, source device and destination device parameters must be specified as bootblocker args. The input to this command must be single reference to a program task generator specified by the use parameter.

Note: In order to generate a valid boot image the input elf file and bootblocker arguments must suit the target.

BOOTBLOCKERFLAGS This argument specifies the command line options as would be passed to the Hilscher Bootblocker tool. The options have to be provided as comma separated list. The Hilscher Waf build system parses this argument and will generate a boot image accordingly. For that purpose the part of Bootblocker which generates the boot image has been integrated into Hilscher Waf build system. External Bootblocker tool is not required.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 55/60 5.5.2 bld.firmware - generate a loadable firmware Synopsis def build(bld) bld.firmware( BOOTBLOCKERFLAGS = [ 'bootblock_arg',…], cflags = [“cflag”,…], cxxflags = [“cxxflag”,…], defines = [ „define=value“,…], description = “description_string”, displaygroup = “displaygroup_name”, features = “feature …”, hidden_from_list = True | False, includes = [“include_path”,…], install_path = “path”, linkerscript = „linkerscript_path“, linkflags = [“linkerflag”,…], name = “taskgenerator_name”, source = [ “file”,…], source_arm = [ “file_arm”,…], source_thumb = [ “file_thumb”,…], platform = “platform_name”, target = “target_path/target_name”, toolchain = “toolchain”, use = [ “name”,…], version_include = “version_headerfile_name”, ) Description The bld.firmware command defines the generation of a loadable firmware for use with second stage loader based netX boot sequence. The command combines the linking step from command bld.program and the boot image creation process from command bld.bootimage. Thus the command uses arguments from both build commands. In the following only differences in certain arguments are explained. For full reference of all arguments see description of bld. - build command, bld.program - link an application / executable and bld.bootimage - generate a netX bootimage.

Note: In order to generate a valid loadable firmware image the input elf file must define conform to loadable firmware file elf rules. This includes a proper structure definition of the elf file within the linkerscript. target = “nxf_file_name” The target argument sets the name of the loadable firmware file to be generated. The argument defines the full name and must be specified with extension (“.nxf”). The command will derive the file name of the linker output from the target argument by replacing its extension with “.elf”.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 56/60 5.5.3 bld.module - generate a loadable module Synopsis def build(bld) bld.module( cflags = [“cflag”,…], cxxflags = [“cxxflag”,…], defines = [ „define=value“,…], description = “description_string”, displaygroup = “displaygroup_name”, features = “feature …”, fileheader_source = “fileheader_source_file”, hidden_from_list = True | False, includes = [“include_path”,…], install_path = “path”, linkerscript = „linkerscript_path“, linkflags = [“linkerflag”,…], name = “taskgenerator_name”, platform = “platform_name”, source = [ “file”,…], source_arm = [ “file_arm”,…], source_thumb = [ “file_thumb”,…], taglist_source = “taglist_source_file”, target = “nxo_file_name”, toolchain = “toolchain”, use = [ “name”,…], version_include = “version_headerfile_name”, ) Description The bld.module command defines the generation of a loadable module. A loadable module is used with a base firmware containing the operating system. The base firmware will load, dynamically link and execute the loadable module at runtime. Multiple loadable modules can be executed at the same time on a single netX chip and thus allow combination of modules to a custom communication firmware. The command is derived from the linking step defined by command bld.program but performs additional code generation and processing steps. The command accepts the same arguments as bld.program but requires some additional parameters.

Note: In order to generate a valid loadable module linked elf file must define conform to loadable module file elf rules. This includes a proper structure definition of the elf file within the linkerscript. fileheader_source = “fileheader_source_file” A loadable firmware as well as a loadable module contain a file header structure. This structure contains a basic description of the module. For loadable modules the file header source file must be provided using the separate argument fileheader_source. taglist_source = “taglist_source_file A loadable module contain a taglist. This taglist define the used resources by the loadable module and can be modified within the module file using the taglist editor tool. This might be required to solve resource conflicts if multiple modules are used together. The source of the taglist file must specified using this argument. target = “nxo_file_name” The target argument sets the name of the loadable module file to be generated. The argument defines the full name and must be specified with extension (“.nxo”). The command will derive the file name of the linker output from the target argument by replacing its extension with “.elf”.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 57/60 5.5.4 bld.generate_hboot_image - generate a hboot image Synopsis def build(bld): bld.generate_hboot_image( hboot_xml = “hboot_xml_file”, name = “taskgenerator_name”, netx_type = “netx_type_name”, target = “hboot_file_name”, sniplib = “path_to_sniplib”, use = [ “name”,…], ) Description The bld.hboot command creates a full hboot image from input elf files using the firmware structure defined in an hboot xml file. hboot_xml = “hboot_xml_file” Path to hboot xml file which describes the structure of the firmware. The elf files passed to this build command by the use argument can be referenced from the hboot xml file using aliases “tElf0”, “tElf1”… netx_type = “netx_type_name” This argument is used to specify the target netx type. This information is used by hboot tool to load the proper patch table which describes the rom code of the target chipset. The following netx types are defined: • NETX4000_RELAXED is the netX4000 relaxed chipset • NETX90_MPW is the netX90 multi project wafer sample target = “hboot_file_name” The target argument defines the output file name to be used for the image. sniplib = “path_to_sniplib” When the hboot xml file references external snippets, this argument must be used to specify the path to the snippet library. use = [ “name”,…] The use argument is a list of bld.program task generator names from which the firmware should be build. The entries in this list are enumerated using aliases tElf0, tElf1,… . These aliases must be used in hboot xml file to reference the elf files.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 58/60 5.5.5 bld.generate_netx90_intflash2_image - generate a netx90 application image Synopsis def build(bld): bld.generate_netx90_intflash2_image( target = “hboot_file_name”, use = [ “name”], ) Description The bld.generate_netx90_intflash2_image command creates flash image for the intflash2 memory of netx90 chipset. Such an image typically contains the netX90 application firmware. The command expects that the elf file was created using a proper linkerscript which takes the memory structure of the intflash2 memory of application side into account. target = “hboot_file_name” The target argument defines the output file name to be used for the image. use = [ “name”,…] The use argument is a single reference to a bld.program task generator name from which the firmware image for intflash2 memory should be build.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Command reference 59/60 5.6 Distribution 5.6.1 bld.install_as - copy file to distribution with renaming Synopsis def build(bld): bld.install_as(“destination_file_path”, “source_file_path”) Description The install_as command copies a file to the distribution and optionally changes its name.

“destination_file_path” Destination file path relative to distribution directory.

“source_file_path” Path to source file relative to current wscript

5.6.2 bld.install_files - copy multiple files to distribution Synopsis def build(bld): bld.install_files(“destination_dir_path”, [ “source_file_path”, …])

Description Multiple files are copied to a directory within distribution directory using the install_files command.

“destination_dir_path” Path to the destination directory where to place the files. The path is relative to distribution directory.

[“source_file_path”, …] List of paths of files to copy. Paths are relative to current wscript.

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018 Appendix 60/60 6 Appendix 6.1 List of tables Table 1: List of revisions...... 4 Table 2: Terms, abbreviations and definitions ...... 4 Table 3: References to documents ...... 4 Table 4: Typical file structure of a project using Hilscher Waf build system ...... 6

6.2 List of figures Figure 1: Environment object relations ...... 7 Figure 2: Hilscher Waf build environment structure ...... 8

Hilscher Waf Build System | Building libraries, applications and netX firmware DOC170404OI02EN | Revision 2 | English | 2018-01 | Released | Public © Hilscher, 2017‑2018