classdef MakefileBuilder < rtw.connectivity.Builder
%MAKEFILEBUILDER builds an application for a target processor
%
%   MAKEFILEBUILDER(COMPONENTARGS, TARGETAPPLICATIONFRAMEWORK) returns an
%   instance of the MAKEFILEBUILDER class. This class supports a customizable
%   makefile-based build process. You can use it to build applications (e.g. a
%   PIL application) that interface with a model component such as a referenced
%   model; this model component is included in the build as a collection of
%   compiled object code or library files.
%
%   MAKEFILEBUILDER uses the same template makefile that is specified in the
%   model representing the component included in the build. It is required that
%   this template makefile includes a makefile target named MAKEFILEBUILDER_TGT.
%
%   See also RTW.CONNECTIVITY.COMPONENTARGS, RTW.CONNECTIVITY.CONFIG,
%   RTW.PIL.RTIOSTREAMAPPLICATIONFRAMEWORK

%   Copyright 2007-2020 The MathWorks, Inc.
%

    properties (Access=private)
        exeExtension;
        FileSeparator;
    end

    methods
        function this = MakefileBuilder(componentArgs, ...
                                        targetApplicationFramework, ...
                                        exeExtension)
            narginchk(3, 3);
            validateattributes(exeExtension, {'char', 'string'}, {'scalartext'});
            
            % call super class constructor
            this@rtw.connectivity.Builder(componentArgs, ...
                                targetApplicationFramework);

            this.exeExtension = convertStringsToChars(exeExtension);

            % MakefileBuilder needs to inject additional hooks to the PIL
            % application build
            this.BuildStrategy.registerFunctionOverride('getRelativePathFromApplicationToComponent', @() this.getRelativePathFromApplicationToComponentStrategyWrapper());
            this.BuildStrategy.registerFunctionOverride('getFileSeparator', @() this.getFileSeparatorStrategyWrapper());
            this.BuildStrategy.registerFunctionOverride('fullFile', @(varargin) this.fullFileStrategyWrapper(varargin{:}));
            this.BuildStrategy.registerFunctionOverride('getExecutableFileExtension', @() this.getExecutableExtension());
        end
    end

    % Protected methods which could be overridden by target authors in
    % subclasses. By default these will use the default behavior as
    % specified by rtw.pil.ApplicationBuildManager.
    methods (Access = 'protected')

        function relComponentPath = getPathFromApplicationToComponent(this, lXilCompInfo) %#ok<INUSD>

            relComponentPath = this.BuildStrategy.getDefaultBehavior().getRelativePathFromApplicationToComponent();
            end

        function fileSep = get_FileSeparator(this, lXilCompInfo) %#ok<INUSD>
            fileSep = this.FileSeparator;
            if isempty(fileSep)
                fileSep = this.BuildStrategy.getDefaultBehavior.getFileSeparator();
                end
            end

        function fullPath = get_fullfile(this, lXilCompInfo, varargin) %#ok<INUSL>

            fullPath = this.BuildStrategy.getDefaultBehavior.fullFile(varargin{:});
            end

        function buildInfo = getComponentIntegrationBuildInfo(this, buildInfo, lXilCompInfo) %#ok<INUSD>

            this.BuildStrategy.getDefaultBehavior().processComponentIntegrationBuildInfo(buildInfo);
                end

        function build(this, buildInfo, lXilCompInfo, varargin) %#ok<INUSD>

           this.BuildStrategy.getDefaultBehavior().doBuild(buildInfo);
            end

        function exe = getExecutable(this, buildInfo) %#ok<INUSD>
                            
            exe = this.BuildStrategy.getDefaultBehavior().getApplicationPath();
            end
            
        function extension = getExecutableExtension(this)

            extension = this.exeExtension;
        end
    end

    % BuildStrategy wrapper calls. Allows
    % rtw.pil.ApplicationBuildManager to call overridden methods from the
    % connectivity config by registering these to the build strategy in the
    % constructor
    methods (Sealed, Access=private)

        function componentRelativePath = getRelativePathFromApplicationToComponentStrategyWrapper(this)

            componentRelativePath = this.getPathFromApplicationToComponent(this.BuildStrategy.PILBuildOptions.XilCompInfo);
              end

        function fileSeparator = getFileSeparatorStrategyWrapper(this)

            fileSeparator = this.get_FileSeparator(this.BuildStrategy.PILBuildOptions.XilCompInfo);
        end

        function fullFileResult = fullFileStrategyWrapper(this, varargin)

            fullFileResult = this.get_fullfile(this.BuildStrategy.PILBuildOptions.XilCompInfo, varargin{:});
            end
                end
            end

