Main Content

Customize Template Makefiles

To configure or customize a template makefile (TMF), you should be familiar with how the make command works and how it processes a makefile (.mk file). You should also understand makefile build rules. For information on these topics, refer to the documentation provided with the make utility that you use.

Template Makefiles and Tokens

A template makefile contains tokens. The build process expands the tokens and creates makefiles:

  • model.mk –– Compiles and links code generated from model components.

  • rtwshared.mk –– Compiles generated shared utility code.

The makefiles (model_or_sharedutils.mk) use commands that are specific to your development computer.

Template Makefile Tokens

The make_rtw command (or a different command provided with some targets) directs the process of generating model_or_sharedutils.mk. The make_rtw command processes the TMF specified on the Code Generation pane of the Configuration Parameters dialog box. make_rtw copies the TMF, line by line, expanding each token encountered. Template Makefile Tokens Expanded by make_rtw lists the tokens and their expansions.

These tokens are used in several ways by the expanded makefile:

  • To control the conditional behavior in the makefile. The conditionals are used to control the source file lists, library names, target to be built, and other build-related information.

  • To provide the macro definitions for compiling the files, for example, -DINTEGER_CODE=1.

Template Makefile Tokens Expanded by make_rtw

TokenExpansion
General purpose

|>ADDITIONAL_LDFLAGS<|

Linker flags automatically added by blocks.

|>ALT_MATLAB_BIN<|

Alternate full pathname for the MATLAB® executable; value is different than value for MATLAB_BIN token when the full pathname contains spaces.

|>ALT_MATLAB_ROOT<|

Alternate full pathname for the MATLAB installation; value is different than value for MATLAB_ROOT token when the full pathname contains spaces.

|>BUILDARGS<|

Options passed to make_rtw. This token is provided so that the contents of your model_or_sharedutils.mk file change when you change the build arguments, thus forcing an update of modules when your build options change.

|>COMBINE_OUTPUT_UPDATE_FCNS<|

True (1) when you select model configuration parameter Single output/update function, otherwise False (0). Used for the macro definition -DONESTEPFCN=1.

|>COMPILE_FLAGS_OTHER<|

Compiler flags in a group other than 'OPTS', 'OPT_OPTS', and 'OPTIMIZATION_FLAGS'. The build process produces a warning if |>COMPILE_FLAGS_OTHER<| is absent and these conditions apply:

  • The build information contains a compiler flag that is not in 'OPTS', 'OPT_OPTS', or 'OPTIMIZATION_FLAGS'.

  • The compiler flag is not in the template makefile.

|>COMPUTER<|

Computer type. See the MATLAB computer command.

|>DEFINES_OTHER<|

Preprocessor macro definitions in a group other than 'OPTS', 'OPT_OPTS', 'OPTIMIZATION_FLAGS', and 'Custom'.

A preprocessor macro definition in 'OPTS', 'OPT_OPTS', 'OPTIMIZATION_FLAGS', or 'Custom' that has a corresponding variable/token pair in the template makefile is not expanded in DEFINES_OTHER. This behavior helps to avoid the provision of duplicate preprocessor macro definitions.

For example, some template makefiles contain these statements:

...
NUMST = |>NUMST<|
...
CPP_REQ_DEFINES1 = ... -DNUMST=$(NUMST) ...
If the template makefile contains the variable/token pair NUMST = |>NUMST<| and NUMST is a preprocessor macro definition in buildInfo, then the build process does not expand it in DEFINES_OTHER.

The build process produces a warning if |>DEFINES_OTHER<| is absent and these conditions apply:

  • The build information contains a preprocessor macro definition that is not in 'OPTS', 'OPT_OPTS', 'OPTIMIZATION_FLAGS', or 'Custom'.

  • The preprocessor macro definition, for example, NUMST, is not in the template makefile.

|>EXPAND_LIBRARY_LOCATION<|

Location of precompiled library file. The TargetPreCompLibLocation configuration parameter can override this setting. For examples, see Control Library Location and Naming During Build.

|>EXPAND_LIBRARY_NAME<|

Library name. For examples, see Control Library Location and Naming During Build and Modify the Template Makefile for rtwmakecfg.

|>EXPAND_LIBRARY_SUFFIX<|

Library suffix. The TargetLibSuffix configuration parameter can override this setting. For examples, see Control Library Location and Naming During Build.

|>EXT_MODE<| (Not required for R2018a and later provided template makefile specifies TOOLCHAIN_NAME)

True (1) to enable generation of external mode support code, otherwise False (0).

|>EXTMODE_TRANSPORT<| (Not required for R2018a and later provided template makefile specifies TOOLCHAIN_NAME)

Index of transport mechanism (for example, tcpip, serial) for external mode.

|>EXTMODE_STATIC<| (Not required for R2018a and later provided template makefile specifies TOOLCHAIN_NAME)

True (1) if static memory allocation is selected for external mode. False (0) if dynamic memory allocation is selected.

|>EXTMODE_STATIC_SIZE<| (Not required for R2018a and later provided template makefile specifies TOOLCHAIN_NAME)

Size of static memory allocation buffer for external mode.

|>GENERATE_ERT_S_FUNCTION<|

True (1) when model configuration parameter Create block is set to SIL, otherwise False (0). Used for control of the makefile target of the build.

|>INCLUDE_MDL_TERMINATE_FCN<|

True (1) when model configuration parameter Terminate function required is selected, otherwise False (0). Used for the macro definition -DTERMFCN==1.

|>INTEGER_CODE<|

True (1) when model configuration parameter Support floating-point numbers is cleared, otherwise False (0). INTEGER_CODE is a required macro definition when compiling the source code and is used when selecting precompiled libraries to link against.

|>MAKEFILE_NAME<|

model_or_sharedutils.mk — The name of the makefile that was created from the TMF.

|>MAT_FILE<|

True (1) when model configuration parameter MAT-file logging is selected, otherwise False (0). MAT_FILE is a required macro definition when compiling the source code and also is used to include logging code in the build process.

|>MATLAB_BIN<|

Location of the MATLAB executable program.

|>MATLAB_ROOT<|

Path to where MATLAB is installed.

|>MEM_ALLOC<|

RT_MALLOC or RT_STATIC. Indicates how memory is to be allocated.

|>MEXEXT<|

MEX-file extension. See the MATLAB mexext command.

|>MODEL_MODULES<|

Additional generated source modules. For example, you can split a large model into two files, model.c and model1.c. In this case, this token expands to model1.c.

|>MODEL_MODULES_OBJ<|

Object filenames (.obj) corresponding to additional generated source modules.

|>MODEL_NAME<|

Name of the Simulink® block diagram currently being built.

|>MULTITASKING<|

True (1) if solver mode is multitasking, otherwise False (0).

|>NCSTATES<|

Number of continuous states.

|>NUMST<|

Number of sample times in the model.

|>RELEASE_VERSION<|

The MATLAB release version.

|>S_FUNCTIONS_LIB<|

List of S-function libraries available for linking.

|>SOLVER<|

Solver source filename, for example, ode3.c.

|>SOLVER_OBJ<|

Solver object (.obj) filename, for example, ode3.obj.

|>TARGET_LANG_EXT<|

c when model configuration parameter Language is set to C, cpp when Language is set to C++. Used in the makefile to control the extension on generated source files.

|>TID01EQ<|

True (1) if sampling rates of the continuous task and the first discrete task are equal, otherwise False (0).

S-function and build information support

Note

For examples of the tokens in this section, see Modify the Template Makefile for rtwmakecfg.

|>START_EXPAND_INCLUDES<|
|>EXPAND_DIR_NAME<|
|>END_EXPAND_INCLUDES<|

List of folder names to add to the include path. Additionally, the ADD_INCLUDES macro must be added to the INCLUDES line.

|>START_EXPAND_LIBRARIES<|
|>EXPAND_LIBRARY_NAME<|
|>END_EXPAND_LIBRARIES<|

List of library names.

|>START_EXPAND_MODULES<|
|>EXPAND_MODULE_NAME<|
|>END_EXPAND_MODULES<|

Library module names within |>START_EXPAND_LIBRARIES<| and |>START_PRECOMP_LIBRARIES<| library lists.

|>START_EXPAND_RULES<|
|>EXPAND_DIR_NAME<|
|>END_EXPAND_RULES<|

Makefile rules.

|>START_PRECOMP_LIBRARIES<|
|>EXPAND_LIBRARY_NAME<|
|>END_PRECOMP_LIBRARIES<|

List of precompiled library names.

Model reference support

Note

For examples of the tokens in this section, see Providing Model Referencing Support in the TMF.

|>MASTER_ANCHOR_DIR<|

For parallel builds, current work folder (pwd) at the time the build started.

|>MODELLIB<|

Name of the library file generated for the current model.

|>MODELREFS<|

List of models referenced by the top model.

|>MODELREF_LINK_LIBS<|

List of referenced model libraries against which the top model links.

|>MODELREF_LINK_RSPFILE_NAME<|

Name of a response file against which the top model links. This token is valid only for build environments that support linker response files. For an example of its use, see matlabroot/toolbox/coder/compile/tmf/grt_vcx64.tmf.

|>MODELREF_TARGET_TYPE<|

Type of target being built. Possible values are

  • NONE: Standalone model or top model referencing other models

  • RTW: Model reference target build

  • SIM: Model reference simulation target build

|>RELATIVE_PATH_TO_ANCHOR<|

Relative path, from the location of the generated makefile, to the MATLAB working folder.

|>START_DIR<|

Code generation folder at the time the build started. This token is required for parallel builds.

These tokens are expanded by substitution of parameter values known to the build process. For example, if the source model contains blocks with two different sample times, the TMF statement

NUMST = |>NUMST<|

expands to:

NUMST = 2

In addition to the above, make_rtw expands tokens from other sources:

  • Target-specific tokens defined in the target options of the Configuration Parameters dialog box

  • Structures in the rtwoptions section of the system target file. Structures in the rtwoptions structure array that contain the field makevariable are expanded.

The following example is extracted from matlabroot/rtw/c/grt/grt.tlc. The section starting with BEGIN_RTW_OPTIONS contains MATLAB code that sets up rtwoptions. The following directive causes the |>EXT_MODE<| token to be expanded to 1 (on) or 0 (off), depending on how you set the external mode options.

rtwoptions(2).makevariable = 'EXT_MODE'

Invoke the make Utility

make Command

After creating model_or_sharedutils.mk from your TMF, the build process invokes a make command. To invoke make, the build process issues this command.

makecommand -f model_or_sharedutils.mk

makecommand is defined by the MAKECMD macro in your system target file TMF (see Structure of the Template Makefile). You can specify additional options to make by using the model configuration parameter Make command. (See the sections Specify a Make Command and Template Makefiles and Make Options.)

For example, specifying OPT_OPTS=-O2 in the Make command field causes make_rtw to generate the following make command.

makecommand -f model_or_sharedutils.mk OPT_OPTS=-O2

A comment at the top of the TMF specifies the available make command options. If these options do not provide you with enough flexibility, you can configure your own TMF.

make Utility Versions

The make utility lets you control nearly every aspect of building your real-time program. There are several different versions of make available. The code generator provides the Free Software Foundation GNU® make for both UNIX®[1] and PC platforms in platform-specific subfolders under

matlabroot/bin

It is possible to use other versions of make with the code generator, although GNU Make is recommended. To be compatible with the code generator, verify that your version of make supports the following command format.

makecommand -f model_or_sharedutils.mk

Structure of the Template Makefile

A TMF has multiple sections, including the following:

  • Abstract — Describes what the makefile targets. Here is a representative abstract from the ERT TMFs in matlabroot/toolbox/coder/compile/tmf:

    # Abstract:
    #       Template makefile for building a Windows-based stand-alone embedded
    #       real-time version of Simulink model using generated C code and the
    #          Microsoft Visual C/C++ compiler for x64.
    #
    #       Note that this template is automatically customized by the build 
    #       procedure to create "<model>.mk"
    #
    #       The following defines can be used to modify the behavior of the
    #       build:
    #         OPT_OPTS       - Optimization option. See DEFAULT_OPT_OPTS in
    #                          vctools.mak for default.
    #         OPTS           - User specific options.
    #         CPP_OPTS       - C++ compiler options.
    #         USER_SRCS      - Additional user sources, such as files needed by
    #                          S-functions.
    #         USER_INCLUDES  - Additional include paths
    #                          (i.e. USER_INCLUDES="-Iwhere-ever -Iwhere-ever2")
    #
    #       To enable debugging:
    #         set DEBUG_BUILD = 1, which will trigger OPTS=-Zi (may vary with
    #                               compiler version, see compiler doc) 
    #
    #       This template makefile is designed to be used with a system target
    #       file that contains 'rtwgensettings.BuildDirSuffix' see ert.tlc
  • Macros read by make_rtw section — Defines macros that tell make_rtw how to process the TMF. Here is a representative Macros read by make_rtw section from the GRT TMFs in matlabroot/toolbox/coder/compile/tmf:

    #------------------------ Macros read by make_rtw -----------------------------
    #
    # The following macros are read by the build procedure:
    #
    #  MAKECMD         - This is the command used to invoke the make utility
    #  HOST            - What platform this template makefile is targeted for
    #                    (i.e. PC or UNIX)
    #  BUILD           - Invoke make from the build procedure (yes/no)?
    #  SYS_TARGET_FILE - Name of system target file.
    
    MAKECMD         = nmake
    HOST            = PC
    BUILD           = yes
    SYS_TARGET_FILE = any
    BUILD_SUCCESS	= ^#^#^# Created
    
    # Opt in to simplified format by specifying compatible Toolchain
    TOOLCHAIN_NAME = [\
        "Microsoft Visual C++ 2019 v16.0 | nmake (64-bit Windows)", \
        "Microsoft Visual C++ 2017 v15.0 | nmake (64-bit Windows)", \
        "Microsoft Visual C++ 2015 v14.0 | nmake (64-bit Windows)"]
    

    The macros in this section might include:

    • MAKECMD — Specifies the command used to invoke the make utility. For example, if MAKECMD = mymake, then the make command invoked is

      mymake -f model_or_sharedutils.mk

    • HOST — Specifies the platform targeted by this TMF. This can be PC, UNIX, computer_name (see the MATLAB computer command), or ANY.

    • BUILD — Instructs make_rtw whether or not it should invoke make from the build procedure. Specify yes or no.

    • SYS_TARGET_FILE — Specifies the name of the system target file or the value any. This is used for consistency checking by make_rtw to verify the system target file specified in the Target selection panel of the Code Generation pane of the Configuration Parameters dialog box. If you specify any, you can use the TMF with any system target file.

    • BUILD_SUCCESS — When the makefile creates a static library, it produces the BUILD_SUCCESS string as defined, for example, by this rule in ert_vcx64.tmf:

      $(PRODUCT) : $(OBJS) $(LIBS) $(MODELREF_LINK_LIBS)
      	@cmd /C "echo ### Linking ..."
      	$(LD) $(LDFLAGS) $(LIBS) \
          @$(CMD_FILE) @$(MODELREF_LINK_RSPFILE) -dll -def:$(MODEL).def -out:$@
      	@cmd /C "echo $(BUILD_SUCCESS) dynamically linked library  $(PRODUCT)"
      

      When the build process finds the BUILD_SUCCESS string, it polls for the existence of the updated static library file. The build process does not link the library file to the executable file until the build process can confirm the presence of the library file, with an updated timestamp, on the file system.

      If the build process does not find BUILD_SUCCESS in the compilation log, then the build process assumes that the updated library archive is available on the file system. If required, the build process links the library to the executable file.

  • Tokens expanded by make_rtw section — Defines the tokens that make_rtw expands. Here is a brief excerpt from a representative Tokens expanded by make_rtw section from the ERT TMFs in matlabroot/toolbox/coder/compile/tmf/:

    #---------------------- Tokens expanded by make_rtw ----------------------------
    #
    # The following tokens, when wrapped with "|>" and "<|" are expanded by the
    # build procedure.
    #
    #  MODEL_NAME          - Name of the Simulink block diagram
    #  MODEL_MODULES       - Any additional generated source modules
    #  MAKEFILE_NAME       - Name of makefile created from template makefile <model>.mk
    #  MATLAB_ROOT         - Path to where MATLAB is installed.
    ...
    
    MODEL                   = |>MODEL_NAME<|
    MODULES                 = |>MODEL_MODULES<|
    PRODUCT                 = |>PRODUCT<|
    MAKEFILE                = |>MAKEFILE_NAME<|
    MATLAB_ROOT             = |>MATLAB_ROOT<|
    ...

    For more information about TMF tokens, see Template Makefile Tokens Expanded by make_rtw.

  • Subsequent sections vary based on compiler, host, and target. Some common sections include Model and reference models, External mode, Tool Specifications or Tool Definitions, Include Path, C Flags, Additional Libraries, and Source Files.

  • Rules section — Contains the make rules used in building an executable from the generated source code. The build rules are typically specific to your version of make. The Rules section might be followed by related sections such as Dependencies.

Customize and Create Template Makefiles

Introduction

This section describes the mechanics of setting up a custom template makefile (TMF) and incorporating it into the build process. It also discusses techniques for modifying a TMF and MATLAB file mechanisms associated with the TMF.

Before creating a custom TMF, you should read Folder and File Naming Conventions to understand the folder structure and MATLAB path requirements for custom targets.

Setting Up a Template Makefile

To customize or create a new TMF, copy an existing GRT or ERT TMF from matlabroot/toolbox/coder/compile/tmf.

Place the copy in the same folder as the associated system target file. Usually, this is the mytarget/mytarget folder within the target folder structure. Then, rename your TMF (for example, mytarget.tmf) and modify it.

To allow the build process to locate and select your TMF, you must provide information in the system target file file header (see System Target File Structure). For a target that implements a single TMF, the standard way to specify the TMF to be used in the build process is to use the TMF directive of the system target file file header.

TMF: mytarget.tmf

Using Macros and Pattern Matching Expressions in a Template Makefile

This section shows, through an example, how to use macros and file-pattern-matching expressions in a TMF to generate commands in model_or_sharedutils.mk.

The make utility processes model_or_sharedutils.mk and generates a set of commands based upon dependency rules defined in model_or_sharedutils.mk. After make generates the set of commands for building or rebuilding test, make executes them.

For example, to build a program called test, make must link the object files. However, if the object files don't exist or are out of date, make must compile the source code. Thus there is a dependency between source and object files.

Each version of make differs slightly in its features and how rules are defined. For example, consider a program called test that gets created from two sources, file1.c and file2.c. Using most versions of make, the dependency rules would be

test: file1.o file2.o
        cc -o test file1.o file2.o

file1.o: file1.c
        cc -c file1.c

file2.o: file2.c
        cc -c file2.c

In this example, a UNIX[2] environment is assumed. In a PC environment the file extensions and compile and link commands are different.

In processing the first rule

test: file1.o file2.o

make sees that to build test, it needs to build file1.o and file2.o. To build file1.o, make processes the rule

file1.o: file1.c

If file1.o doesn't exist, or if file1.o is older than file1.c, make compiles file1.c.

The format of TMFs follows the above example. Our TMFs use additional features of make such as macros and file-pattern-matching expressions. In most versions of make, a macro is defined with

MACRO_NAME = value

References to macros are made with $(MACRO_NAME). When make sees this form of expression, it substitutes value for $(MACRO_NAME).

You can use pattern matching expressions to make the dependency rules more general. For example, using GNU[3] Make, you could replace the two “file1.o: file1.c” and “file2.o: file2.c” rules with the single rule

%.o : %.c
        cc -c $<

Note that $< in the previous example is a special macro that equates to the dependency file (that is, file1.c or file2.c). Thus, using macros and the "%" pattern matching character, the previous example can be reduced to

SRCS = file1.c file2.c
OBJS = $(SRCS:.c=.o)

test: $(OBJS)
        cc -o $@ $(OBJS)

%.o : %.c
        cc -c $<

Note that the $@ macro above is another special macro that equates to the name of the current dependency target, in this case test.

This example generates the list of objects (OBJS) from the list of sources (SRCS) by using the text substitution feature for macro expansion. It replaces the source file extension (for example, .c) with the object file extension (.o). This example also generalized the build rule for the program, test, to use the special "$@" macro.

Customizing Generated Makefiles with rtwmakecfg

TMFs provide tokens that let you add the following items to generated makefiles:

  • Source folders

  • Include folders

  • Run-time library names

  • Run-time module objects

S-functions can add this information to the makefile by using an rtwmakecfg.m file function. This function is particularly useful when building a model that contains one or more of your S-Function blocks, such as device driver blocks.

To add information pertaining to an S-function to the makefile,

  1. Create the function rtwmakecfg in file rtwmakecfg.m. The code generator associates this file with your S-function based on its folder location.

  2. Modify your target's TMF such that it supports macro expansion for the information returned by rtwmakecfg functions.

After the TLC phase of the build process, when generating a makefile from the TMF, the build process searches for an rtwmakecfg.m file in the folder that contains the S-function component. If it finds the file, the build process calls the rtwmakecfg function. For more information, see Use rtwmakecfg.m API to Customize Generated Makefiles.

Supporting Continuous Time in Custom Targets

If you want your custom ERT-based target to support continuous time, you must update your template makefile (TMF) and the static main program module (for example, mytarget_main.c) for your target.

Template Makefile Modifications.  Add the NCSTATES token expansion after the NUMST token expansion, as follows:

NUMST = |>NUMST<|
NCSTATES = |>NCSTATES<|

In addition, add NCSTATES to the CPP_REQ_DEFINES macro, as in the following example:

CPP_REQ_DEFINES = -DMODEL=$(MODEL) -DNUMST=$(NUMST) -DNCSTATES=$(NCSTATES) \
-DMAT_FILE=$(MAT_FILE)
-DINTEGER_CODE=$(INTEGER_CODE) \
-DONESTEPFCN=$(ONESTEPFCN) -DTERMFCN=$(TERMFCN) \
-DHAVESTDIO
-DMULTI_INSTANCE_CODE=$(MULTI_INSTANCE_CODE) \

Modifications to Main Program Module.  The main program module defines a static main function that manages task scheduling for the supported tasking modes of single- and multiple-rate models. NUMST (the number of sample times in the model) determines whether the main function calls multirate or single-rate code. However, when a model uses continuous time, do not rely on NUMST directly.

When the model has continuous time and the flag TID01EQ is true, both continuous time and the fastest discrete time are treated as one rate in generated code. The code associated with the fastest discrete rate is guarded by a major time step check. When the model has only two rates, and TID01EQ is true, the generated code has a single-rate call interface.

To support models that have continuous time, update the static main module to take TID01EQ into account, as follows:

  1. Before NUMST is referenced in the file, add the following code:

    #if defined(TID01EQ) && TID01EQ == 1 && NCSTATES == 0
    #define DISC_NUMST (NUMST - 1)
    #else
    #define DISC_NUMST NUMST
    #endif
  2. Replace instances of NUMST in the file by DISC_NUMST.

Model Reference Considerations

See Support Model Referencing for important information on TMF modifications you may need to make to support the code generator model referencing features.

Note

If you are using a TMF without the variable MODELREFS, the file might have been used with a previous release of Simulink software. If you want your TMF to support model referencing, add MODELREFS to the make file.

Timeout Error When Building Shared Utility Code with Custom Template Makefile

If the build process uses a custom template makefile to create a makefile for the shared utility code, the build process produces a timeout error when all of these conditions apply:

  • The configuration parameter GenCodeOnly is 'off'.

  • The BUILD_SUCCESS message is output during the make call to rtwshared.mk.

  • The make call to rtwshared.mk does not update the final product (typically rtwshared.lib).

To avoid the error, update the custom template makefile so that the make call generates the BUILD_SUCCESS message only when the final product is generated (as identified by the make variable PRODUCT). Alternatively, if the build process does not use the generated makefile, disable makefile generation by setting the configuration parameter GenerateMakefile to 'off'.

Related Topics


[1] UNIX is a registered trademark of The Open Group in the United States and other countries.

[2] UNIX is a registered trademark of The Open Group in the United States and other countries.

[3] GNU is a registered trademark of the Free Software Foundation.