Main Content

Best Practices for Effective Builds

With the CI/CD Automation for Simulink Check support package, you can define a development and verification process for your team by using a process model. When you deploy your process model to your team, consider the following best practices for scheduling builds and caching artifacts.

Use Incremental Builds for Regular Submissions

For builds that you perform on a daily or more frequent basis, use incremental builds. Incremental builds are faster and more efficient, but incremental builds skip tasks that the build system considers up to date.

By default, the function runprocess performs an incremental build:

runprocess()

If you use a pull request workflow, incremental builds are helpful for efficiently prequalifying changes before merging with the main repository.

Run Full Builds for Qualifying Software

Outside of the normal build schedule, you should run a full (non-incremental) build at least one time per week and anytime you are qualifying software for a release. When you run a full build, the build system force runs each of the tasks in the pipeline. The full build makes sure that each task in the pipeline executes and that the output artifacts reflect the latest changes.

To run a full build, use the function runprocess with the argument Force specified as True:

runprocess(Force=true)
The Force argument forces tasks in the pipeline to execute, even if the tasks already have up to date results.

For more information, see Specify Settings for Process Advisor and Build System and runprocess.

Cache Models and Other Artifacts Used During Build

If you select the setting Enable model caching, the build system can cache your models and several other artifacts. The cache allows the build system to avoid reloading the same artifacts multiple times within a build.

The artifacts that the build system can cache include:

  • Simulink® models

  • Simulink libraries, subsystem references, and data dictionaries

  • Test files, results, and harnesses (internally saved and externally saved) from Simulink Test™

  • Requirements files and requirement sets from Requirements Toolbox™

  • System Composer™ architecture models

You can control the size of the cache by using the padv.ProjectSettings properties MaxNumModelsInCache and MaxNumTestResultsInCache. The built-in tasks use the utility function padv.util.closeModelsLoadedByTask to close models loaded by the task. For more information, see padv.ProjectSettings and padv.util.closeModelsLoadedByTask.

If you have custom tasks, you can improve the efficiency of model loading in your builds by closing the models loaded by a task by using the function padv.util.closeModelsLoadedByTask inside your custom tasks.

For example:

classdef MyCustomTask < padv.Task
    methods
        function obj = MyCustomTask(options)
            arguments
                % unique identifier for task
                options.Name = "MyCustomTask";
                % artifacts the task iterates over
                options.IterationQuery = "padv.builtin.query.FindModels";
                % input artifacts for the task
                options.InputQueries = "padv.builtin.query.GetIterationArtifact";
                % where the task outputs artifacts
                options.OutputDirectory = fullfile(...
                    '$DEFAULTOUTPUTDIR$','my_custom_task_results');
            end
            % Calling constructor of superclass padv.Task
            obj@padv.Task(options.Name,...
                IterationQuery=options.IterationQuery,...
                InputQueries=options.InputQueries);
            obj.OutputDirectory = options.OutputDirectory;
        end
        function taskResult = run(obj,input)
            % Before the task loads models, save a list of the models that are already loaded.
            loadedModels = get_param(Simulink.allBlockDiagrams(), 'Name');
            
            % identify model name
            % "input" is a cell array of input artifacts
            % First input query gets iteration artifact (a model)
            model = input{1}; % get padv.Artifact from first input query
            modelName = padv.util.getModelName(model);

            % Example task that loads model and displays information
            load_system(modelName);
            disp(modelName);
            disp('Data Dictionaries:')
            disp(Simulink.data.dictionary.getOpenDictionaryPaths)
            
            % specify results from task using padv.TaskResult
            taskResult = padv.TaskResult;
            taskResult.Status = padv.TaskStatus.Pass;
            % taskResult.Status = padv.TaskStatus.Fail;
            % taskResult.Status = padv.TaskStatus.Error;

            % Close models that were loaded by this task.
            padv.util.closeModelsLoadedByTask(...
                PreviouslyLoadedModels=loadedModels)
        end
    end
end

See Also

| | |

Related Topics