classdef BuildOpts < matlab.mixin.Copyable
%BuildOptions holds command options for invoking the compile stage

% Copyright 2020-2021 The MathWorks, Inc.

    properties(Constant=true, Hidden=true)
        % Options that are never overridden by the corresponding
        % option in a parent component
        NoOverrideOpts = ...
            {'MakefileSelfDependency', 'BuildVariant', 'BuildName', 'ClientChecksum'};
    end
    
    properties(Dependent=true)
        BuildMethod
    end
    
    properties
        BuildVariant (1,1) coder.make.enum.BuildVariant = coder.make.enum.BuildVariant('STATIC_LIBRARY');
    end
    
    properties(Hidden=true)
        BuildName char = ''
        BuildConfiguration char = coder.make.ToolchainInfo.getDefaultBuildConfig
        CMakePackages cell = {}
        ClientChecksum = [];
        CoderTargetAuxMakeContent = [];
        CustomToolchainOptions cell = {}
        DirectModelReferenceInstancesAsap2 = {}; % Legacy property not passed to compile stage
        LegacyTargetLibSuffix char = ''
        MakefileBasedBuild
        MakefileSelfDependency logical = true
        ModelRefLibPathFormat  coder.make.internal.ModelRefLibPathFormat = coder.make.internal.ModelRefLibPathFormat.NOT_SPECIFIED
        PrecompiledLibSuffix char = ''
        RTWVerbose logical = false
        SuppressExe logical = false      
        TargetLang char = ''
        TargetLangExt char = ''
        UseFileChecksums logical = true
        buildHookEnvVars cell = {}
        buildHookPathPrepends cell = {}
        checkStatusOnly logical = false      
        isCpp logical = false      
        isMATLABCodeGen logical = false
        makeCommandPrepend char = ''
        makefileName char = ''
        ncstates char = ''
        sysTargetFile char = ''
    end
    
    properties(Transient=true, Hidden=true)
        ComponentsToBuild string = []
        BuildActions coder.make.enum.BuildAction = 'NONE'
        BuildMethodObject
        CompileErrorDiagnosticFunctions cell = {}
        CompileProfileFcn function_handle = @(x)[];
        CopyBuildInfo logical = true
        DispHook = {}
        MexCompInfo = []
        forceCompile logical = false % Required subject to g2041630
        generateCodeOnly logical = false
    end
    
    properties(Hidden = true, GetAccess=public, SetAccess=private)
        BuildMethodSerializable = '';
    end
    
    methods
        
        function set.sysTargetFile(this, val)
            % Remove any path
            [~, systemTargetFilename, ext] = fileparts(val);
            this.sysTargetFile = [systemTargetFilename ext];
        end
        
        function val = get.BuildMethod(this)
            
            if ~isempty(this.BuildMethodObject)
                % Return an instantiated object if available
                val = this.BuildMethodObject;
            else
                % Return the build method as a char array, i.e. the form in
                % which it was serialized
                val = this.BuildMethodSerializable;
                
                if isempty(val)
                    val = '';
                else
                    [p, ~, e] = fileparts(val);
                    
                    if strcmp(e, '.tmf') && contains(p, '$(MATLABROOT)')
                        val = strrep(val, '$(MATLABROOT)', matlabroot);
                    end
                end
            end
        end        
        
        function set.BuildMethod(this, val)
            % The build method may be a toolchain info or TMF properties
            % object; store the supplied value directly as a transient property
            % to avoid cost of re-instantiating
            this.BuildMethodObject = val;
            
            % Additionally capture the BuildMethod in a serializable format
            if isa(val, 'coder.make.internal.TMFProps')
                lBuildMethod = val.TemplateMakefile;
            elseif isa(val, 'coder.make.ToolchainInfo')
                lBuildMethod = val.Name;
            elseif isempty(val)
                lBuildMethod = '';
            else
                lBuildMethod = val;
            end
            
            % For template makefiles, if the template has a path under
            % matlabroot or on matlabpath then store it (and serialize it)
            % without the path            
            [p, f, e] = fileparts(lBuildMethod);
            if strcmp(e, '.tmf')
                if contains(lBuildMethod, matlabroot)
                    % Tokenize matlabroot
                    lBuildMethod = strrep(lBuildMethod, matlabroot, '$(MATLABROOT)');
                    
                else
                    tmfNoPath = [f e];
                    tmfOnPath = which(tmfNoPath);
                    pathOfTmfOnPath = fileparts(tmfOnPath);
                    if ~isempty(pathOfTmfOnPath) && strcmp(pathOfTmfOnPath, p)
                        % For template makefile on the matlabpath, serialize without
                        % the path
                        lBuildMethod = [f e];
                    end
                end
            end
            
            this.BuildMethodSerializable = lBuildMethod;
        end
    end
    
    methods(Access=public, Hidden=true)
        % Constructor. Just the default constructor but made hidden.
        function this = BuildOpts
        end
    end
    
end
