function code_lcc_make_file(fileNameInfo,buildInfo,modelName)

% CODE_LCC_MAKE_FILE(FILENAMEINFO)

%   Copyright 1995-2022 The MathWorks, Inc.
%     
	global gMachineInfo gTargetInfo %#ok<GVMIS>

    if(strcmp(computer,'PCWIN64'))
        lccRoot =  fullfile(matlabroot,'sys','lcc64','lcc64');
        projectInfo.cc = [lccRoot,'\bin\lcc64.exe'];
        projectInfo.ld = [lccRoot,'\bin\lcclnk64.exe'];
        projectInfo.libcmd = [lccRoot,'\bin\lcclib64.exe'];
    else
        lccRoot =  fullfile(matlabroot,'sys','lcc');
        projectInfo.cc = [lccRoot,'\bin\lcc.exe'];
        projectInfo.ld = [lccRoot,'\bin\lcclnk.exe'];
        projectInfo.libcmd = [lccRoot,'\bin\lcclib.exe'];
    end

    %
    % g2680582: this fix allows the use of $(START_DIR) to represent the local anchor directory
    % where source (or header) file directories may reside when using coder.updateBuildInfo
    % (path expansion methods use this setting to expand the START_DIR macro)
    %
    if gTargetInfo.codingSFunction
        buildInfo.Settings.LocalAnchorDir = fileNameInfo.projectDirArray{1};
    end

	fileName = fullfile(fileNameInfo.targetDirName,fileNameInfo.makeBatchFile);
   sf_echo_generating('Coder',fileName);
	file = fopen(fileName,'Wt');
	if file<3
		construct_coder_error([],getString(message('Stateflow:sfprivate:error_FailedToCreateFile',fileName)),1);
	end
fprintf(file,'"%s\\bin\\lccmake.exe" -f %s\n',lccRoot,fileNameInfo.lccMakeFile);
	fclose(file);

	projectInfo.targetDirName = fileNameInfo.targetDirName;
	projectInfo.handlesSpaces = 1;
	projectInfo.nameDirective = '-o ';

    projectInfo.cflags = [getCatString(buildInfo.getCompileFlags) getCatString(buildInfo.getDefines)];
    projectInfo.ldflags = getCatString(buildInfo.getLinkFlags);

	projectInfo.libflags = '';
	
	projectInfo.makeFileName = fileNameInfo.lccMakeFile;

    thirdPartyExcludes = {'USER_INCLUDES',...
        'AUX_INCLUDES','ML_INCLUDES','SL_INCLUDES','SF_INCLUDES'};
    projectInfo.includeDirs = buildInfo.getIncludePaths(true, thirdPartyExcludes);

    thirdPartyIncludes = buildInfo.getIncludePaths(true, {}, thirdPartyExcludes);
    if ~isempty(thirdPartyIncludes)
        for i = 1:length(thirdPartyIncludes)
            path = thirdPartyIncludes{i};
            if coder.make.internal.isRelativePath(path)
                thirdPartyIncludes{i} = [fileNameInfo.projectDirArray{1}, filesep, path];
            end
        end
        thirdPartyIncludes = CGXE.Utils.fix_windows_paths_for_make_file(thirdPartyIncludes);
        projectInfo.includeDirs = [projectInfo.includeDirs thirdPartyIncludes];
    end
    if gTargetInfo.codingSFunction 
        libraries  =arrayfun(@(BI)fullfile(BI.Path,BI.Name),buildInfo.getLinkObjects,'UniformOutput', false)';
        projectInfo.libraries = strrep(libraries,'$(MATLAB_ROOT)',matlabroot);
    end

    sourceGroups = {'MODULE_SRCS','MODEL_SRC','MODEL_REG', ...
        'AUX_SRCS','USER_SRCS'};
    projectInfo.sourceFiles = buildInfo.getSourceFiles(true,true,sourceGroups);

    thirdPartyExcludeGroups = sourceGroups;
    projectInfo.thirdPartySrcs = buildInfo.getSourceFiles(true,true, {},...
        thirdPartyExcludeGroups);
    projectInfo.thirdPartySourcePaths = buildInfo.getSourcePaths(true);

    if gTargetInfo.codingSFunction
        for i = 1:length(projectInfo.thirdPartySourcePaths)
            if coder.make.internal.isRelativePath(projectInfo.thirdPartySourcePaths{i})
                projectInfo.thirdPartySourcePaths{i} = [fileNameInfo.projectDirArray{1}, filesep, projectInfo.thirdPartySourcePaths{i}];
            end
        end
    end

	if(gTargetInfo.codingLibrary)
		projectInfo.codingLibrary = 1;
		projectInfo.outputFileName = [gMachineInfo.machineName,'_',gMachineInfo.targetName,'.lib'];
	else
		projectInfo.codingLibrary = 0;
			projectInfo.outputFileName = [gMachineInfo.machineName,'_',gMachineInfo.targetName,'.',mexext];
		end
	projectInfo.preLinkCommand = '';
	projectInfo.postLinkCommand = '';
%
% g2680582: this fix cleans the use of the local anchor dir as it was not originally set
% from with the gTargetInfo
%
if gTargetInfo.codingSFunction
    buildInfo.Settings.LocalAnchorDir = '';
end
	lcc_make_gen(projectInfo,fileNameInfo,buildInfo,modelName);	

function lcc_make_gen(projectInfo,fileNameInfo,buildInfo,modelName)

%Escape '#' in directories if there is one.
projectInfo = escapeHashInDirs(projectInfo);

	fileName = fullfile(projectInfo.targetDirName,projectInfo.makeFileName);
  sf_echo_generating('Coder',fileName);
	file = fopen(fileName,'Wt');
	if file<3
		construct_coder_error([],getString(message('Stateflow:sfprivate:error_FailedToCreateFile',fileName)),1);
	end

	if(projectInfo.handlesSpaces)
		quoteChar = '"';
	else
		quoteChar = '';
	end

	DOLLAR = '$';
fprintf(file,'CC     = %s%s%s\n',quoteChar,projectInfo.cc,quoteChar);
fprintf(file,'LD     = %s%s%s\n',quoteChar,projectInfo.ld,quoteChar);
fprintf(file,'LIBCMD = %s%s%s\n',quoteChar,projectInfo.libcmd,quoteChar);
fprintf(file,'CFLAGS = %s\n',projectInfo.cflags);
fprintf(file,'LDFLAGS = %s\n',projectInfo.ldflags);
fprintf(file,'LIBFLAGS = %s\n',projectInfo.libflags);
fprintf(file,'\n');

	projectInfo.objectFiles = [projectInfo.sourceFiles projectInfo.thirdPartySrcs];
	for i=1:length(projectInfo.objectFiles)
		sourceFile = projectInfo.objectFiles{i};
		objectFile = [sourceFile(1:end-1),'obj'];
		fileSeps = find(objectFile=='\');
		if(~isempty(fileSeps))
			objectFile = objectFile(fileSeps(end)+1:end);
		end
		projectInfo.objectFiles{i} = objectFile;
	end


    includeDirString = '';
    if(~isempty(projectInfo.includeDirsEscaped))
        for i = 1:length(projectInfo.includeDirsEscaped)
            includeDirString	= [includeDirString,' -I',quoteChar,projectInfo.includeDirsEscaped{i},quoteChar,' ']; %#ok<AGROW>
        end
    end

    if ~isempty(fileNameInfo.auxInfo.includePaths)
        for i = 1:length(fileNameInfo.auxInfo.includePaths)
            path = fileNameInfo.auxInfo.includePaths{i};
			includeDirString = [includeDirString,' -I',quoteChar,path,quoteChar,' ']; %#ok<AGROW>
        end
    end
	projectInfo.objectListFile = [projectInfo.makeFileName,'o'];
	projectInfo.objectListFilePath = fullfile(projectInfo.targetDirName,projectInfo.objectListFile);
    fileNameInfo.objListFile = projectInfo.objectListFile;

fprintf(file,'OBJECTS = \\\n');
	for i= 1:length(projectInfo.objectFiles)
fprintf(file,'	%s%s%s\\\n',quoteChar,projectInfo.objectFiles{i},quoteChar);
	end
fprintf(file,'\n');
fprintf(file,'INCLUDE_PATH=%s\n',includeDirString);
fprintf(file,' \n');
fprintf(file,'\n');
	projectInfo.preLinkCommand = '';
	projectInfo.postLinkCommand = '';
    excludeGroups = {'SFCLIB','USER_LIBS','LINK_MACHINE_LIBS', ...
     'LINK_MACHINE_OBJLIST','TMWLIB','PARLIB'};

    userGroups = {};
	if projectInfo.codingLibrary
fprintf(file,'%s : %s(MAKEFILE) %s(OBJECTS)\n',projectInfo.outputFileName,DOLLAR,DOLLAR);
  	code_lcc_objlist_file(projectInfo.objectListFilePath,projectInfo.objectFiles,projectInfo.libraries,quoteChar);

    libObjectListFile = ['lib_' projectInfo.objectListFile];
    CGXE.Coder.code_append_user_external_link_flags_for_library(libObjectListFile,  fileNameInfo.targetDirName, buildInfo);
    libObjectListFilePath = fullfile(projectInfo.targetDirName, libObjectListFile );
    tplibraries  =arrayfun(@(BI)fullfile(BI.Path,BI.Name), ...
        buildInfo.getLinkObjects(userGroups,excludeGroups),'UniformOutput', false)';
    thirdPartyLibs = strrep(tplibraries,'$(MATLAB_ROOT)',matlabroot);
    code_lcc_objlist_file(libObjectListFilePath,{},thirdPartyLibs,quoteChar);
    CGXE.Coder.code_append_syslibs_to_objlist_file(libObjectListFile, ...
            fileNameInfo.targetDirName, buildInfo, modelName);
		if(~isempty(projectInfo.preLinkCommand))
fprintf(file,'	%s\n',projectInfo.preLinkCommand);
		end
fprintf(file,'	%s(LIBCMD) %s(LIBFLAGS) /OUT:%s *.obj\n',DOLLAR,DOLLAR,projectInfo.outputFileName);
		if(~isempty(projectInfo.postLinkCommand))
fprintf(file,'	%s\n',projectInfo.postLinkCommand);
		end
    else
        code_lcc_objlist_file(projectInfo.objectListFilePath,projectInfo.objectFiles,projectInfo.libraries,quoteChar)

        CGXE.Coder.code_append_syslibs_to_objlist_file(projectInfo.objectListFile, ...
            fileNameInfo.targetDirName, buildInfo, modelName); 
fprintf(file,'%s : %s(MAKEFILE) %s(OBJECTS)\n',projectInfo.outputFileName,DOLLAR,DOLLAR);
		if(~isempty(projectInfo.preLinkCommand))
fprintf(file,'	%s\n',projectInfo.preLinkCommand);
		end
fprintf(file,'	%s(LD) %s(LDFLAGS) %s%s @%s\n',DOLLAR,DOLLAR,projectInfo.nameDirective,projectInfo.outputFileName,projectInfo.objectListFile);
		if(~isempty(projectInfo.postLinkCommand))
fprintf(file,'	%s\n',projectInfo.postLinkCommand);
		end
	end
    numSrcs = length(projectInfo.sourceFilesEscaped);
	for i=1:numSrcs
fprintf(file,'%s :	%s%s%s\n',projectInfo.objectFiles{i},quoteChar,projectInfo.sourceFilesEscaped{i},quoteChar);
fprintf(file,'	%s(CC) %s(CFLAGS) %s(INCLUDE_PATH) %s%s%s\n',DOLLAR,DOLLAR,DOLLAR,quoteChar,projectInfo.sourceFilesEscaped{i},quoteChar);
	end

    for i=1:length(projectInfo.thirdPartySrcsEscaped)
        [fullSrcName, srcFileName] = CGXE.Utils.tokenizeFileFromModel(projectInfo.thirdPartySrcsEscaped{i},...
            modelName, projectInfo.thirdPartySourcePaths);
        objFileName = [srcFileName '.obj'];
fprintf(file,'%s :	"%s"\n',objFileName,fullSrcName);
fprintf(file,'	%s(CC) %s(CFLAGS) %s(INCLUDE_PATH) "%s"\n',DOLLAR,DOLLAR,DOLLAR,fullSrcName);
    end

	fclose(file);

function code_lcc_objlist_file(objListFile,objectFiles,libraryFiles,quoteChar)

	fileName = objListFile;
  sf_echo_generating('Coder',fileName);
	file = fopen(fileName,'Wt');
	if file<3
		construct_coder_error([],getString(message('Stateflow:sfprivate:error_FailedToCreateFile',fileName)),1);
	end

	for i=1:length(objectFiles)
fprintf(file,'%s%s%s\n',quoteChar,objectFiles{i},quoteChar);
	end
	for i=1:length(libraryFiles)
        [~,~,ext] = fileparts(libraryFiles{i});
        if isequal(ext,'.mol')
            libLinkFile = change_file_ext(libraryFiles{i},'.lmko');
            if exist(libLinkFile,'file')
                linkObjStr = fileread(libLinkFile);
                linkObjStr = strtrim(regexprep(linkObjStr, '[\n\r]+',newline));            
                %g1335830: dont create empty lines which the linker cannot handle
                if(~isempty(linkObjStr))                
fprintf(file,'%s\n',linkObjStr);
                end
            end
        else
fprintf(file,'%s%s%s\n',quoteChar,libraryFiles{i},quoteChar);
        end
	end

	fclose(file);

function newFileName = change_file_ext(fileName, extension)    
[pathstr,name] = fileparts(fileName);
newFileName = [pathstr filesep name extension];

function projectInfo = escapeHashInDirs(projectInfo)
%Escape the '#' sign in the directories if there is one. Without this, if
%there is a '#' sign the makefile will consider it as a seperator between
%files.

projectInfo.includeDirsEscaped = strrep(projectInfo.includeDirs, '#', '\#');
projectInfo.librariesEscaped = strrep(projectInfo.libraries, '#', '\#');
projectInfo.sourceFilesEscaped = strrep(projectInfo.sourceFiles, '#', '\#');
projectInfo.sourceFilesEscaped = strrep(projectInfo.sourceFilesEscaped, '$', '$$');
projectInfo.thirdPartySrcsEscaped = strrep(projectInfo.thirdPartySrcs, '#', '\#');

function str = getCatString(incell)
%Conatenate all the strings in cell array of strings.
str = sprintf('%s ',incell{:});
if ~isempty(str)
    str(end) = [];
end
