Main Content

在 Simulink 环境中编译集成的代码

工作流

要编译集成生成的代码和外部 C 或 C++ 代码的可执行程序,请依次执行下表中的任务。

任务

操作

更多信息

1

选择一种编译方法。

编译从 Simulink 模型生成的代码的方法 (Embedded Coder)

有关示例,请参阅Build Process Workflow for Real-Time Systems (Embedded Coder)

2

为您的外部代码配置编译过程支持。

为集成的代码编译过程配置参数 (Embedded Coder)

3

为您的外部代码配置 S-Function 编译支持。

编译对 S-Function 的支持 (Embedded Coder)

Use makecfg to Customize Generated Makefiles for S-Functions (Embedded Coder)

有关示例,请参阅调用可重用的外部算法代码进行仿真和代码生成 (Embedded Coder)

4

配置编译过程以查找外部代码源、库和头文件。

Manage Build Process File Dependencies (Embedded Coder)

Control Library Location and Naming During Build (Embedded Coder)

5

设置您的外部代码集成所需的自定义编译处理。

有关编译过程自定义工作流的信息,请参阅Customize Post-Code-Generation Build Processing (Embedded Coder)

要自动将编译自定义应用于工具链方法编译,请参阅Customize Build Process with sl_customization.m (Embedded Coder)

要自动将编译自定义应用于模板联编文件方法编译,请参阅使用 STF_make_rtw_hook 文件自定义编译过程 (Embedded Coder)

为集成的代码编译过程配置参数

下表说明如何配置编译过程的“模型配置参数”对话框的代码生成 > 自定义代码窗格中的模型配置参数,以支持在编译过程中集成外部代码。有关外部代码的文件夹的信息,请参阅管理编译过程文件夹 (Embedded Coder)。如果您选择将外部代码放入Code generation folder 中,请参阅在编译文件夹中保留外部代码文件 (Embedded Coder)

要执行的操作选择

将包含文件夹(其中包含头文件)添加到编译过程

代码信息 > 包含目录,然后输入文件夹的绝对路径或相对路径。

如果指定相对路径,则路径必须相对于包含模型文件的文件夹,而不是相对于编译文件夹。您指定文件夹的顺序是在其中搜索头文件、源和库文件的顺序。

添加要编译和链接的源文件

代码信息 > 源文件,然后输入文件的完整路径或仅输入文件名。

如果文件位于当前 MATLAB® 文件夹或其中一个包含文件夹中,请只输入文件名。对于您指定的每个其他源,编译过程都会为源文件所在的文件夹在模板联编文件中展开一条通用规则。例如,如果源文件位于文件夹 inc 中,则编译过程将添加一条类似于以下内容的规则:

%.obj: buildir\inc\%.c
            $(CC) -c -Fo$(@F) $(CFLAGS) $<

编译过程按照列出源文件的顺序添加规则。

添加要链接的库

代码信息 > ,然后输入库的完整路径或仅输入文件名。

如果库位于当前 MATLAB 文件夹或其中某个包含文件夹中,请只输入文件名。

使用与针对 MATLAB Function 模块、Stateflow® 图和 Truth Table 模块的仿真指定的相同的自定义代码设置

使用与仿真目标相同的自定义代码设置

此参数引用“配置参数”对话框中的仿真目标窗格。

使库模型能够使用库所链接到的父模型中具有唯一性的自定义代码设置

使用本地自定义代码设置(不从主模型继承)

此参数仅适用于包含 MATLAB Function 模块、Stateflow 图或 Truth Table 模块的库模型。

在编译文件夹中保留外部代码文件

默认情况下,编译过程将删除外部源文件。您可以按照下列规范保留外部源文件。

如果将 .c/.cpp.h 源文件放入编译文件夹中,并且希望防止代码生成器在 TLC 代码生成过程中将其删除,请在 .c/.cpp.h 文件的第一行中插入文本 target specific file。例如:

/*  COMPANY-NAME target specific file
 *
 *   This file is created for use with the 
 *   COMPANY-NAME target.
 *   It is used for ...
 */
...

确保“target specific file”的拼写与前面示例中的完全相同,并且这段文本位于源文件的第一行。其他文字可以出现在这些文字之前或之后。

以这种方式标记用户文件可防止对这些文件进行后处理,避免用生成的源文件对这些文件的代码格式进行整理。在以前的版本中会发生自动缩进,以编译具有模式 model_*.c/.cpp(其中 * 为文本)的名称的文件夹文件。格式整理不会损坏文件,但可能会导致源代码管理软件检测到差异,这些差异可能会触发不必要的更新。

编译对 S-Function 的支持

借助用户编写的 S-Function 模块,您可以将外部代码整合到 Simulink® 开发环境中。在大多数情况下,您可以使用 S-Function 将现有外部代码与生成的代码进行集成。有几种编写 S-Function 的方法:

使用 S-Function,还可以最灵活有效地在编译过程中包含原有和自定义代码文件的编译信息。

将 S-Function 添加到编译过程有多种不同的方法。

隐式编译支持

在编译具有 S-Function 的模型时,编译过程向生成的联编文件添加规则、包含路径和源文件名。S-Function 的源文件(.h.c.cpp)必须与 S-Function MEX 文件位于同一文件夹中。无论是使用工具链方法还是使用模板联编文件方法进行编译,编译过程都会将此信息传播到工具链或模板联编文件中。

  • 如果文件 sfcnname.h 与 S-Function MEX 文件位于同一文件夹中(例如 sfcnname.mexext),则该文件夹将被添加到包含路径中。

  • 如果文件 sfcnname.csfcnname.cpp 与 S-Function MEX 文件位于同一文件夹中,则编译过程会添加一个联编文件规则,以编译来自该文件夹的文件。

  • 当 S-Function 不与 TLC 文件内联时,编译过程必须编译 S-Function 源文件。为了确定要添加到要编译的文件列表的源文件的名称,编译过程会在 MATLAB 路径上搜索 sfcnname.cpp。如果找到源文件,则编译过程会将源文件名添加到联编文件。如果在路径上找不到 sfcnname.cpp,则编译过程会将文件名 sfcnname.c 添加到联编文件,无论它是否位于 MATLAB 路径上都是如此。

    注意

    为了使 Simulink 引擎找到用于仿真和代码生成的 MEX 文件,它必须存在于 MATLAB 路径上,或存在于我们的当前 MATLAB 工作文件夹中。

为 S-Function 指定其他源文件

如果您的 S-Function 有其他源文件依存关系,则必须将其他模块的名称添加到编译过程。指定文件名:

  • 在“S-Function 模块参数”对话框的 S-Function 模块字段中

  • 在对 set_param 函数的调用中使用 SFunctionModules 参数

例如,假设您编译具有多个模块的 S-Function。

mex sfun_main.c sfun_module1.c sfun_module2.c

然后,您可以通过执行以下操作之一将模块添加到编译过程:

  • 在“S-Function 模块”对话框中,在 S-Function 模块字段中指定 sfun_mainsfun_module1sfun_module2

  • 在 MATLAB 命令提示符下,输入:

    set_param(sfun_block,'SFunctionModules','sfun_module1 sfun_module2')

    您也可以定义一个变量来表示参数值。

    modules = 'sfun_module1 sfun_module2'
              set_param(sfun_block,'SFunctionModules', modules)

S-Function 模块字段和 SFunctionModules 参数不支持完整的源文件路径设定。要使用该参数,代码生成器在执行联编文件时必须找到其他源文件。为了让代码生成器找到其他文件,请将它们放在与 S-Function MEX 文件相同的文件夹中。然后您可以利用隐式编译支持中所述的隐式编译支持。

准备好生成代码之后,强制代码生成器重新编译顶层模型,如Control Regeneration of Top Model Code中所述。

对于更复杂的 S-Function 文件依存关系,例如在其他位置指定源文件或者指定库或目标文件,请使用 rtwmakecfg.m API,如Use rtwmakecfg.m API to Customize Generated Makefiles中所述。

使用 TLC 库函数

如果通过编写 TLC 文件来内联 S-Function,则可以使用 TLC 库函数 LibAddToModelSources 将源文件名添加到编译过程。有关详细信息,请参阅LibAddSourceFileCustomSection(file, builtInSection, newSection)

注意

此函数不支持完整的源文件路径设定。该函数假定代码生成器在执行联编文件时可以找到其他源文件。

另一个有用的 TLC 库函数是 LibAddToCommonIncludes。在 #include 语句中使用此函数以将 S-Function 头文件包含在生成的 model.h 头文件中。有关详细信息,请参阅LibAddToCommonIncludes(incFileName)

对于更复杂的 S-Function 文件依存关系,例如在其他位置指定源文件或者指定库或目标文件,请使用 rtwmakecfg.m API,如Use rtwmakecfg.m API to Customize Generated Makefiles中所述。

预编译 S-Function 库

您可以使用 MATLAB 语言函数 rtw_precompile_libs 为模型预编译新的或更新的 S-Function 库(MEX 文件)。此函数使用指定的模型和库编译设定编译库并将其放置在预编译库文件夹中。

通过预编译 S-Function 库,可以优化系统编译。一旦您的预编译库存在,编译过程便可以在后续的编译中省略库编译。对于使用大量库的模型,可以显著节省编译处理的时间。

要使用 rtw_precompile_libs,请执行下列操作:

  1. 根据您的系统平台设置库文件后缀,包括文件类型扩展名。

    考虑确定平台类型,然后使用 TargetLibSuffix 参数对应地设置库后缀。例如,为 GRT 目标应用后缀时,可以将后缀设置为 _std.a(对于 UNIX® 平台)和 _vcx64.lib(对于 Windows® 平台)。

      if isunix
        suffix = '_std.a';
      else
        suffix = '_vcx64.lib';
      end
    
    set_param(my_model,'TargetLibSuffix', suffix);

    有许多因素会影响预编译库后缀和扩展名。下表提供了通常选择的系统目标文件、编译器工具链以及影响您选择的后缀和扩展名的其他选项的示例。有关详细信息,请检查 matlab/rtw/c/grt 文件夹或 matlab/rtw/c/ert 文件夹中的模板联编文件。

    TMF 文件COMPILER _TOOL_CHAIN 值预编译器库 (PRECOMP_LIBRARIES)
    库后缀 S-Function(EXPAND _LIBRARY _NAME 值) 库后缀整数 - 仅代码(EXPAND _LIBRARY _NAME 值)库后缀速度优化(EXPAND _LIBRARY _NAME 值)库扩展名(EXPAND _LIBRARY _NAME 值)
    ert_vcx64.tmfvcx64_rtwsfcn_vcx64_int_ert_vcx64_ert_vcx64.lib
    ert_unix.tmfunix_rtwsfcn_int_ert_ert.a
    grt_vcx64.tmfvcx64不适用不适用_vcx64.lib
    grt_unix.tmfunix不适用不适用_std.a
  2. 设置预编译库文件夹。

    使用以下方法之一来设置预编译库文件夹:

    如果设置 TargetPreCompLibLocationmakeInfo.precompile,则 TargetPreCompLibLocation 的设置优先。

    以下命令将模型 my_model 的预编译库文件夹设置为当前工作文件夹下的 lib 文件夹。

    set_param(my_model,'TargetPreCompLibLocation', fullfile(pwd,'lib'));

    注意

    如果您为预编译库文件和目标库文件后缀都设置目标文件夹,则编译过程将在处理编译时检测是否缺少任何预编译库文件。

  3. 定义编译设定。

    设置定义编译设定的结构体。下表描述您可以在结构体中定义的字段。这些字段是可选的,但 rtwmakecfgDirs 除外。

    字段描述

    rtwmakecfgDirs

    字符向量元胞数组,用于命名包含要预编译的库的 rtwmakecfg 文件的文件夹。该函数使用 rtwmakecfg 返回的 makeInfo.libraryNameLocation 元素来指定预编译库的名称和位置。如果您通过设置 TargetPreCompLibLocation 参数来指定库文件夹,则该设置将覆盖 makeInfo.library.Location 设置。

    注意:指定的模型必须包含使用由 rtwmakecfg 文件指定的预编译库的模块,因为仅在编译过程使用这些库时,TMF 到联编文件的转换才会生成库规则。

    libSuffix

    字符向量,指定要附加到每个库名称的后缀(包括文件类型扩展名),例如 .a_vc.lib。字符向量必须包含句点 (.)。您必须使用此字段或 TargetLibSuffix 参数设置后缀。如果您同时使用这两种机制指定后缀,则 TargetLibSuffix 设置将覆盖此字段的设置。

    intOnlyBuild

    布尔标志。当设置为 true 时,该标志表示库将优化,以便它们仅从整数代码编译。此字段仅适用于 ERT 目标。

    makeOpts

    字符向量,指定要包含在 rtwMake 命令行中的选项。

    addLibs

    结构体的元胞数组,这些结构体指定要编译的、并非由 rtwmakecfg 函数指定的库。必须使用两个字符数组形式的字段来定义每个结构体:

    • libName - 没有后缀的库名称

    • libLoc - 预编译库的位置

    目标联编文件 (TMF) 可以指定其他库以及这些库的编译方式。使用此字段来预编译这些库。

    以下命令设置编译设定 build_spec,它指示要编译的文件位于当前工作文件夹下的 src 文件夹中。

    build_spec = [];
    build_spec.rtwmakecfgDirs = {fullfile(pwd,'src')};
  4. 发出对 rtw_precompile_libs 的调用。

    该调用必须指定要为其编译预编译库的模型和编译设定。例如:

    rtw_precompile_libs(my_model,build_spec);

相关主题