function macroList = getCodeGenMacrosPerBuildVariant(h,buildInfo,category)
%

%   Copyright 2014-2020 The MathWorks, Inc.

macroStructInit = createMacroStruct();
macroList = struct('comment', {}, 'macro', {}, 'value', {}, 'inplace', {});
switch (category)
    case 'Baseline'
        % ----------------------------------
        % Baseline Macros
        % ----------------------------------
        macro = macroStructInit;
        macro.comment = 'Name of the system to build';
        macro.macro = 'PRODUCT_NAME';  % Equivalent in TMF: |>MODEL_NAME<|
        macro.value = buildInfo.ModelName;
        macroList( 1 ) = macro;
        macro = macroStructInit;
        macro.comment = 'Name of this makefile';
        macro.macro = 'MAKEFILE';  % Equivalent in TMF: |>MAKEFILE_NAME<|
        macro.value = h.BrMakefileName;
        macroList( end + 1 ) = macro;
        % ----------------------------------
        % Special folders
        % ----------------------------------
        specialDirs = { h.SpecialDirs.Macros.Name };
        numSpecialDirMacros = numel( h.SpecialDirs.Macros );
        macro = repmat( macroStructInit, 1, numSpecialDirMacros );
        for i = 1:numel( h.SpecialDirs.Macros )
            macro( i ).comment = '';
            macro( i ).macro = h.SpecialDirs.Macros( i ).Name;
            macro( i ).value = h.SpecialDirs.Macros( i ).Value;
        end
        macroList = horzcat( macroList, macro );
        % ----------------------------------
        % Macros (make vars) from BuildInfo
        % ----------------------------------
        [~,makeVars,makeVarValues] = buildInfo.getMakeVars();
        specialDirsIdx = ismember( makeVars, specialDirs );
        makeVars( specialDirsIdx ) = [  ];
        makeVarValues( specialDirsIdx ) = [  ];
        isUnixPlatform = isunix;
        for i = 1:numel( makeVars )
            if isempty( makeVars{ i } )
                continue
            end
            newValue = makeVarValues{ i };
            % -------------------------------------
            % Overwrite special folders with their
            % alternate versions
            % -------------------------------------
            if strcmp( makeVars{ i }, 'RELATIVE_PATH_TO_ANCHOR' )
                if isUnixPlatform
                    % return to original full path before
                    % transforming the file separator
                    newValue = coder.make.internal.transformPaths( newValue, 'pathType', 'full' );
                end
                newValue = h.transformFileSep( newValue );
                if isUnixPlatform
                    % convert to alternate path (puts \ if path
                    % contains spaces)
                    newValue = coder.make.internal.transformPaths( newValue, 'pathType', 'alternate' );
                end
                newValue = h.transformPathBasedOnWriter( newValue );
                newValue = h.wrapWithQuotes( newValue );
            end
            % ---------------------------
            % Form the macro struct
            % ---------------------------
            macro = macroStructInit;
            macro.macro = makeVars{ i };
            macro.value = newValue;
            macroList( end + 1 ) = macro;  %#ok<AGROW>
        end

        if h.requiresCommandFile()
            [objectCodeCommandFileName, linkObjectsCommandFileName, compilerCommandFileName] =  ...
                coder.make.getResponseFileName(h.BrMakefileName);

            if ~isempty(buildInfo.ModelRefs)
                macro = macroStructInit;
                macro.comment = 'Linker command listing model reference link objects';
                macro.macro = 'MODELREF_LINK_RSPFILE';
                macro.value = linkObjectsCommandFileName;
                macroList( end + 1 ) = macro;
            end

            % Determine if compiler command file is in use
            lUseCompilerCommandFile = coder.make.useCompilerCommandFile...
                (h.ToolchainInfo);

            if lUseCompilerCommandFile
                macro = macroStructInit;
                macro.comment = 'Compiler command listing model reference header paths';
                macro.macro = 'COMPILER_COMMAND_FILE';
                macro.value = compilerCommandFileName;
                macroList( end + 1 ) = macro;
            end

            macro = macroStructInit;
            macro.comment = 'Command file';
            macro.macro = 'CMD_FILE';
            macro.value = objectCodeCommandFileName;
            macroList( end + 1 ) = macro;
        end

        if (h.BuildOutputType==coder.make.enum.BuildOutput.SHARED_LIBRARY)
            macro = macroStructInit;
            macro.comment = 'Definition file';
            macro.macro = 'DEF_FILE';
            macro.value = '$(PRODUCT_NAME).def';
            macroList( end + 1 ) = macro;
        end

        % TFL-specific C/CPP standard options macros
        [C_STANDARD_OPTS,CPP_STANDARD_OPTS] = coder.make.Builder.getStdCompilerOptions(h.ToolchainInfo, buildInfo);
        macro = macroStructInit;
        macro.macro = 'C_STANDARD_OPTS';
        macro.value = C_STANDARD_OPTS;
        macroList( end + 1 ) = macro;
        macro = macroStructInit;
        macro.macro = 'CPP_STANDARD_OPTS';
        macro.value = CPP_STANDARD_OPTS;
        macroList( end + 1 ) = macro;
        
        % Workaround for a build-config-specific macro
        if coder.make.internal.isToolchain( buildInfo, 'MSVC' ) ||...
            coder.make.internal.isToolchain( buildInfo, 'INTEL' )
            % For MSVC and Intel, certain compiler and link flags are taken from vcdefs.mak and the
            % actual flags that are used depend on the presence or absence of
            % the NODEBUG macro. However, the required debug flags (e.g. if
            % running a SIL simulation with debugging) are already supplied when
            % the ToolchainInfo object was configured. This means we can always
            % have NODEBUG defined so that we only take the default (no debug)
            % flags from vcdefs.mak.

            % Note: it's not the value of NODEBUG that controls the MSVC compile flags, it
            % is the presence or absence that controls the compile flags.
            macro = macroStructInit;
            macro.macro = 'NODEBUG';
            macro.value = '1';
            macroList( end + 1 ) = macro;
        end
    case 'ModelLib'
        % NOTE: new macro names introduced
        macro = macroStructInit;
        macro.comment = 'Static library target';
        macro.macro = 'MODELLIB';  % Equivalent in TMF: |>MODELLIB<|
        macro.value = buildInfo.findKeyValuePair( 'BuildArg', 'MODELLIB' ).Value;
        macroList( 1 ) = macro;
end

end

function macro = createMacroStruct
macro = struct( 'comment', '', 'macro', '', 'value', [  ], 'inplace', false );
end

