function linkobjs = getTargetLinkObjs(h,buildInfo,varargin)
%

%   Copyright 2014-2021 The MathWorks, Inc.

target = h.Components.FinalProduct.TargetInfo;
% ---------------------------------------
% Get the baseline objects and libraries
% ---------------------------------------
linkobjs = {  };
macro = unique(h.getMacroToken( target.TargetDepsMacro ), 'stable');
objsMacro = h.getMacroOf( 'object files' );
objsToken = h.getMacroToken( objsMacro );
for i = 1:numel( macro )
    % Link objects whose macro is not 'object files' are libraries
    % We prefix them if needed
    if ~strcmpi(macro{i}, objsToken) && h.ToolchainInfo.Attributes.isKey('LinkerLibraryPrefix')
        bldArtifact = h.ToolchainInfo.BuildArtifact;
        if contains( bldArtifact, 'gmake', 'IgnoreCase', true )
            macro{ i }  = ['$(foreach lib,' macro{ i },',',...
                           h.ToolchainInfo.getAttribute('LinkerLibraryPrefix'),'$(lib))'];
        else
            error(message('CoderFoundation:builder:LinkerAttributeIncompatibleWithMake', bldArtifact));
        end
    end
    linkobjs = horzcat( linkobjs, macro{ i } );  %#ok<AGROW>
end
% Update linkObjs: add MAIN_OBJ for executable targets if it not included
% in a linker response file
lRequiresCommandFile = h.requiresCommandFile();
if h.isStandaloneExecutableTarget && ~lRequiresCommandFile
    mainObjIdx = strcmp( h.Components.ObjectFiles.macro, h.getMacroOf( 'main object file' ) );
    if any( mainObjIdx )
        mainObjToken = h.getMacroToken( h.getMacroOf( 'main object file' ) );
        linkobjs = h.insertCellElement( linkobjs, mainObjToken, objsToken );
    end
end
% This workaround should be removed when we address G886533
% ---------------------------------------------------------
% Add PREBUILT_OBJS after the |>OBJS<| on the link line
% ---------------------------------------------------------
foundPrebuiltObjs = false;
for i = 1:length( buildInfo.LinkObj )
    if strcmp( buildInfo.LinkObj( i ).Group, 'PREBUILT_OBJECTS' )
        foundPrebuiltObjs = true;
        break
    end
end
if foundPrebuiltObjs
    nonObjIdx = ~strcmp( linkobjs, objsToken );
    newLinkObjs = h.removeCellElements( linkobjs, nonObjIdx );
    newLinkObjs = horzcat( newLinkObjs, h.getMacroToken( h.getMacroOf( 'prebuilt object files' ) ) );
    newLinkObjs = [ newLinkObjs, linkobjs( nonObjIdx ) ];
    linkobjs = newLinkObjs;
end
% ------------------------------------------------
% If building a static library, archive the
% object files only
% ------------------------------------------------
intermediateStaticLibTarget = ((nargin>=4) && (any( strcmpi( varargin{ 1 }, { 'intermediate', 'final' } ) )) && strcmpi( varargin{ 2 }, 'static library' ));
if intermediateStaticLibTarget
    % @todo : TODO: If MEX, archive with the S-Function libraries too
    % (ask Tony where to get this info)
    % Workaround for intermediate static library target:
    % Remove all entries from the LinkObjs list except the
    % object files
    % if coder.make.Builder.useExplicitListInArtifact
    %    assert(false, 'TODO: Find the MEX source and object files')
    % else
    % nonObjIdx = find(strcmp('|>OBJS<|', linkobjs)==0);
    % if numel(nonObjIdx) == numel(linkobjs)
    %     nonObjIdx = find(strcmp('@$(CMD_FILE)', linkobjs)==0);
    % end
    % linkobjs = h.removeCellElements(linkobjs, nonObjIdx);
    linkobjs = { '|>OBJS<|' };
    %end
end
% ------------------------------------------------
% Handle long archiver/linker lines in Windows
% ------------------------------------------------
% Replace object list with a call to a command file
if lRequiresCommandFile
    idx = strcmp( linkobjs, '|>OBJS<|' );
    if any( idx )
        linkobjs{ idx } = '@$(CMD_FILE)';
    end
end
% ------------------------------------------------
% Do not add anymore to the link line when building
% a static library.
% ------------------------------------------------
if (h.BuildOutputType==coder.make.enum.BuildOutput.STATIC_LIBRARY) || intermediateStaticLibTarget
    % ---------------------------------------
    % FORMAT the final LinkObjs list
    % ---------------------------------------
    linkobjs = h.substituteWithBuildToolFileSep( h.getBuildTool( 'Archiver' ), linkobjs );
    % ---------------------------------------
    % The linkobjs should be in opposite
    % order as the dependencies
    % ---------------------------------------
    % linkobjs = fliplr(linkobjs);
    return
    % stop at the object files
end
% ------------------------------------------------
% Handle long linker lines in Windows
% ------------------------------------------------
modelRefToken = '|>MODELREF_LIBS<|';
modelRefRspFileStr = '@$(MODELREF_LINK_RSPFILE)';
modelRefIdx = false(size(linkobjs));
if (h.BuildOutputType==coder.make.enum.BuildOutput.EXECUTABLE ||...
    h.BuildOutputType==coder.make.enum.BuildOutput.SHARED_LIBRARY)
    modelRefIdx = strcmp( linkobjs, modelRefToken );
end

% -----------------------------------------------------------
% Group "MODELREF_LIBS" in case of a One-Pass Linker (g949112)
% -----------------------------------------------------------
lStartLibraryGroup = {};
lEndLibraryGroup = {};
if strcmpi( h.BuildOpts.TargetLangExt, 'cpp' )
    linkerTool = h.ToolchainInfo.getBuildTool( 'C++ Linker' );
else
    linkerTool = h.ToolchainInfo.getBuildTool( 'Linker' );
end
if nnz( linkerTool.Directives.isKey( { 'StartLibraryGroup', 'EndLibraryGroup' } ) )
    lStartLibraryGroup = {linkerTool.getDirective( 'StartLibraryGroup' )};
    lEndLibraryGroup = {linkerTool.getDirective( 'EndLibraryGroup' )};
    idx = strcmp( linkobjs, modelRefToken ) | strcmp( linkobjs, modelRefRspFileStr ) ;
    if any( idx )
        linkobjs{ idx } = [ linkerTool.getDirective( 'StartLibraryGroup' ), ' ', linkobjs{idx}, ' ', linkerTool.getDirective( 'EndLibraryGroup' ) ];
    end
    % Enclose libraries with the --start-group/--end-group linker
    % flags to handle circular library dependencies
    libsIdx =  strcmp(linkobjs, '|>LIBS<|');
    if any(libsIdx)
        linkobjs{ libsIdx } = [ linkerTool.getDirective( 'StartLibraryGroup' ), ' ', linkobjs{libsIdx}, ' ', linkerTool.getDirective( 'EndLibraryGroup' ) ];
    end
end

    
if any(modelRefIdx)
    if lRequiresCommandFile
        % Replace model reference list with a call to a response file
        linkobjs{ modelRefIdx } = modelRefRspFileStr;
    else
        % For model reference library archives, we need a relative path from the build folder to the
        % location of the archive
        [~, lRelativePathToAnchor] = findBuildArg(buildInfo, 'RELATIVE_PATH_TO_ANCHOR');
    
        libExt = getFileExtension(getBuildTool(h, 'Archiver'), 'Static Library');
        
        lLinkLibFullPathsRel = coder.make.internal.getModelRefLinkObjs(...
            h.BuilderArgs.ModelRefLibPathFormat, ...
            lRelativePathToAnchor, ...
            buildInfo.ModelRefs, ...
            buildInfo.Settings.LocalAnchorDir, ...
            libExt);    
        
        makeToolFileSep = h.getBuildAppDirective('FileSeparator');
        lHandleSpacesInPath = coder.make.internal.PathHandleSpaces.WrapWithQuotes;
        lLinkLibFullPathsRel = coder.make.internal.formatModelRefLinkObjs(lLinkLibFullPathsRel, makeToolFileSep, lHandleSpacesInPath);

        % Replace the macro with a list of link objects
        idx = find(modelRefIdx);
        linkobjs = [linkobjs(1:idx-1) ...
                    lStartLibraryGroup lLinkLibFullPathsRel(:)' lEndLibraryGroup ...
                    linkobjs(idx+1:end)];
    end
end

% ---------------------------------------------------
% The link objects should be in opposite order as the
% dependencies.
% IMPORTANT: Do this before adding the system libraries
% ---------------------------------------------------
% linkobjs = fliplr(linkobjs);
% ---------------------------------------
% System libraries - contains -l<<lib>>
% ---------------------------------------
syslibs = h.getMacroToken( h.getMacroOf( 'syslibs' ) );
linkobjs = horzcat( linkobjs, syslibs );
% Toolchain libraries
linkobjs = horzcat( linkobjs, h.getMacroToken( h.getMacroOf( 'toolchainlibs' ) ) );
% FORMAT the final LinkObjs list
linkobjs = h.substituteWithBuildToolFileSep( h.getBuildTool( 'Linker' ), linkobjs );
end
