Skip to content

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 DSP
  • android, for building rules applying to the application processor running Android
  • UbuntuARM, 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.
`_ASM_SRCS 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 _DIR is defined for any of these libraries, the make system will recurse to that directory to update the library dependency.
`_DIR Similar to _LIBS.
<targetName>_DLLS Specifies a list of shared objects from which symbols will be imported (similar to IMPLIB).
`_RCS 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 _ZIP_SRCHROOT. Wildcards are supported for directories and files.
<targetName>_ZIP_SRCHROOT Specifies the base path for files listed in _ZIP_SPEC. Paths in the ZIP file are relative to this base.
<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.
`_CC 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 _skel.so
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 library rpcmem is defined as set(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 library worker_pool is defined as set(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 and set(asyncdspq_libs "libasyncdspq.${DLL_EXT}") for dynamic library.
  • 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 library rpcmem 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:

    1. Name for the custom library that should be used while linking to this library, in CMakeLists.txt
    2. <library_name>_libs variable
    3. <library_name>_incs variable
    4. Location of the prebuilt custom library. If no prebuilt library exists, use ""
    5. 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 to CUSTOM_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
  • 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, specify BUILD_SOURCE as the third argument to link_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 commandisdebian` 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 with build_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.

  1. Build a dynamic (or shared) library

    BUILD_DLLS += libcalculator_skel
    
    add_library(calculator_skel SHARED <SRCS>)
    
  2. Build a static library

    BUILD_LIBS += libcalculator_skel
    
    add_library(calculator_skel_static STATIC <SRCS>)
    
  3. 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. The set_target_properties command renames the benchmark_device as benchmark.

  4. Include a build file

    include abc.min
    
    include(abc.cmake)
    
  5. 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)
    
  6. 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})
    
  7. 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})
    
  8. 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})
    
  9. Rule to build IDL file

    libbenchmark_skel_QAICIDLS += inc/benchmark
    
    build_idl(inc/benchmark.idl benchmark)
    

    IDL files are built with the QAIC compiler

  10. 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})
    
  11. 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)
    
  12. 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)
    
  13. Specify additional linker flags for a specific shared object or executable target

    benchmark_LD_FLAGS += -ldl
    
    target_link_options(benchmark PUBLIC "-ldl")
    
  14. Specify additional defines that are added when building an object

    benchmark_DEFINES += VERIFY_PRINT_ERROR
    
    target_compile_definitions(benchmark_device PUBLIC VERIFY_PRINT_ERROR)
    
  15. 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})
    
  16. Define a custom variable

    NO_QURT_INC = 1
    
    set(NO_QURT_INC 1)
    
  17. Link rule for a existing Hexagon SDK library

    benchmark_q_LIBS += getopt_custom
    
    link_custom_library(benchmark_q getopt_custom)
    
  18. 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)
    
  19. Add a rule to link an external dependent library for the hexagon project

    • To add an external dependent library to the existing hexagon project, a user may follow specific rules for the respective make.d and CMake build system.

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.