Build resources
Introduction
This page explains the three make systems supported by this SDK. At least one example using each is included in the $HEXAGON_SDK_ROOT/examples folder.
Make system | Reference | SDK example | Description |
---|---|---|---|
make.d | Brew | calculator | Legacy Hexagon SDK make framework, based on GNU make, with a set of common definitions files and templates for project make files. |
cmake | cmake | calculator | Support for cross-platform builds |
GNU make | make | qhl | Legacy Make system |
make.d
The make.d framework is built upon two main files in the SDK: defines.min and rules.min. Each user project contains a file named Makefile that includes these two files and defines the project to be built according to make.d variables and conventions.
File Name | Description |
---|---|
Makefile | A user-defined file that includes make.d's defines.min, sets BUILD variables, and lastly includes $(RULES_MIN). |
defines.min | Customized for Hexagon SDK. It sets up all the predefined variables and functions exported by make.d and also includes the all default rule definition. |
rules.min | Customized for Hexagon SDK. It sets up all the rules based on the make.d primitives, tells GNU Make what to execute and how. |
Once created for a new project, the SDK user will typically not have to modify any of these files.
defines.min
should be included at the beginning of the makefile and rules.min
at the end.
Snippet from the Calculator C++ Makefile:
...
project definition
...
include $(V_TARGET)_deps.min
include $(HEXAGON_SDK_ROOT)/build/make.d/$(V_TARGET)_vs.min
include $(HEXAGON_SDK_ROOT)/build/defines.min
include $(V_TARGET).min
include $(RULES_MIN)
make.d user-project files
A project Makefile typically includes a local project-defined <V_TARGET>.min
and <V_TARGET>_deps.min
file, which specify the custom build rules for that project:
<V_TARGET>.min
specifies the sources and dependencies needed to generate the executables or shared objects.<V_TARGET>_deps.min
specifies the dependencies of the project.
<V_TARGET>
, which is derived from the make command, can take one of the following values:
hexagon
, for building rules applying to the Hexagon DSPandroid
, for building rules applying to the application processor running AndroidUbuntuARM
, for building rules applying to the application processor running Ubuntu
Build goals
The make command has the following syntax:
make <action> [options]
Note that action is also referred as build goal in the document.
The make.d system defines the following target goals:
Action | Description |
---|---|
hexagon | Builds all binaries for Hexagon platform and runs QEXES tests on simulator if the project is updated |
hexagonsim | Builds all binaries for Hexagon platform and runs QEXES tests on simulator forcefully |
android | Builds the project and its dependencies for Android platform with default options |
ubuntuARM | Builds the project and its dependencies for ubuntu platform with default options |
hexagon_clean | Cleans project and its dependencies for hexagon variant. Prebuilt dependencies are not removed. |
android_clean | Cleans project and its dependencies for Android variant. Prebuilt dependencies are not removed. |
ubuntuARM_clean | Cleans project and its dependencies for Ubuntu variant. Prebuilt dependencies are not removed. |
help | Prints brief description on the usage and usage examples |
Make.d supports a syntax for specifying the build goal where options can be given as separate arguments and options may be omitted to rely on defaults.
List of options to build for hexagon and Android/ubuntu are given below:
- Options for all Android and ubuntuArm actions(android, android_clean, UbuntuARM, UbuntuARM_clean)
Options | Values | Description |
---|---|---|
BUILD | ReleaseG*, Release, Debug | Builds ReleaseG, Release or Debug executable |
HLOS_ARCH | 32*,64 | Builds 32-bit or 64-bit executable |
TREE | 0, 1* | Builds only the project and not dependencies if TREE=0, Build the project and dependencies if TREE=1. |
VERBOSE | any value | Displays all the outputs from the build process. If VERBOSE is not defined, the build system displays only error messages. |
BUILD_OUTPUT_DIR | any directory name | Generates all the project binaries in the specified directory |
Note the default values for each option are identified with *. Also cleaning the build with TREE=1 does not remove prebuilt dependencies.
- Options for all hexagon actions(hexagon, hexagonsim, hexagon_clean)
Options | Values | Description |
---|---|---|
BUILD | ReleaseG*, Release, Debug | Builds ReleaseG, Release or Debug executable |
DSP_ARCH | v65*, v66, v68, ... | Builds executable for the specified DSP architecture |
TREE | 0, 1* | Build only the project and not dependencies if TREE=0, Build the project and dependencies if TREE=1 |
NO_QURT_INC | 0*, 1 | Do not include QuRT as a dependency when NO_QURT_INC=1 |
VERBOSE | any value | Displays all the outputs from the build process and simulator tests. If VERBOSE is not defined, the build system displays only error messages. |
BUILD_OUTPUT_DIR | any directory name | Generates all the project binaries in the specified directory |
Most of the user applications running on the DSP require QURT OS support. If you want to run your application/example in a standalone build without OS support, you can select NO_QURT_INC=1
Refer to $HEXAGON_SDK_ROOT/examples/calculator for an example that does not need QURT OS support and $HEXAGON_SDK_ROOT/examples/multithreading for an example that
needs QURT OS support.
- Description for BUILD option values
Value | Description |
---|---|
ReleaseG | optimized, symbols not removed |
Release | optimized , symbols removed |
Debug | unoptimized, symbols not removed |
Usage examples
Refer to calculator example for more details.
Below are some example make.d invocations:
make android
builds 32-bit Android libraries (and dependencies) for the project defined in the user Makefile, in ReleaseG mode.
make hexagon
will build the project's Hexagon artifacts, in ReleaseG mode, for architecture version v65, with default toolchain version supplied in the SDK.
make hexagon VERBOSE=1
is same as make hexagon
, but displays all the outputs from the build process and simulator tests.
The make command prints the default options used in building the project and the build output directory as shown below:
make hexagonsim
==== Building for ReleaseG variant of hexagon architecture v65 ====
==== Using Hexagon Tools at <HEXAGON_SDK_ROOT>/tools/HEXAGON_Tools/8.7.06 ====
Build output directory: <HEXAGON_SDK_ROOT>/examples/calculator/hexagon_ReleaseG_toolv87_v65/ship
If BUILD_QEXES is defined, as part of build process, the build outputs for hexagon are validated by running them on simulator ensuring a successful build completion.
Build targets
The <V_TARGET>.min
file must specify its build targets.
Supported build targets are listed below.
Target | Description | Example |
---|---|---|
BUILD_LIBS | Name of static libraries built | BUILD_LIBS += libcalculator_skel |
BUILD_EXES | Name of executable targets | BUILD_EXES += calculator |
BUILD_QEXES | Name of quick executables. These executables are run automatically on simulator as part of any build command to ensure basic tests are passing | BUILD_QEXES += calculator_q |
QEXE_ARGS | List of arguments to the quick executable | multithreading_q_QEXE_ARGS += arg1 arg2 |
QEXE_SIM_OPTIONS | List of arguments to the Hexagon simulator when running the quick executable | QEXE_SIM_OPTIONS += --dsp_clock 1000 --ahb:lowaddr 0xc0000000 --ahb:highaddr 0xc0ffffff |
BUILD_DLLS | Name of shared or dynamic libraries built | BUILD_DLLS += libcalculator |
PRIMORDIAL_STACK_SIZE | User-thread stack size for Qurt-based simulator tests(default is 256 KB) | multithreading_q_PRIMORDIAL_STACK_SIZE = 0x80000 |
BUILD_COPIES | Files to be copied to output directories | see build copies below |
Tool variables
Some variables control the flags and options to be used with the building tools:
Variable | Description |
---|---|
DEFINES |
Specifies #define names passed to the compiler. Always append to this variable when adding defines. When appropriate, use the alternate <objectname>_DEFINES to be more specific. Note: -D should not be appended to the variable names. E.g. DEFINES += MYDEFINE1 MYDEFINE2 should be used to define variables MYDEFINE1 and MYDEFINE2. |
INCDIRS |
Specifies additional include paths that are passed to the compiler. Always append to this variable when adding include paths. When possible, use the alternate <objectname>_INCDIRS . |
LIBDIRS |
Specifies the paths to search for libraries, DLLS, and import libraries. Always append to this variable when adding paths. |
C_FLAGS or CC_FLAGS |
Specifies compiler flags applying to all C objects. |
CPP_FLAGS or CXX_FLAGS |
Specifies compiler flags applying to all C++ objects. |
Target-specific variables
After defining the build targets, the .min file should define the sources, objects and options needed to generate them. Some of the frequently used options are listed below. For an exhaustive list refer to build_SRCS.
Target source | Type of Source file definition | Example definition | SDK .min file example |
---|---|---|---|
<targetName>_C_SRCS |
List of .c source files. Do not specify the .c extension. | calculator_q_C_SRCS = src/calculator_test_main | calculator_c++/hexagon.min |
<targetName>_CPP_SRCS |
List of .cpp source files. Do not specify the .c extension. | calculator_q_CPP_SRCS = src/calculator_dsp | calculator_c++/hexagon.min |
<targetName>_ASM_SRCS |
List of ASM source files. Do not specify the .S extension | libqprintf_example_skel_ASM_SRCS += asm_src/qprintf_example_asm | qprintf_example/hexagon.min |
<targetName>_LIBS |
list of libs to link with this target. These libs are dependencies for the application and they are listed in DEPENDENCIES variable in corresponding _deps.min file. |
calculator_plus_LIBS += rpcmem | calculator_c++/UbuntuARM.min |
<targetName>_DIR |
Source directory from which a lib needs to be generated | RPCMEM_DIR = $(HEXAGON_SDK_ROOT)/ipc/fastrpc/rpcmem | calculator_c++/UbuntuARM_deps.min |
<targetName>_QAICIDLS |
IDL files to be compiled into C/C++ prior to building the target | calculator_q_QAICIDLS = inc/calculator | calculator/hexagon.min |
Dependency specification
A project's <V_TARGET>_deps.min
file defines its dependencies, which may be picked up from a prebuilt binary or built from source.
Here is an example of how dependencies are specified(from $HEXAGON_SDK_ROOT/example/calculator/hexagon_deps.min): DEPENDENCIES += \ ATOMIC \ RPCMEM \ TEST_MAIN \ TEST_UTIL
The Hexagon SDK comes with dependencies in prebuilt binaries. They are located in their respective directories. For an example please see the $HEXAGON_SDK_ROOT/libs/atomic/prebuilt/ directory. Most of these prebuilt libraries contain debug symbols as they are built with "-g" compiler flag. When libraries are built with -g, the symbols they contain will be part of the final build output. For most of the dependencies, source code also has been provided in the SDK. For an example please see the $HEXAGON_SDK_ROOT/libs/atomic/ directory.
The $HEXAGON_SDK_ROOT/build/default_deps.min file specifies whether a prebuilt library needs to be used or built from sources by default and where to find the source or binary for that library. This file needs to be included in <V_TARGET>_deps.min
file.
If you want to override the way default_deps.min specifies how dependencies should be accessed, you need to set <LIB_NAME>_[PREBUILT_]DIR
in your local <V_TARGET>_deps.min
to point to the desired location of the dependency, as shown below:
ATOMIC_PREBUILT_DIR = $(HEXAGON_SDK_ROOT)/libs/atomic
The line above indicates that the ATOMIC library should be retrieved as a prebuilt binary from the $(HEXAGON_SDK_ROOT)/libs/atomic folder.
Alternatively, you may specify the following in your local dependency file:
ATOMIC_DIR = $(HEXAGON_SDK_ROOT)/libs/atomic
The line above would indicate that the ATOMIC library should be built from source located under $(HEXAGON_SDK_ROOT)/libs/atomic.
Note: For each library, you should only set <LIB_NAME>_DIR
or <LIB_NAME>_PREBUILT_DIR
in the <V_TARGET>_deps.min
.
See $HEXAGON_SDK_ROOT/build/default_deps.min and $HEXAGON_SDK_ROOT/examples/calculator/hexagon_deps.min for more clarity.
Customizing build rules
It is sometimes necessary to define custom build rules. For example, when a single file needs a custom compile option or when a tool is needed to generate a source file. These rules can be added to the makefile after the include $(RULES_MIN) line.
For example:
$(OBJ_DIR)/example.c : example.bin
bin2src.exe -s$(subst /,\\,$<) -dfs:/example.bin -o$@
Additional Information
Build Sources
The variables below allow to change definitions for a specific target.
Target-specific variables | Description |
---|---|
<targetName>_C_SRCS |
Specifies a list of .c source files required to build this target. Do not specify the .c extension. |
<targetName>.C_SRCS |
Specifies a list of C sources files required to build this target. You must specify the file's extension. |
<targetName>_CPP_SRCS |
Specifies a list of CPP source files required to build this target. Do not specify the .cpp extension. |
<targetName>.CPP_SRCS |
Specifies a list of CPP sources files required to build this target. You must specify the file's extension. |
<targetName>_CXX_SRCS , <targetName>.CXX_SRCS |
Specifies a list of CPP source files required to build this target. Do not specify the .cxx extension. |
` |
Specifies a list of ASM source files required to build this target. Do not specify the .S extension. |
<targetName>.ASM_SRCS |
Specifies a list of ASM sources files required to build this target. You must specify the file's extension. This is useful when you need to distinguish between ASM sources that use the extension .S vs .S |
<targetName>_LIBS |
Specifies a list of libraries to link with this target. When a variable |
` |
Similar to |
<targetName>_DLLS |
Specifies a list of shared objects from which symbols will be imported (similar to IMPLIB). |
` |
Specifies a list of resource (RES) files. |
<targetName>_LD_FLAGS |
Used to specify additional linker flags for a specific shared object or executable target. Linker flags may be compiler specific; this variable may need to be set conditionally. |
<targetName>_DEFS |
Specifies DLL-specific DEF files. |
<targetName>_ZIP_SPEC |
Specifies the files to include in the ZIP file. Paths should be specified relative to |
<targetName>_ZIP_SRCHROOT |
Specifies the base path for files listed in |
<targetName>_QAICIDLS |
Specifies the IDL files to be compiled into C/C++ prior to building the target. Targets should add the stub or skel sources to their list of C sources. |
<targetName>_QAICIDLS |
<targetName>_QAICIDLS=<idl> <targetName>_C_SRCS+=$V/<interface>_stub or <targetName>_QAICIDLS=<idl> <targetName>_C_SRCS+=$V/<interface>_skel : Typically only the stub or the skel is built into a single target. |
The variables below allow to modify the build options for a specific object.
Build variables | Description |
---|---|
<objectName>_CC_FLAGS , <objectName>_C_FLAGS |
Used to specify additional compiler flags for a specific C object. Compiler flags may be compiler specific; this variable may need to be set conditionally. |
<objectName>_CXX_FLAGS , <objectName>_CPP_FLAGS |
Used to specify additional compiler flags for a specific C++ object. Compiler flags may be compiler specific; this variable may need to be set conditionally. |
` |
Used to change the default tool used to compile this C object. |
<objectName>_CXX |
Used to change the default tool used to compile this CPP or CXX object. |
<objectName>_INCDIRS |
Specifies additional include paths to use for <objectName> . |
<objectName>_DEFINES |
Specifies additional defines that are added when building <objectName> . Note: <objectname>_DEFINES += -DMYDEFINE1 –DMYDEFINE2 should not be used, instead <objectname>_DEFINES += MYDEFINE1 MYDEFINE2 should be used, -D will be picked up by default. |
<objectName>_UNDEFINES |
Removes the specified defines when building <objectName> . |
Exporting build outputs
After the project is built, the final built outputs need to be validated on target or/and an application needs to
invoke the APIs exported by the project. In order to consolidate these outputs all the required
header files, libraries, dlls, executables are typically copied to a directory called <output>/ship
, where output
is the output directory name. The make.d build system supports a build
target called "BUILD_COPIES" to achieve this.
Here is an example of <target.min>
containing BUILD_COPIES definition:
BUILD_COPIES = \
$(DLLS) \
$(EXES) \
$V/calculator.h \
$(LIBS) \
$(SHIP_DIR)/ ;
Which copies all the generated DLLs, executables, calculator.h, libraries to $(SHIP_DIR).
The ship directory can be overridden by redefining SHIP_DIR
after including defines.min as follows in the makefile,.
include $(HEXAGON_SDK_ROOT)/build/defines.min
SHIP_DIR=$(V)/ship_new
Toolchain Support in Android NDK
By default the Hexagon SDK supports Android NDK r25c
, though the backward compatibility to Android NDK r19c
is maintained.
Android NDK r19c
comes with Clang toolchain support. However, Hexagon SDK build supports GCC toolchain to enable users to compile using other NDK versions. To use the GCC toolchain, set ANDROID_ROOT_DIR to the Android root directory and use V_GCC=1
option in the make command.
Note that Android NDK r19c
does not support GCC and hence the below command will not work with NDK r19c
.
make android V_GCC=1
The default Android API level is set to 26 (i.e. Version 8 OREO). The API level can be modified by passing API_LEVEL=<>
in the make command.
make android API_LEVEL=28
To use an older Android NDK such as r14b
, it is recommended to change the Android API level to 24 or below. API level 24 works only with the full Android NDK and not with the minimal Android NDK.
make android V_GCC=1 API_LEVEL=24
For older Android NDK versions such as Android NDK r19c
, users need to make sure the Android NDK platform at $HEXAGON_SDK_ROOT/tools/android-ndk-r19c/platforms
folder has the corresponding API folder present before they set the API level.
CMake
CMake is an open source cross-platform tool designed to build, test and package complex software projects. The software compilation in CMake is controlled using simple, platform- and compiler-independent configuration files. In Hexagon SDK, CMake build system is supported along with make.d-based build system and offers an alternative to make.d to build projects. Using both CMake and make.d to build a single project is also possible with some limitations that are described in the sections below.
CMake configuration files
The toolchain and configuration files that are needed to use the CMake build system are located in the $HEXAGON_SDK_ROOT/build/cmake directory. The description of each of these files is as follows:
cmake_configure.bash
: This file contains the environment setup and configuration of the CMake build system based on the options provided by the user. This file also generates the necessary MakeFiles for Hexagon or Android targets.hexagon_fun.cmake
: This file contains the support functions that are needed to simplify the compilation of IDL files, running on simulator and invoking make.d build commands from CMake.hexagon_toolchain.cmake
: This file defines the cross-compilation tools needed to compile code for Hexagon targets. This contains all the options related to the Hexagon LLVM toolchain.ubuntuARM32_toolchain.cmake
: This file defines the cross-compilation tools needed to compile code for UbuntuARM 32-bit targets. This contains all the options related to the UbuntuARM 32-bit toolchain.ubuntuARM64_toolchain.cmake
: This file defines the cross-compilation tools needed to compile code for UbuntuARM 64-bit targets. This contains all the options related to the UbuntuARM 64-bit toolchain.custom_toolchain.cmake
: This file can be used to define the compilation tools needed to compile code for custom hosts OS different than Android, UbuntuARM, Windows and QNX.
The Android toolchain file used to build the application code is taken from the Android NDK installed in the Hexagon SDK, located at: $HEXAGON_SDK_ROOT/tools/android-ndk-r25c/build/cmake/android.toolchain.cmake
.
Using CMake build system
To use the CMake build system to compile code for Hexagon or HLOS targets, the user has to create a CMakeLists.txt file which defines the necessary rules to build an HLOS executable and DSP library.
To keep the build commands identical for both make.d and CMake, there is an executable with the name build_cmake
that can be used to build the examples. It can be accessed once the SDK environment is set.
The usage of the CMake build systems is as described below:
build_cmake <action> [Options]
CMake build system supports the following target options
Action | Description |
---|---|
hexagon | Build a dynamic DSP lib .so |
hexagonsim | Build a dynamic DSP lib or executable for hexagon and run on simulator |
android | Build the Android executable |
ubuntuARM | Build the UbuntuARM executable |
<CUSTOM_NAME> |
<CUSTOM_NAME> helps to build the custom HLOS executable. <CUSTOM_NAME> can take any name other than hexagon, hexagonsim, android, windows, qnx and ubuntuARM. Custom Toolchain explains how to use the custom toolchain for CMake projects |
help | Prints brief description on the usage and usage examples |
Hexagon Options | Acceptable Values( * denotes defaults ) | Description |
---|---|---|
DSP_ARCH | v65*, v66, v68, v69, v73, v75 | Target Variant |
NO_QURT_INC | 0*, 1 | Do not include QuRT as a dependency when NO_QURT_INC=1 |
Note: The option NO_QURT_INC
can also be defined as a variable in the example CMakeLists.txt. For example, Calculator, which is a non QURT example defines this option as set(NO_QURT_INC 1)
in its CMakeLists.txt. If this option is defined in CMakeLists.txt and also passed as an argument while building the example, then the latter will overwrite the former value.
HLOS Options | Acceptable Values( * denotes defaults ) | Description |
---|---|---|
HLOS_ARCH | 32, 64* | HLOS architecture variant |
DOMAIN_FLAG | 0, 1, 2, 3* | Select the fastrpc domain |
Other Options | Acceptable Values( * denotes defaults ) | Description |
---|---|---|
BUILD | ReleaseG*, Debug, Release | Build Variant |
VERBOSE | 0*,1 | If VERBOSE=1 , it displays all the outputs from the build process. If VERBOSE is not defined, the build system displays only error messages. |
TREE | 0*,1 | TREE=0 cleans project build directory. TREE=1 cleans project build directory and dependency build directories |
-gMake | CMake Build uses Makefile Generator instead of default Ninja Generator when provided. | |
-j | <num> |
Enables to build the project using multiple threads. Default value of <num> is 1. |
Usage examples
Arguments to build_cmake
for some common usage examples are listed in the table below:
Arguments to build_cmake |
Description |
---|---|
hexagonsim | Builds binary for hexagon target and runs on simulator |
hexagon | Builds |
hexagon_clean | Cleans the hexagon build directory |
hexagon_clean TREE=1 | Cleans the hexagon build directory and the dependency build directories |
android | Builds Android target related files |
android_clean | Cleans the Android build directory |
android_clean TREE=1 | Cleans the example Android build directory and the dependency build directories |
ubuntuARM | Builds UbuntuARM 64-bit target related files |
ubuntuARM_clean HLOS_ARCH=32 | Cleans the UbuntuARM 32-bit build directory |
ubuntuARM_clean HLOS_ARCH=32 TREE=1 | Cleans the UbuntuARM 32-bit build directory and the dependency build directories if built |
android BUILD=ReleaseG HLOS_ARCH=32 | Builds ReleaseG variant of Android for 32-bit arch |
hexagon BUILD=Debug DSP_ARCH=v68 | Builds Debug variant of hexagon target V68 to run on top of QURT |
hexagon BUILD=Debug DSP_ARCH=v68 NO_QURT_INC=1 | Builds baremetal Debug variant of hexagon target V68 |
Note: Custom flags with values can be passed to the CMakeLists.txt through build commands. For example, in LPI example, to build libLPI.so we pass LPI flag with value 1 as build_cmake hexagon LPI=1
Mixing CMake and make.d build systems
Mixing of CMake and make.d is needed if a CMake-based project has a dependency on a library built only with make.d. In this scenario, the CMake project should invoke make.d commands to build the required libraries. This approach is illustrated in the benchmark example of the compute add-on.
Since all the Hexagon SDK libraries have make.d support, there should never be a case where a make.d project needs to invoke a CMake command.
CMake helper functions
The table below describes some CMake helper functions that are commonly used in building software:
Helper function | Usage summary | Documentation |
---|---|---|
find_library | Find a library in the specified locations | find_library |
add_dependencies | Add a dependency between top level targets | add_dependencies |
add_library | Add a library target, built from the sources specified | add_library |
target_link_directories | Specify the search paths for the linker | target_link_directories |
target_link_libraries | Specify the libraries to be used to link a given target | target_link_libraries |
add_custom_command | Add a custom build rule to the generated build system | add_custom_command |
ExternalProject_Add | Build a target from sources outside of the current CMake project | ExternalProject |
include_directories | Add the given directories to the include path of current CMake project | include_directories |
target_include_directories | Add the directories to the include path for a given target | target_include_directories |
add_executable | Add an executable target, built from the sources specified | add_executable |
set_target_properties | Set properties for the given targets | set_target_properties |
target_compile_definitions | Add compile definitions for a given target | target_compile_definitions |
file | Perform operations on the file system | file |
include | Include external build rules to the current project | include |
Hexagon CMake helper functions
The table below describes some CMake helper function that are present when you include $(HEXAGON_SDK_ROOT)/build/cmake/hexagon_fun.cmake
.
Helper function | Usage summary | Example |
---|---|---|
build_idl(<idlFile> <target>) |
Set up a custom_target to build <idlFile> using qaic IDL compiler and also add the custom_target created as the dependency of <target> |
build_idl(inc/calculator calculator) |
add_external_project(<target> SOURCE_DIR <library_source_dir> BYPPRODUCTS <list_variable> [ADDITIONAL_CMAKE_ARGS "<cmake args>"]) |
Takes the source directory of the library and list of binaries generated as arguments and calls cmake's ExternalProject_Add() with all the cmake variables needed by Hexagon SDK build system. ADDITIONAL_CMAKE_ARGS is an optional argument to pass cmake variables other than the default set by this function. BYPRODUCTS list is compulsory for Ninja Generator and is ignored with Makefile Generator. |
set(LIBS_GENERATED ${QHL_DIR}/${V}/libqhblas.a ${QHL_DIR}/${V}/libqhmath.a) add_external_project(qhl-target SOURCE_DIR $(HEXAGON_SDK_ROOT)/libs/qhl BYPRODUCTS LIBS_GENERATED) |
link_options(<target>) |
Set up the architecture-specific linker flags for the <target> |
link_options(calculator_device) |
link_custom_library(<target> <custom_library>) |
Build the <custom_library> and link to the target. To build the <custom_library> from source, use the BUILD_SOURCE flag. For example link_custom_library(<target> <custom_library> BUILD_SOURCE) . <custom_library> can take one of the following values: (rpcmem, atomic, test_util, rtld, qhl, qhl_hvx) |
link_custom_library(calculator_device rpcmem) |
choose_dsprpc("<domain>" <target>) |
Take <domain> as argument and return the corresponding remote library name in <target> . <domain> take values from 0-3 and default is 3(CDSP). |
choose_dsprpc("3", calculator) |
Add custom library as a dependency
Define the following variables for the user library to be added, in hexagon_fun.cmake
which is located at$HEXAGON_SDK_ROOT/build/cmake
. Follow these rules so that CMake build system can understand the custom library variables:
-
Define a variable
<library_name>_libs
- If the library is build as a static library, set the value of variable as
<library_name>.${LIB_EXT}
. For example, the variable for SDK libraryrpcmem
is defined asset(rpcmem_libs "rpcmem.${LIB_EXT}")
. - If the library is build as a dynamic library, set the value of variable as
lib<library_name>.${DLL_EXT}
. For example, the variable for SDK libraryworker_pool
is defined asset(worker_pool_libs "libworker_pool.${DLL_EXT}")
. - If both versions of custom library are build then use two variables with different names. For example, SDK library
asyncdspq
has two variables defined -set(asyncdspq_static_libs "asyncdspq.${LIB_EXT}")
for static library andset(asyncdspq_libs "libasyncdspq.${DLL_EXT}")
for dynamic library.
- If the library is build as a static library, set the value of variable as
-
Define a variable
<library_name>_incs
. Set its value to the directory containing the header files for the custom library. For example, this variable for SDK libraryrpcmem
is defined as:set(rpcmem_incs "${HEXAGON_SDK_ROOT}/ipc/fastrpc/rpcmem/inc")
-
Define a variable
<library_name>_struct
containing all the required information regarding the custom library. It will contain five fields:- Name for the custom library that should be used while linking to this library, in CMakeLists.txt
<library_name>_libs
variable<library_name>_incs
variable- Location of the prebuilt custom library. If no prebuilt library exists, use
""
- Location of the source code of custom library.
For example, this variable for SDK library
rpcmem
is defined as:set(rpcmem_struct "rpcmem" rpcmem_libs rpcmem_incs "${HEXAGON_SDK_ROOT}/ipc/fastrpc/rpcmem/prebuilt" "${HEXAGON_SDK_ROOT}/ipc/fastrpc/rpcmem")
-
Add
<library_name>_struct
toCUSTOM_LIBS_STRUCTS
-
Depending on whether the custom library is supported for HLOS or DSP, add its name to supported libs list.
- For DSP, add to
QURT_supported_libs
- For Android, add to
Android_supported_libs
- For UbuntuARM, add to
UbuntuARM_supported_libs
- For WoS, add to
Windows_supported_libs
- For QNX, add to
Qnx_supported_libs
- For DSP, add to
-
The custom library is now ready to be linked into any project build with CMake. You can use
link_custom_library
to add it as a dependency to a target. Additionally, specifyBUILD_SOURCE
as the third argument tolink_custom_library
to build the library from source.
Custom Toolchain
custom_toolchain.cmake
helps users to run HLOS toolchains not supported in the Hexagon SDK to compile the code. The table below contains target variables needed to be updated in custom_toolchain.cmake
.
Target variable | Description |
---|---|
CUSTOM_PREFIX | Full custom toolchain prefix |
CUSTOM_LIB_DIR | Path for finding target-specific libs |
RELEASE_FLAGS | Common compiler flags needed in the Release variant |
DEBUG_FLAGS | Common compiler flags needed in the Debug variant |
CXX_FLAGS | Specific compiler flags needed for building CXX-executable |
C_FLAGS | Specific compiler flags needed for building C-executable |
EXE_LD_FLAGS | Linker flags needed to build an executable |
DLL_LD_FLAGS | Linker flags needed to build a shared library |
To build with a custom toolchain, use any target name other than the pre-existing target names android, ubuntuARM, hexagon, qnx and windows in the build_cmake command. The output folder name will be <CUSTOM_NAME>_<BUILD_VARIANT>
for 32-bit Arch and <CUSTOM_NAME>_<BUILD_VARIANT>_aarch64
for 64-bit arch where <CUSTOM_NAME>
is the target name provided.
For example, to compile code for Debian HLOS.
- Update the
custom_toolchain.cmake
target specific variables mentioned above with Debian configurations. - To build an executable run
build_cmake debian BUILD=Debug HLOS_ARCH=32'. In the command
is
debian` and HLOS_ARCH is 32-bit. - The binaries built using the Debian toolchain will be available in the
debian_Debug
folder.
Additional Notes
-
In CMakeLists.txt file, the
CMAKE_SYSTEM_NAME
variable must match the<CUSTOM_NAME>
name passed withbuild_cmake
command. This variable can be used to add custom target code in CMakeLists.txt -
If the user is using both make.d and cmake build systems, clean the output directories before switching between build systems.
Transition from make.d to CMake
To convert a make.d project to CMake, create a CMakeLists.txt
file. This file will contain the build instructions equivalent to those specified in hexagon.min
, hexagon_deps.min
, android.min
, android_deps.min
, ubuntuARM.min
and ubuntuARM_deps.min
files.
The following list includes the various make.d commands and their corresponding CMake commands. All the build rules below are taken from the build files of benchmark
and calculator_c++
examples. Description for the variables used in the following list under make.d are specificed in build targets, tool variables and target-specific variables. Similarly, the details for the CMake functions used in these examples are enumerated in CMake helper functions, Hexagon CMake helper functions and add custom library as a dependency.
-
Build a dynamic (or shared) library
BUILD_DLLS += libcalculator_skel
add_library(calculator_skel SHARED <SRCS>)
-
Build a static library
BUILD_LIBS += libcalculator_skel
add_library(calculator_skel_static STATIC <SRCS>)
-
Build the executable targets
EXE_NAME=benchmark BUILD_EXES+=$(EXE_NAME)
set(srcs_app ${CMAKE_CURRENT_SOURCE_DIR}/src_app/warp_ref ${CMAKE_CURRENT_SOURCE_DIR}/src_app/dilate3x3_ref) add_executable(benchmark_device ${srcs_app}) set_target_properties(benchmark_device PROPERTIES OUTPUT_NAME "benchmark")
In make.d the binary
benchmark
is created from various sources defined using$(EXE_NAME)_C_SRCS
,$(EXE_NAME)_CPP_SRCS
,$(EXE_NAME)_DLLS
and so on.In CMake target name is suffixed with
_device
to make it different from stub name. Theset_target_properties
command renames thebenchmark_device
asbenchmark
. -
Include a build file
include abc.min
include(abc.cmake)
-
Include directories
INCDIRS += src_app/dsp_queue INCDIRS += incs/stddef
# Add the directories to the include path for current CMake project include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src_app/ ${HEXAGON_SDK_ROOT}/incs/stddef/) # Add the directories to the include path for a given target target_include_directories(benchmark_device PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
-
List of C source files
benchmark_q_C_SRCS+= src_app/dilate5x5_ref src_app/dilate3x3_ref
set(srcs_app ${CMAKE_CURRENT_SOURCE_DIR}/src_app/dilate5x5_ref ${CMAKE_CURRENT_SOURCE_DIR}/src_app/dilate3x3_ref) add_library(<TARGET_NAME> [STATIC | SHARED] ${srcs_app})
-
List of CPP source files
benchmark_q_CPP_SRCS += src_app/warp_ref src_app/benchmark
set(srcs_app ${CMAKE_CURRENT_SOURCE_DIR}/src_app/warp_ref ${CMAKE_CURRENT_SOURCE_DIR}/src_app/benchmark) add_library(<TARGET_NAME> [STATIC | SHARED] ${srcs_app})
-
List of ASM source files
libbenchmark_skel.ASM_SRCS += asm_src/dilate5x5_asm.S
set(srcs ${CMAKE_CURRENT_SOURCE_DIR}/asm_src/dilate5x5_asm.S) add_library(<TARGET_NAME> [STATIC | SHARED] ${srcs})
-
Rule to build IDL file
libbenchmark_skel_QAICIDLS += inc/benchmark
build_idl(inc/benchmark.idl benchmark)
IDL files are built with the QAIC compiler
-
Build the quick executables
BUILD_QEXES += benchmark_q benchmark_q_C_SRCS+= src_app/dilate5x5_ref src_app/dilate3x3_ref
set(srcs_app ${CMAKE_CURRENT_SOURCE_DIR}/src_app/warp_ref ${CMAKE_CURRENT_SOURCE_DIR}/src_app/dilate3x3_ref) add_library(benchmark_q SHARED ${srcs_app})
-
Specify arguments to Hexagon simulator
QEXE_SIM_OPTIONS +=--l2tcm_base 0xd800 --dsp_clock 1000
set(HEXAGON_EXEC_SIM_OPTIONS ${HEXAGON_EXEC_SIM_OPTIONS} --l2tcm_base 0xd800 --dsp_clock 1000)
-
Specify arguments to quick executable
QEXE_CMD_OPTIONS +=-f epsilon -w 256 -h 64 -r -k 0
set(HEXAGON_EXEC_CMD_OPTIONS ${HEXAGON_EXEC_CMD_OPTIONS} -f transpose -w 256 -h 64 -r -k 0)
-
Specify additional linker flags for a specific shared object or executable target
benchmark_LD_FLAGS += -ldl
target_link_options(benchmark PUBLIC "-ldl")
-
Specify additional defines that are added when building an object
benchmark_DEFINES += VERIFY_PRINT_ERROR
target_compile_definitions(benchmark_device PUBLIC VERIFY_PRINT_ERROR)
-
Link CPP library to the target
CXX_FLAGS += -std=c++14 TARGET_DIR = $(HEXAGON_LIB_DIR)/$(V_ARCH)/G0/pic libcalculator_plus_skel_DLLS += $(TARGET_DIR)/libc++ libcalculator_plus_skel_DLLS += $(TARGET_DIR)/libc++abi $(V)/libcalculator_plus_skel.so: $(V)/libc++.so.1 $(V)/libc++abi.so.1 $(V)/libc++.so.1: $(V)/libc++abi.so.1 $(call cp_af,$(TARGET_DIR)/libc++.so.1 $(V))\ $(call cp_af,$(TARGET_DIR)/libc++.so.1.0 $(V)) $(V)/libc++abi.so.1: $(call mkdir_p,$(V)) $(call cp_af,$(TARGET_DIR)/libc++abi.so.1 $(V)) $(call cp_af,$(TARGET_DIR)/libc++abi.so.1.0 $(V))
target_link_libraries(calculator_plus_skel ${HEXAGON_LIB_DIR}/${HEXAGON_ARCH}/G0/pic/libc++abi.so.1) target_link_libraries(calculator_plus_skel ${HEXAGON_LIB_DIR}/${HEXAGON_ARCH}/G0/pic/libc++.so.1 ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions -std=c++14") file(COPY ${HEXAGON_LIB_DIR}/${HEXAGON_ARCH}/G0/pic/libc++abi.so.1 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) file(COPY ${HEXAGON_LIB_DIR}/${HEXAGON_ARCH}/G0/pic/libc++.so.1 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) file(COPY ${HEXAGON_LIB_DIR}/${HEXAGON_ARCH}/G0/pic/libc++abi.so.1.0 DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) file(COPY ${HEXAGON_LIB_DIR}/${HEXAGON_ARCH}/G0/pic/libc++.so.1.0 DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
-
Define a custom variable
NO_QURT_INC = 1
set(NO_QURT_INC 1)
-
Link rule for a existing Hexagon SDK library
benchmark_q_LIBS += getopt_custom
link_custom_library(benchmark_q getopt_custom)
-
Specify additional compiler flags for a specific shared object or executable target
benchmark_CC_FLAGS += -fPIC -ffunction-sections
target_compile_options(benchmark PUBLIC -fPIC -ffunction-sections)
NOTE: In CMake buildsystem, user can specify additional compiler flags for particular source file like below:
set_source_files_properties(benchmark.cpp PROPERTIES COMPILE_OPTIONS -fPIC -ffunction-sections)
-
Add a rule to link an external dependent library for the hexagon project
GNU make
It is possible to construct traditional GNU makefiles for Hexagon SDK projects. One example is given at $HEXAGON_SDK_ROOT/examples/qhl.
Building Android application
Steps to build an Android application are mentioned in C++_APK example
Using libraries residing on target
Some APIs are implemented directly in the Hexagon DSP image.
This is the case for example for memscpy
or HAP_power_request
.
Projects that use these libraries need to specify test_util as a library dependency to the project in order to be able to run the application on the hexagon simulator.
Reference documents
Reference documents for compiler and linker
Documentation on the Hexagon toolchain is provided as part of the Hexagon SDK: * Compiler documentation * Linker section in Hexagon Utilities documentation
Interface Description Language (IDL)
The IDL used in the SDK describes the interface between the application processor and the Hexagon DSPs communicating using FastRPC.