This topic describes some advanced ways of using the CMake templates.

Building a Widget

To build a widget, you need a config.xml file that describes your application (widget) and how the Application Framework launches it. Your repository contains a simple default file named config.xml.in that should work for simple applications and should not require interactions with other bindings.

It is also recommended that you use the sample configuration file that you can find in the location. This file is named config.xms.in.sample and is more complete. Copy the sample file to your conf.d/wgt directory and name it config.xml.in. Once you have your copy, edit the file to fit your needs.

CAUTION: The default file is only meant to be used for a simple widget application. For more complicated applications that need to export their API, or ship several applications in one widget need to use the provided config.xml.in.sample file, which has all new Application Framework features explained and provides examples.

Using CMake Template Macros

To leverage all CMake template features, you must specify properties on your targets. Some macros do not work unless you specify the target type. If you do not specify a type (e.g. a custom target such as an HTML5 application), the macro uses the LABELS property to determine the target type.

Aside from those values, the following optional values can be assigned to the LABELS property. These values define the resource types that make up your test materials:

Following is a mapping between LABELS and directories where files reside in the widget:

Following is a mapping between test-dedicated LABELS and directories where files reside in the widget:

TIP: Use the prefix afb- (Application Framework Binding) with your BINDING targets.

Following is an example that sets the LABELS and OUTPUT_NAME properties:

SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
        LABELS "HTDOCS"
        OUTPUT_NAME dist.prod
    )

NOTE: You do not need to specify an INSTALL command for these targets. Installation is handled by the template and installs using the following path : ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}

Also, if you want to set and use rpath with your target, you should use and set the target property INSTALL_RPATH.

Adding an External Third-Party Library

You can add an external third-party library that is built, linked, and shipped with the project. Or, you can link and ship the library only with the project.

Building, Linking, and Shipping an External Library with the Project

If you need to include an external library that is not shipped with the project, you can bundle the required library in the lib widget directory.

Templates includes facilities to help you work with external libraries. A standard method is to declare as many CMake ExternalProject modules as you need to match the number of needed libraries.

An ExternalProject module is a special CMake module that lets you define how to download, update, patch, configure, build, and install an external project. The project does not need to be a CMake project. Additionally, you can provide custom steps to account for special needs using ExternalProject step. See the CMake ExternalProject documentation site for more information.

Following is an example that includes the mxml library for the unicens2-binding project:

set(MXML external-mxml)
set(MXML_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/mxml)
ExternalProject_Add(${MXML}
    GIT_REPOSITORY https://github.com/michaelrsweet/mxml.git
    GIT_TAG release-2.10
    SOURCE_DIR ${MXML_SOURCE_DIR}
    CONFIGURE_COMMAND ./configure --build x86_64 --host aarch64
    BUILD_COMMAND make libmxml.so.1.5
    BUILD_IN_SOURCE 1
    INSTALL_COMMAND ""
)

PROJECT_TARGET_ADD(mxml)

add_library(${TARGET_NAME} SHARED IMPORTED GLOBAL)

SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
    LABELS LIBRARY
    IMPORTED_LOCATION ${MXML_SOURCE_DIR}/libmxml.so.1
    INTERFACE_INCLUDE_DIRECTORIES ${MXML_SOURCE_DIR}
)

add_dependencies(${TARGET_NAME} ${MXML})

The example defines an external project that drives the building of the library. The example also defines a new CMake target whose type is IMPORTED. The IMPORTED target type indicates the target has yet to be built using CMake but is available at the location defined using the IMPORTED_LOCATION target property.

You might want to build the library as SHARED or STATIC depending on your needs and goals. Next, the example only has to modify the external project configure step and change the filename used by IMPORTED library target defined after external project.

The target's LABELS property is set to LIBRARY to ship it in the widget.

In this example, the Unicens project also needs header information from this library. Consequently, the INTERFACE_INCLUDE_DIRECTORIES target property is used. Setting that property when another target links to that imported target allows access to included directories.

Finally, the example binds the target to the external project by using a CMake dependency.

The target can now be linked and used like any other CMake target.

If you already have a binary version of the library that you want to use and you cannot or do not want to build the library, you can use the IMPORTED library target.

To illustrate, consider the same example in the previous section. Following are the relevant modifications:

PROJECT_TARGET_ADD(mxml)

add_library(${TARGET_NAME} SHARED IMPORTED GLOBAL)

SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
    LABELS LIBRARY
    IMPORTED_LOCATION /path_to_library/libmxml.so.1
    INTERFACE_INCLUDE_DIRECTORIES /path_to_mxml/include/dir
)

In the previous example, notice the changes to the IMPORTED_LOCATION and INTERFACE_INCLUDE_DIRECTORIES statements. These locate the binary version of the library.

Finally, you can link any other library or executable target with this imported library just as you would for any other target.

Macro Reference

Following are several macros that are useful for advanced CMake usage.

PROJECT_TARGET_ADD

This macro adds the target to your project. Following is a typical example that adds the target to your project. You need to provide the name of your target as the macro's parameter:

Example:

PROJECT_TARGET_ADD(low-can-demo)

The macro makes the variable ${TARGET_NAME} available and it is defined using the specified name (e.g. low-can-demo). The variable changes each time the PROJECT_TARGET_ADD macro is called.

project_subdirs_add

This macro searches within specified subfolders of the CMake project for any CMakeLists.txt file. If the file is found, it is added to your project. You can use this macro in a hybrid application (e.g. where the binding exists in a subfolder).

The following example searches within all subfolders:

Usage :

project_subdirs_add()

You might want to restrict the subfolders being searched. If so, you can specify a globbing pattern as the argument. Doing so effectively creates a search filter.

Following is an example that specifies all directories that begin with a number, are followed by the dash character, and then followed by any characters:

project_subdirs_add("[0-9]-*")

set_openapi_filename

This macro is used with a BINDINGV2 target and defines the binding definition filename. You can use it to also define a relative path to the current CMakeLists.txt file.

If you do not use this macro to specify the name of your definition file, the default one is used, which is ${OUTPUT_NAME}-apidef and uses OUTPUT_NAME as the target property.

CAUTION When specifying the binding definition filename, you must not use the file's extension as part of the name. Following is an example:

set_openapi_filename('binding/mybinding_definition')

add_input_files

This macro creates a custom target dedicated for HTML5 and data resource files. The macro provides syntax and schema verification for different languages that include LUA, JSON and XML.

Alongside the macro are tools used to check files. You can configure the tools by setting the following variables:

Following is an example:

add_input_file("${MY_FILES_LIST}")

NOTE: If an issue occurs during the "check" step of the macro, the build halts.