function [productCreatedMessage, lWrappedMakeCmd, lMakeCmd, executor, writer] = ...
        invokeBuilder...
        (buildInfo, lBuildConfiguration, lCustomToolchainOptions, varargin)
%INVOKEBUILDER Invoke the builder.

% Copyright 2011-2020 The MathWorks, Inc.

narginchk(1,nargin);

% Quick checks
if ~isToolchainInstalled(buildInfo)
    productCreatedMessage = '';
    lWrappedMakeCmd = '';
    lMakeCmd = '';
    executor = [];
    writer = [];
    return
end

% Get the builder class name
builderName = buildInfo.getBuildToolInfo('BuilderClassName');

% Instantiate the Builder
builder = feval(builderName, buildInfo, lBuildConfiguration, ...
                lCustomToolchainOptions, varargin{:});

% Run the builder
try
    [lWrappedMakeCmd, lMakeCmd, executor, writer] = run(builder, buildInfo);    
catch exc
    [valid, validExc] = isToolchainValid(buildInfo);
    if ~valid
        exc = exc.addCause(validExc);
    end
    rethrow(exc)
end

% Message expected in build log when final product is created
productCreatedMessage = coder.make.Builder.getProductCreatedMessage;

end


% Is the toolchain installed?
function yes = isToolchainInstalled(buildInfo)
yes = buildInfo.BuildTools.IsToolchainInstalled;
if ~yes   
    % Setup the exception
    % Reuse error message for MSVC which has a generic statement.
    noCompilerExc = MException('RTW:buildProcess:noSupportedCompiler',...
                 DAStudio.message('RTW:buildProcess:noSupportedCompiler'));
    excName = 'noCompilerExc';
    
    buildOpts    = buildInfo.getBuildToolInfo('BuildOpts');
    errorMATFile = 'make_exception.mat';
    
    if buildOpts.generateCodeOnly
        % Save the exception
        save(errorMATFile, excName);
        
        % Inform the user that the support files are not generated
        DAStudio.warning('RTW:buildProcess:codeGenOnlyMakeGenWarn',...
            noCompilerExc.message, errorMATFile);
    else        
        throw(noCompilerExc);
    end
end

end


% Is the toolchain valid?
function [yes, validationExc] = isToolchainValid(buildInfo)
toolchainObj = buildInfo.getBuildToolInfo('ToolchainInfo');
validationExc = [];
try
    [yes, validationReport] = toolchainObj.validate('setup', 'cleanup', 'useCachedReport');
    if ~yes
        validationExc = MException('CoderFoundation:toolchain:InvalidToolchain', ...
            validationReport);
    end
catch validationExc
    yes = 0;
    return
end

end

