function [tc, results] = ibis_ami_gnu_gcc_cross
%ibis_ami_gnu_gcc_cross Specifications for "GNU gcc/g++" Cross compiler toolchain.

% Copyright 2011-2023 The MathWorks, Inc.

% Get existing gnu_gcc core toolchain
toolchainDir = fullfile(matlabroot, 'toolbox', 'coder', 'compile', 'tools');
addpath(toolchainDir);
[tc, results] = gnu_gcc;

tc.ShellSetup{1} = 'CALL %SystemDrive%\cygwin64-cross-compiler\cross-compiler\setup_cross-compiler.bat';
tc.ShellCleanup{1} = 'CALL %SystemDrive%\cygwin64-cross-compiler\cross-compiler\cleanup_cross-compiler.bat';

% take care of the format issues due to the version not specified
tc.Name = regexprep(tc.Name, '\s\s\|', ' |'); % remove an extra space before '|'
results.tcFile = regexprep(results.tcFile, '_v.mat', '.mat'); % remove extra '_v'

% Customize toolchain for IBIS-AMI Cross-Compiler
if ~results.error

    % Update top-level data from core toolchain
    tc.Platform  = 'win64';
    tc.Name = 'GNU gcc/g++ cross-compiler | gmake (64-bit Windows)';
    % Setup/Cleanup
    tc.ShellSetup{1} = 'CALL %SystemDrive%\cygwin64-cross-compiler\cross-compiler\setup_cross-compiler.bat';
    tc.ShellCleanup{1} = 'CALL %SystemDrive%\cygwin64-cross-compiler\cross-compiler\cleanup_cross-compiler.bat';
    % Attributes
    tc.addAttribute('RequiresCommandFile');
    tc.addAttribute('RequiresBatchFile');
    % MACROS
    tc.addMacro('MAKEFILE_FILESEP', '/');
  
    %% Modify generic toolchain for IBIS-AMI Linux Cross compiler
    % Set options for GNU C compiler
    tool = tc.getBuildTool('C Compiler');
    tool.setCommand('x86_64-centos7-linux-gnu-gcc.exe');
    tool.setDirective('Preinclude', '');
    tool.setDirective('PreprocessorUndefine', '');
    % Set options for GNU linker
    tool = tc.getBuildTool('Linker');
    tool.setCommand('x86_64-centos7-linux-gnu-gcc.exe');
    % Have to set this to dll, as rtwbuild needs output file to be based on the local platform. Gets renamed later.
    tool.setFileExtension('Executable', '.dll');
    tool.setFileExtension('Shared Library', '.dll');
    % Set options for GNU C++ compiler
    tool = tc.getBuildTool('C++ Compiler');
    tool.setCommand('x86_64-centos7-linux-gnu-g++.exe');
    tool.setInputFileExtensions({'Source'});
    tool.setDirective('Preinclude', '');
    tool.setDirective('PreprocessorUndefine', '');
    % Set options for GNU C++ linker
    tool = tc.getBuildTool('C++ Linker');
    tool.setCommand('x86_64-centos7-linux-gnu-g++.exe');
    % Have to set this to dll, as rtwbuild needs output file to be based on the local platform. Gets renamed later.
    tool.setFileExtension('Executable', '.dll');
    tool.setFileExtension('Shared Library', '.dll');
    % Set options for GNU Archiver
    tool = tc.getBuildTool('Archiver');
    tool.setCommand('x86_64-centos7-linux-gnu-ar.exe');
    % Set options for MEX Tool
    tool = tc.getBuildTool('MEX Tool');
    tool.setFileExtension('MEX', '.mexa64');

    %% Set Builder options
    tc.setBuilderApplication('glnxa64');
    tc.BuilderApplication.Command = coder.make.BuildItem('MAKE','make');
    tc.BuilderApplication.Path = coder.make.BuildItem('MAKE_PATH','');
    
    %% Get the debug flag per build tool
    debugFlag.Linker      = getDebugFlag('Linker');
    debugFlag.CppLinker   = getDebugFlag('C++ Linker');

    %% Modify Baseline Build options
    linkerOpts       = {'-shared -Wl,-rpath,"$(MATLAB_ARCH_BIN)",-L"$(MATLAB_ARCH_BIN)" -Wl,--no-undefined'};
    compatLinkerOpts = {'-Wl,--wrap=memcpy -static-libgcc -static-libstdc++'};
    sharedLinkerOpts = {'-shared -Wl,-rpath,"$(MATLAB_ARCH_BIN)",-L"$(MATLAB_ARCH_BIN)" -Wl,--no-undefined'};
    %cCompilerFlags   = {'-c $(C_STANDARD_OPTS) -fPIC -O3'};
    %cppCompilerFlags = {'-c $(CPP_STANDARD_OPTS) -fPIC -O3'};

    %% Set flags for "Faster Runs" Build Configuration
    cfg = tc.getBuildConfiguration('Faster Runs');
    % Set CFLAGS
    %cfg.setOption('C Compiler', cCompilerFlags);
    % Set CPPFLAGS
    %cfg.setOption('C++ Compiler', cppCompilerFlags);
    % Set CPP_LDFLAGS
    cfg.setOption('C++ Linker', linkerOpts);
    % Set CPP_SHAREDLIB_LDFLAGS
    cfg.setOption('C++ Shared Library Linker', sharedLinkerOpts);
    % Set LDFLAGS
    cfg.setOption('Linker', linkerOpts);
    % Set SHAREDLIB_LDFLAGS
    cfg.setOption('Shared Library Linker', sharedLinkerOpts);

    %% Set flags for "Faster Builds" Build Configuration
    cfg = tc.getBuildConfiguration('Faster Builds');
    % Set CPP_LDFLAGS
    cfg.setOption('C++ Linker', linkerOpts);
    % Set CPP_SHAREDLIB_LDFLAGS
    cfg.setOption('C++ Shared Library Linker', sharedLinkerOpts);
    % Set LDFLAGS
    cfg.setOption('Linker', linkerOpts);
    % Set SHAREDLIB_LDFLAGS
    cfg.setOption('Shared Library Linker', sharedLinkerOpts);

    %% Set flags for "Debug" Build Configuration
    cfg = tc.getBuildConfiguration('Debug');
    % Set CPP_LDFLAGS
    cfg.setOption('C++ Linker', horzcat(linkerOpts, debugFlag.CppLinker));
    % Set CPP_SHAREDLIB_LDFLAGS
    cfg.setOption('C++ Shared Library Linker', horzcat(sharedLinkerOpts, debugFlag.CppLinker));
    % Set LDFLAGS
    cfg.setOption('Linker', horzcat(linkerOpts, debugFlag.Linker));
    % Set SHAREDLIB_LDFLAGS
    cfg.setOption('Shared Library Linker', horzcat(sharedLinkerOpts, debugFlag.Linker));

    %% Add Compatibility Build Configuration
    tc.addBuildConfiguration('Compatibility','Maximize Linux version compatibility');
    cfg = tc.getBuildConfiguration('Compatibility');
    cfg.setOption('Archiver','ruvs');
    cfg.setOption('C Compiler','-c $(C_STANDARD_OPTS) -fPIC -O0');
    cfg.setOption('C++ Compiler','-c $(CPP_STANDARD_OPTS) -fPIC -O0');
    cfg.setOption('C++ Linker', horzcat(linkerOpts, compatLinkerOpts));
    cfg.setOption('C++ Shared Library Linker', sharedLinkerOpts);
    cfg.setOption('Linker', linkerOpts);
    cfg.setOption('Make Tool','-f $(MAKEFILE)');
    cfg.setOption('Shared Library Linker', sharedLinkerOpts);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Helper Functions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    function flag = getDebugFlag(toolkey)
        flag = tc.getBuildTool(toolkey).Directives.getValue('Debug').getRef();
    end
end
% LocalWords:  toolchain gmake maci CRL ansi msvc vc openwatc watc glnx optims
% LocalWords:  CFLAGS CPPFLAGS lccopts microsoft msdn aspx intel Wl fno rpath
% LocalWords:  ruvs Wwrite Winline Wstrict Wnested externs Wpointer Wcast qual
% LocalWords:  Wshadow SFUN COPTIMFLAGS outdir LDFLAGS MODELLIB LIBFIXPT
% LocalWords:  LIBMWMATHUTIL LIBMWIPP LIBMWSL FILEIO fopenmp DOMPLIBNAME os
% LocalWords:  libiomp liomp
