The Software Build System¶
Four Layers¶
The software build system is organized into four layers:
-
The Software Project Layer: Example: Hello World. This layer represents the top level of the build system. The software ELF executables and flash binaries are built at this level. Depending on what functionality the software project build requires, it will add libraries from the Software Component Layer.
-
The Software Component Layer: Software Components are the building blocks of a software project build. Each component is built as a library and may have dependencies on additional software components in the Software Component Layer. The Software Component's sources are located directly in the Software Component's directory, or referenced from specific locations in the submodule layer.
-
The Submodule Layer: Submodules are Git submodules containing, among other things, source code referenced from the Software Component Layer. The software build system does not directly build at this level. Makefiles located in the Submodule Layer are not executed.
-
The Code Generation Layer: Some components require some form of transformation to be turned into source code. The component in question provides specific code generation instructions in the form of a custom command (
add_custom_command) in itsCMakefile.txt. The custom command is added as a dependency to the genericcgentarget, which gets executed as part ofmake regen, the build tree (re-)generation command. Except for the Register Access Layer, code-generated files are written to thecodegen/subdirectory in the build tree.
The following software components currently rely on code generation:
- sdram: Register macros and initialization code for the LiteDRAM module are generated from the LiteX submodule.
- Register Access Layer: This layer, code-generated by Corsair, is part of the source tree, in the registers/generated directory.
The Software CMakeLists¶
The build system consists of a tree of CMakeLists.txt files. The top-level CMakeLists.txt adds the gw/ and sw/ subdirectories. The CMakeLists.txt file in the sw/ directory adds the components/ and projects/ subdirectories, etc., down to the individual SW component and project directories.
A Software Component CMakeList¶
The Software Component CMakeList is straightforward: You give the library a name, specify its sources, include paths, and C/CPPFLAGS:
add_library(gpio)
target_sources(gpio
PRIVATE
gpio.cpp
)
target_compile_options(gpio
PRIVATE
-O2 -g -ffunction-sections
)
#Paths to include files users of usb_hid are expected to use.
target_include_directories(gpio
PUBLIC
${CMAKE_CURRENT_LIST_DIR}
${PROJECT_SOURCE_DIR}/registers/generated/
)
A Software Project CMakeList¶
CMake is designed to build software. The necessary functions for creating libraries, executables, etc., are predefined. The only custom function added to the software CMakeLists tree is link_and_create_image(). This function executes the necessary steps to link the given target using a given linker script and generate an executable and a memory file. The memory file can be used by the GW part of the build system to initialize IMEM.
A typical SW project CMakeLists.txt file looks like this:
add_executable(hello_world
EXCLUDE_FROM_ALL
hello.cpp
)
#Setting the -g flag for the hello_dbg build testing GDB access.
target_compile_options(hello_world
PRIVATE -g)
if(CMAKE_BUILD_TYPE STREQUAL "sim")
link_and_create_image(hello_world
${PROJECT_SOURCE_DIR}/sw/components/bootstrap/link_imem_boot.ld)
else()
link_and_create_image(hello_world
${PROJECT_SOURCE_DIR}/sw/components/bootstrap/link_ddr_boot.ld)
endif()
target_link_libraries(hello_world gpio riscv bootstrap)
add_flash_sw_target(hello_world)
Note that depending on whether we're building for simulation or FPGA, two variants of the linker script are used. See the Linker Script for more details.
Software CMakeList Organization¶

Software CMakeLists Organization.