Conditional Inclusions (#if / #endif)
You can generate preprocessor conditional directives in your code by implementing variants in your model. In the generated code, the preprocessor conditional directives select a section of code to execute at compile time.
This example uses Simulink.Variant
objects to control Variant Subsystem blocks. For information about other ways to control variants, see Variant Control Modes in Variant Blocks. For information about types of variants other than Variant Subsystem blocks, see What Are Variants and When to Use Them.
Inspect Model
Open the example model PreprocessorConditionalsUsingVariantSubsystem
.
model = 'PreprocessorConditionalsUsingVariantSubsystem';
open_system(model);
This model contains two variant subsystems, LeftController
and RightController
, each with two child subsystems, Linear
and Nonlinear
. The PostLoadFcn
callback function of the model loads rtwdemo_preprocessor_data.mat
. To view the callback function, from the Simulink toolstrip, click the Modeling tab and, in the Setup section, click Model Settings > Model Properties. In the Model Properties dialog box, open the Callbacks tab and select PostLoadFcn. Alternatively, view the callback function programmatically.
get_param(model,'PostLoadFcn')
ans = 'load preprocessor_data.mat'
The callback function instantiates two Simulink.Variant
objects, LINEAR
and NONLINEAR
, and one Simulink.Parameter
, VSSMODE
. The LINEAR
variant is active when VSSMODE
is equal to 0
. The NONLINEAR
variant is active when VSSMODE
is equal to 1
. VSSMODE
is initialized to 1
. Verify these settings programmatically.
LINEAR.Condition
ans = 'VSSMODE==0'
NONLINEAR.Condition
ans = 'VSSMODE==1'
VSSMODE.Value
ans = int32
1
LeftController
and RightController
use LINEAR
and NONLINEAR
as the variant control expressions for their respective Linear
and Nonlinear
subsystems. To view this configuration, right-click LeftController
and click Block Parameters (Subsystem). Alternatively, view the variant control expressions programmatically.
choices = get_param(append(model,'/LeftController'),'VariantChoices'); choices(1)
ans = struct with fields:
Name: 'LINEAR'
BlockName: 'PreprocessorConditionalsUsingVariantSubsystem/LeftController/Linear'
choices(2)
ans = struct with fields:
Name: 'NONLINEAR'
BlockName: 'PreprocessorConditionalsUsingVariantSubsystem/LeftController/Nonlinear'
Configure Model
Open the Configuration Parameters dialog box. In the left pane, click Code Generation, then confirm System target file is set to ert.tlc
. Alternatively, set the parameter programmatically.
set_param(model,'SystemTargetFile','ert.tlc');
In the left pane, click Interface. Confirm the Ignore custom storage classes parameter is cleared. Alternatively, clear the parameter programmatically.
set_param(model,'IgnoreCustomStorageClasses','off');
To generate preprocessor conditionals, use custom storage classes.
Open the Block Parameters dialog box for the LeftController
subsystem. Verify the Variant activation time parameter is set to code compile
. Alternatively, set the parameter programmatically.
set_param(append(model,'/LeftController'),'VariantActivationTime','code compile');
Open the LeftController
subsystem. For each child subsystem, click the subsystem and, in the Subsystem Block tab, confirm Atomic Subsystem is selected. Alternatively, set the parameters programmatically.
set_param(append(model,'/LeftController/Linear'),'TreatAsAtomicUnit','on'); set_param(append(model,'/LeftController/Nonlinear'),'TreatAsAtomicUnit','on');
Generate code.
slbuild(model);
### Starting build procedure for: PreprocessorConditionalsUsingVariantSubsystem ### Successful completion of build procedure for: PreprocessorConditionalsUsingVariantSubsystem Build Summary Top model targets: Model Build Reason Status Build Duration ================================================================================================================================================ PreprocessorConditionalsUsingVariantSubsystem Information cache folder or artifacts were missing. Code generated and compiled. 0h 0m 13.98s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 15.242s
View the generated code. The generated code includes #if
and #endif
preprocessor directives that use LINEAR
and NONLINEAR
to select one variant to compile.
cfile = fullfile('PreprocessorConditionalsUsingVariantSubsystem_ert_rtw','PreprocessorConditionalsUsingVariantSubsystem.c'); coder.example.extractLines(cfile," /* Outputs for Atomic SubSystem: '<Root>/LeftController' */",... " /* End of Outputs for SubSystem: '<Root>/LeftController' */", 1, 1);
/* Outputs for Atomic SubSystem: '<Root>/LeftController' */ #if LINEAR /* Outputs for Atomic SubSystem: '<S1>/Linear' */ /* VariantMerge generated from: '<S1>/Out1' incorporates: * DiscreteFilter: '<S3>/Discrete Filter' */ rtY.Out1 = rtb_Add - 0.5 * rtDWork.DiscreteFilter_states_a; /* Update for DiscreteFilter: '<S3>/Discrete Filter' */ rtDWork.DiscreteFilter_states_a = rtY.Out1; /* End of Outputs for SubSystem: '<S1>/Linear' */ #elif NONLINEAR /* Outputs for Atomic SubSystem: '<S1>/Nonlinear' */ /* VariantMerge generated from: '<S1>/Out1' incorporates: * DiscreteFilter: '<S4>/Discrete Filter' * Lookup_n-D: '<S4>/Lookup Table' * Sum: '<Root>/Add' */ rtY.Out1 = look1_binlxpw(rtb_Add, rtCP_LookupTable_bp01Data, rtCP_LookupTable_tableData, 4U) - 0.5 * rtDWork.DiscreteFilter_states_o; /* Update for DiscreteFilter: '<S4>/Discrete Filter' */ rtDWork.DiscreteFilter_states_o = rtY.Out1; /* End of Outputs for SubSystem: '<S1>/Nonlinear' */ #endif