function [tc, results] = ibis_ami_gnu_gcc
%ibis_ami_gnu_gcc Specifications for "GNU gcc/g++" 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;

% Customize toolchain for IBIS-AMI
if ~results.error
    %% Modify generic toolchain for IBIS-AMI
    % Set Executable extension for C linker
    tool = tc.getBuildTool('Linker');
    tool.setFileExtension('Executable', '.so');
    % Set Executable extension for C++ linker
    tool = tc.getBuildTool('C++ Linker');
    tool.setFileExtension('Executable', '.so');
    % Limit Executable extensions for C++ compiler
    tool = tc.getBuildTool('C++ Compiler');
    tool.setInputFileExtensions({'Source'});

    %% 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'};

    %% Set flags for "Faster Runs" Build Configuration
    cfg = tc.getBuildConfiguration('Faster Runs');
    % 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
