function [makeDeps, libPaths] = getMakeDependencies...
        (lBuildInfo, lPrecompiledLibSuffix, finalTarget, outputDir)

%   Copyright 2012-2020 The MathWorks, Inc.

    assert(isempty(lBuildInfo.TargetLibSuffix), ...
           'TargetLibSuffix must always be empty for Toolchain builds');

    skipLibs = false;
    
    incGrps = {};
    excGrps = {};

    [syslibs, libPaths] = lBuildInfo.getSysLibInfo();

    % Get the build tools and the initial file extensions
    tcInfo    = lBuildInfo.getBuildToolInfo('ToolchainInfo');    
    [tools, ext] = coder.make.internal.getToolchainBuildTools(tcInfo);

    % Assume it is gcc/gmake-based and add library directive ("-l") in front
    cmdLineSysLibs = strcat(tools.ld.getDirective('Library'), syslibs);
    
    % the build variant determines the final extension, special suffices and
    % other build specific info.
    bVariant = lBuildInfo.getBuildToolInfo('BuildVariant');
    buildDir  = '.';
    
    % ------------------------------------
    % Get the source module dependencies
    % ------------------------------------
    srcDeps = locGetModules(lBuildInfo,ext,incGrps,excGrps);
    numSrcs = length(srcDeps.srcs);
    
    depLst = srcDeps.objs;    
    additionalDeps = {};

    % --------------------------------------
    % Get the referenced-model dependencies
    % --------------------------------------
    mdlRefDeps = {};
    if (bVariant ~= coder.make.enum.BuildVariant.MODEL_REFERENCE_CODER)
        for i=1:length(lBuildInfo.ModelRefs)
            tmpDeps = locGetLibDependencies(lBuildInfo.ModelRefs(i),...
                                            'MdlRef',...
                                            ext, lPrecompiledLibSuffix, ...
                                            buildDir, ...
                                            lBuildInfo.BuildTools.BuildOpts, ...
                                            tools);
            mdlRefDeps = [mdlRefDeps tmpDeps]; %#ok<AGROW>
            depLst{end+1} = tmpDeps{1}{2}; %#ok<AGROW>
        end
    end

    % ----------------------------------
    % Get the library dependencies
    % ----------------------------------    
    libDeps = {};    
    for i=1:length(lBuildInfo.LinkObj)
        % LinkObjs under the PREBUILT_OBJECTS group should not be added the
        % library dependency list. This group is used by XIL and these
        % modules will end up next to the OBJS on the link line for the 
        % XIL executable
        if ~strcmp(lBuildInfo.LinkObj(i).Group, 'PREBUILT_OBJECTS')
            if lBuildInfo.LinkObj(i).BuildInPlace
                tag = 'BuildInPlaceLib';
            else
                tag = 'Lib';
            end
            tmpDeps = locGetLibDependencies(lBuildInfo.LinkObj(i),...
                                            tag,...
                                            ext, lPrecompiledLibSuffix, ...
                                            buildDir, ...
                                            lBuildInfo.BuildTools.BuildOpts, ...
                                            tools);
            if ~skipLibs
                libDeps = [libDeps tmpDeps]; %#ok<AGROW>
                depLst{end+1} = tmpDeps{1}{2}; %#ok<AGROW>
            else
                if lBuildInfo.LinkObj(i).BuildInPlace
                    libDeps = [libDeps tmpDeps]; %#ok<AGROW>
                    additionalDeps{end+1} = tmpDeps{1}{2}; %#ok<AGROW>
                end
            end
        end
    end

    % --------------------------------------------
    % Get the standalone source file dependencies
    % --------------------------------------------
    sDeps(1:numSrcs) = {{}};
    for i=1:numSrcs
        sDeps{i} = locCreateDepEntry('Module',...
                                     srcDeps.objs{i},...
                                     srcDeps.srcs(i),...
                                     '',...
                                     {},...
                                     buildDir,...
                                     true, ...
                                     {});
    end

    % ------------------------------------------------
    % Create the final target dependencies
    % ------------------------------------------------
    
    noPathOnTarget = false;
    firstDep = locCreateDepEntry('FinalTarget',...
                                 finalTarget,...
                                 depLst,...
                                 '',...
                                 cmdLineSysLibs,...
                                 outputDir,...
                                 noPathOnTarget, ...
                                 additionalDeps);

    % ------------------------------------------------
    % Put together all dependencies in this build
    % ------------------------------------------------
    makeDeps = [{firstDep} sDeps mdlRefDeps libDeps];
end

function libDeps = locGetLibDependencies(lib,tag,ext, lPrecompiledLibSuffix, ...
                                         buildDir, buildOpts,...
                                         tools)

    if lib.LinkOnly
        % LinkOnly => ignore modules
        numSrcs = 0;    
        depLst = {};
        % no make variable required
        mvRoot     = '';
        libName    = lib.Name;

        % Capture the library name without extension
        modMakeVar = libName;
        
        % Add library extension if needed
        libExt = tools.ar.getFileExtension('Static Library');
        libName = coder.make.internal.addLibExtIfMissing(libName, libExt);
        
        outputDir  = lib.Path;
        modOutDir  = outputDir;
    else    
        srcDeps = locGetModules(lib,ext,{},{});
        
        numSrcs = length(srcDeps.srcs);
        depLst  = srcDeps.objs;
        if lib.BuildInPlace
            mvRoot     = lib.getMakeVarRoot();
            libName    = ['$(' mvRoot '_LIB)'];
            modMakeVar = libName;
            depLst     = {['$(' mvRoot '_SRC)']};
            outputDir  = ['$(' mvRoot '_SRC_DIR)'];
            modOutDir  = outputDir;
        else
            [~,mvRoot] = fileparts(lib.Name);
            libName    = lib.Name;

            % Capture the library name without extension
            modMakeVar = libName;

            % Add library extension if needed
            libExt = tools.ar.getFileExtension('Static Library');
            libName = coder.make.internal.addLibExtIfMissing(libName, libExt);

            if strcmpi(tag, 'MdlRef')
                % In Mac, the referenced library is not copied over from
                % the its original path to the build folder. 
                outputDir = lib.Path;
                modOutDir  = outputDir;
            else
                outputDir  = buildDir;
                modOutDir  = outputDir;
                if lib.Precompiled
                    [~, tmpLibName] = fileparts(lib.Name);
                    tmpLibName     = [tmpLibName lPrecompiledLibSuffix];
                    libPath    = lib.formatPaths(lib.Path);
                    fullLib    = fullfile(libPath,tmpLibName);
                    if exist(fullLib,'file')
                        [~, mvRoot] = fileparts(tmpLibName);
                        libName     = tmpLibName;
                        outputDir = libPath;
                    else
                        DAStudio.warning('RTW:buildInfo:missingPrecompLib',...
                                         fullLib);
                    end
                end
            end
        end
    end

    numDeps = numSrcs+1;
    libDeps(1:numDeps) = {{}};
    libDeps{1} = locCreateDepEntry(tag,...
                                   libName,...
                                   depLst,...
                                   mvRoot,...
                                   {},...
                                   outputDir,...
                                   lib.BuildInPlace, ...
                                   {});
    offset = 1;
    for i=1:numSrcs
        libDeps{i + offset} = locCreateDepEntry([tag 'Module'],...
                                                srcDeps.objs{i},...
                                                srcDeps.srcs(i),...
                                                modMakeVar,...
                                                {},...
                                                modOutDir,...
                                                lib.BuildInPlace, ...
                                                {});
    end
    
end

function mods = locGetModules(lBuildInfo,ext,incGrps,excGrps)

    mods.srcs = lBuildInfo.getSourceFiles(true,  false,incGrps,excGrps);
    mods.objs = lBuildInfo.getSourceFiles(false, false,incGrps,excGrps);
    
    if length(unique(mods.objs)) ~= length(mods.objs)
        msg = message('coder_compile:CoderCompile:duplicateSrcFilename',...
                       strjoin(mods.objs));
        exc = MException(msg.Identifier, string(msg));
        throw(exc);
    end

    % Append a default source extension if none is specified
    for i=1:numel(mods.srcs)
        [~, ~, fext] = fileparts(mods.srcs{i});
        if isempty(fext)
            mods.srcs{i} = [mods.srcs{i} ext.c.input];
            mods.objs{i} = [mods.objs{i} ext.c.input];
        end
    end
    % Replace the source file extensions with object file extensions
    if isfield(ext, 'cpp')
        for i=1:numel(ext.cpp)
            pat = [regexptranslate('escape',ext.cpp(i).input), '$'];
            mods.objs = regexprep(mods.objs, pat, ext.cpp(i).output, 'ignorecase');
        end
    end
    if isfield(ext, 'asm')
        for i=1:numel(ext.asm)
            pat = [regexptranslate('escape',ext.asm(i).input), '$'];
            mods.objs = regexprep(mods.objs, pat, ext.asm(i).output, 'ignorecase');
        end
    end
    for i=1:numel(ext.c)
        pat = [regexptranslate('escape',ext.c(i).input), '$'];
        mods.objs = regexprep(mods.objs, pat, ext.c(i).output, 'ignorecase');
    end

end

function depEntry = locCreateDepEntry(targetType,...
                                      targetFilename,...
                                      targetDeps, ...
                                      makeVarName,...
                                      additionalCmdLineDeps,...
                                      outputDir,...
                                      noPathOnTarget,...
                                      additionalDeps)

    if ~noPathOnTarget
        finalTarget = fullfile(outputDir, targetFilename);
    else
        finalTarget = targetFilename;
    end

    pmSrc = '';
    
    depEntry = {targetType,...
                finalTarget,...
                targetDeps,...
                makeVarName,...
                additionalCmdLineDeps,...
                outputDir,...
                pmSrc,...
                additionalDeps};
end
