#!/bin/sh
#$Id: set_compiler_flags,v 1.63 2025/09/11 09:09:52 marcum Exp $
#FUNCTION

#*******************************************************************************
# Function to set SimSys compiler flags for current system.
#
# Variables that are required to be set by the calling command
#
#   arch_type		: current system architecture type
#   debug_flag		: compiler debug option flag (yes or no)
#   prof_flag		: compiler prof option flag (yes or no)
#   include_dir		: list of include file directories
#   opt_define_flags    : optional compiler -D define flags
#
#   SIMSYS_DEBUG	: internal code debug option flag (set or not set)
#   SIMSYS_LICENSE_KEY	: SimSys license key option flag (set or not set)
#   SIMSYS_FLEXLM	: FlexLM license manager option flag (set or not set)
#   XWINDOW_ENABLE	: X-Window option flag (set or not set)
#
# Variables set by this command;
#
#   ar_flags		: ar flags for replacing a routine
#   cpp_compiler_opt0	: C++ compiler with flags for no optimization
#   cpp_compiler_opt1	: C++ compiler with optimization level 1 flags
#   cpp_compiler_opt2	: C++ compiler with optimization level 2 flags
#   cpp_linker		: C++ linker
#   cpp_other_libs	: Other system libraries for linking with C++ linker
#   c_compiler_opt0	: C compiler with flags for no optimization
#   c_compiler_opt1	: C compiler with optimization level 1 flags
#   c_compiler_opt2	: C compiler with optimization level 2 flags
#   c_linker		: C linker
#   c_other_libs	: Other system libraries for linking with C linker
#   f_compiler_opt0	: Fortran compiler with flags for no optimization
#   f_compiler_opt1	: Fortran compiler with optimization level 1 flags
#   f_compiler_opt2	: Fortran compiler with optimization level 2 flags
#   f_linker		: Fortran linker
#   f_other_libs	: Other system libraries for linking with Fortran linker
#   purify_linker	: Purify linker (if available) with flags
#   shared_lib_linker	: Shared library linker with flags
#   shared_lib_suffix	: Shared library file name suffix
#   lib_prefix		: Library file name prefix
#   static_lib_suffix	: Static library file name suffix
#   symtable		: Command to add/update symbolic table
#
#*******************************************************************************

set_compiler_flags ()
{
# -------------------------
# Set include and lib flags
# -------------------------

	include_flag=
	other_lib_flags=

	for dir_name in ${include_dir}; do

		include_flag="${include_flag} -I$dir_name"

		if [ "${mpi_code}" = "yes" ] && [ "${mpi_include_dir}" ] && [ "${mpi_libs}" ]; then

			include_flag="${include_flag} -I${mpi_include_dir}"

			other_lib_flags="${other_lib_flags} ${mpi_libs}"
		fi

		if [ "${X11_code}" = "yes" ] && [ "${X11_include_dir}" ] && [ "${X11_libs}" ]; then

			include_flag="${include_flag} -I${X11_include_dir}"

			other_lib_flags="${other_lib_flags} ${X11_libs}"
		fi
	done

# ----------------
# Set define flags
# ----------------

	if [ "${opt_define_flags}" != "" ]; then

		define_flags="${opt_define_flags}"
	else

		define_flags=
	fi

# -------------------------------------
# Set compiler flags for current system
# -------------------------------------

	sanitize_options=

	case "${arch_type}"
	in

		WIN*)

			ar_flags=rv

			symtable=ranlib

			purify_linker=

			shared_lib_linker="x86_64-w64-mingw32-gcc -mno-stack-arg-probe -shared"
			shared_lib_suffix=dll
			static_lib_suffix=lib
			lib_prefix=

			if [ "${X11_libs}" = "" ]; then

				#linker_flags="-mno-cygwin -Wl,--allow-multiple-definition -Wl,-static"
				linker_flags="-Wl,-static"
			else

				linker_flags="-Wl,-static"

				X11_libs="${X11_libs} /lib/mingw/libcrtdll.a"
			fi

			compiler_flags="${define_flags}"
			compiler_flags="${compiler_flags} -mno-stack-arg-probe"

			if [ "${arch_type}" = "WIN64" ]; then

				cpp_compiler="x86_64-w64-mingw32-g++"
				c_compiler="x86_64-w64-mingw32-gcc"
				f_compiler="x86_64-w64-mingw32-gfortran -cpp -fno-second-underscore"

				compiler_flags="${compiler_flags} -m64"
				shared_lib_linker="${shared_lib_linker} -m64"

			elif [ "${arch_type}" = "WIN32" ]; then

				cpp_compiler="i686-w64-mingw32-g++"
				c_compiler="i686-w64-mingw32-gcc"
				f_compiler="i686-w64-mingw32-gfortran -cpp -fno-second-underscore"

				compiler_flags="${compiler_flags} -m32"
				shared_lib_linker="${shared_lib_linker} -m32"
			fi

			linker_flags="${linker_flags} -s -Wl,--unresolved-symbols=ignore-in-shared-libs"

			cpp_compiler_debug="${cpp_compiler} ${define_flags} -c -O0 ${include_flag} -W -Wall -Wno-unused-parameter -Wno-unused-but-set-variable -g"
			cpp_compiler_opt0="${cpp_compiler} ${compiler_flags} -c -O0 ${include_flag}"
			cpp_compiler_opt1="${cpp_compiler} ${compiler_flags} -c -O1 ${include_flag}"
			cpp_compiler_opt2="${cpp_compiler} ${compiler_flags} -c -O3 ${include_flag}"
			cpp_linker="${cpp_compiler} ${linker_flags}"
			cpp_linker_debug="${cpp_compiler} ${linker_flags} -W -Wall -Wno-unused-parameter -Wno-unused-but-set-variable -g"
 			cpp_other_libs="${other_lib_flags}"

			c_compiler_debug="${c_compiler} ${compiler_flags} -c -O0 ${include_flag} -W -Wall -Wno-unused-parameter -Wno-unused-but-set-variable -g"
			c_compiler_opt0="${c_compiler} ${compiler_flags} -c -O0 ${include_flag}"
			c_compiler_opt1="${c_compiler} ${compiler_flags} -c -O1 ${include_flag}"
			c_compiler_opt2="${c_compiler} ${compiler_flags} -c -O3 ${include_flag}"
			c_linker="${c_compiler} ${linker_flags}"
			c_linker_shared="${c_linker}"
			c_linker_debug="${c_compiler} ${linker_flags} -W -Wall -Wno-unused-parameter -Wno-unused-but-set-variable -g"
 			c_other_libs="${other_lib_flags}"

			f_compiler_debug="${f_compiler} ${define_flags} -c -O0 -W -Wall -Wno-unused-parameter -Wno-unused-but-set-variable -g"
			f_compiler_opt0="${f_compiler} ${compiler_flags} -c -O0"
			f_compiler_opt1="${f_compiler} ${compiler_flags} -c -O"
			f_compiler_opt2="${f_compiler} ${compiler_flags} -c -O"
			f_linker="${f_compiler} ${linker_flags}"
			f_linker_debug="${f_compiler} ${linker_flags} -W -Wall -Wno-unused-parameter -Wno-unused-but-set-variable -g"
 			f_other_libs="${other_lib_flags}"
		;;

		Linux*)

			ar_flags=rvU

			symtable=ranlib

			shared_lib_linker="gcc -shared"
			shared_lib_suffix=so
			static_lib_suffix=a
			lib_prefix=lib

			linker_flags="-Wl,-z,muldefs -Wl,--unresolved-symbols=ignore-in-shared-libs -Wl,-rpath=\$ORIGIN -Wl,-rpath-link=\$ORIGIN"

			f_linker_flags="${linker_flags}"

			static_linker_flags="-static"

			if [ "${static_flag}" != "" ]; then

				linker_flags="${linker_flags} ${static_linker_flags}"

				f_linker_flags="${f_linker_flags} ${static_linker_flags}"
			fi

			if [ "${prof_flag}" = "" ]; then

				compiler_flags=
			else
				compiler_flags="-pg"
			fi

			if [ "${arch_type}" = "Linux-x86-64" ]; then

				compiler_flags="${compiler_flags} -m64"
			fi

			cpp_compiler="g++ -fPIC ${compiler_flags}"
			c_compiler="gcc -fPIC ${compiler_flags}"

			f_compiler="gfortran ${compiler_flags} -cpp -fno-second-underscore"
			f_arch_libs="-lgfortran -lgfortranbegin"

			cpp_opt2_flags="-O3"
			c_opt2_flags="-O3"
			f_opt2_flags="-O3"

			cpp_debug_compiler="${cpp_compiler} -W -Wall -Wno-unused-parameter -Wno-unused-but-set-variable -O0 -g"
			c_debug_compiler="${c_compiler} -W -Wall -Wno-unused-parameter -Wno-unused-but-set-variable -O0 -g"
			f_debug_compiler="${f_compiler} -W -Wall -Wno-unused-parameter -Wno-unused-but-set-variable -O0 -g"

			if [ "${X11_libs}" != "" ] && [ "${static_flag}" != "" ]; then

				arch_libs="-lm -lrt -lpthread"
			else

				arch_libs="-lm -lrt"
			fi

			cpp_compiler_debug="${cpp_debug_compiler} ${define_flags} -c ${include_flag}"
			cpp_compiler_opt0="${cpp_compiler} ${define_flags} -c -O0 ${include_flag}"
			cpp_compiler_opt1="${cpp_compiler} ${define_flags} -c -O1 ${include_flag}"
			cpp_compiler_opt2="${cpp_compiler} ${define_flags} -c ${cpp_opt2_flags} ${include_flag}"
			cpp_linker="${cpp_compiler} ${linker_flags}"
			cpp_linker_debug="${cpp_debug_compiler} ${linker_flags}"
			cpp_other_libs="${arch_libs} ${other_lib_flags}"

			c_compiler_debug="${c_debug_compiler} ${define_flags} -c ${include_flag}"
			c_compiler_opt0="${c_compiler} ${define_flags} -c -O0 ${include_flag}"
			c_compiler_opt1="${c_compiler} ${define_flags} -c -O1 ${include_flag}"
			c_compiler_opt2="${c_compiler} ${define_flags} -c ${c_opt2_flags} ${include_flag}"
			c_linker="${c_compiler} ${linker_flags}"
			c_linker_shared="${c_linker}"
			c_linker_debug="${c_debug_compiler} ${linker_flags}"
			c_other_libs="${arch_libs} ${other_lib_flags}"

			f_compiler_debug="${f_debug_compiler} ${define_flags} -c"
			f_compiler_opt0="${f_compiler} ${define_flags} -c -O0"
			f_compiler_opt1="${f_compiler} ${define_flags} -c -O1"
			f_compiler_opt2="${f_compiler} ${define_flags} -c ${f_opt2_flags}"

			f_linker="${c_compiler} ${f_linker_flags}"
			f_linker_debug="${c_debug_compiler} ${f_linker_flags}"
			f_other_libs="${arch_libs} ${other_lib_flags}"

			sanitize_options="-fsanitize=address -fno-optimize-sibling-calls -fno-omit-frame-pointer"
		;;

		MacOSX*)

			ar_flags=rv

			symtable=ranlib

			purify_linker=

			shared_lib_linker="clang -dynamiclib"
			shared_lib_suffix=dylib
			static_lib_suffix=a
			lib_prefix=lib

			if [ "${prof_flag}" = "" ]; then

				compiler_flags=
			else
				compiler_flags="-pg"
			fi

			if [ "${arch_type}" = "MacOSX-arm64" ]; then

				cpp_compiler="clang++ -target arm64-apple-macos11 -mmacosx-version-min=11"
				c_compiler="clang -target arm64-apple-macos11 -mmacosx-version-min=11"
				f_compiler="gfortran -mmacosx-version-min=11"
			else
				cpp_compiler="clang++ -target x86_64-apple-macos10.13 -mmacosx-version-min=10.13"
				c_compiler="clang -target x86_64-apple-macos10.13 -mmacosx-version-min=10.13"
				f_compiler="gfortran -mmacosx-version-min=10.13"
			fi

			c_linker_flags="-headerpad_max_install_names"
			c_opt0_flags="-O0"
			c_opt1_flags="-O1"
			c_opt2_flags="-O3"

			compiler_version_flags=

			f_arch_libs="-lgfortran -lgfortranbegin"
			f_linker_flags=
			f_opt0_flags="-O0"
			f_opt1_flags="-O1"
			f_opt2_flags="-O3"

			cpp_compiler="${cpp_compiler} ${compiler_version_flags} ${compiler_flags}"
			c_compiler="${c_compiler} ${compiler_version_flags} ${compiler_flags}"
			f_compiler="${f_compiler} ${compiler_flags} -cpp -fno-second-underscore"

			if [ "${X11_libs}" != "" ] && [ "${X11_static_lib_flag}" = "yes" ]; then

				X11_libs="${X11_lib_dir}/libX11.a"
			fi

			cpp_compiler_debug="${cpp_compiler} ${define_flags} -c -Wextra -Wall -Wno-unused-parameter -Wno-unused-but-set-variable -Wconversion -Wno-sign-conversion -O0 -g ${include_flag}"
			cpp_compiler_opt0="${cpp_compiler} ${define_flags} -c ${c_opt0_flags} ${include_flag}"
			cpp_compiler_opt1="${cpp_compiler} ${define_flags} -c ${c_opt1_flags} ${include_flag}"
			cpp_compiler_opt2="${cpp_compiler} ${define_flags} -c ${c_opt2_flags} ${include_flag}"
			cpp_linker="${cpp_compiler} ${c_linker_flags}"
			cpp_linker_debug="${cpp_compiler} ${c_linker_flags} -Wextra -Wall -Wno-unused-parameter -Wno-unused-but-set-variable -Wconversion -Wno-sign-conversion -g"
			cpp_other_libs="-lm ${other_lib_flags}"

			c_compiler_debug="${c_compiler} ${define_flags} -c -Wextra -Wall -Wno-unused-parameter -Wno-unused-but-set-variable -Wconversion -Wno-sign-conversion -O0 -g ${include_flag}"
			c_compiler_opt0="${c_compiler} ${define_flags} -c ${c_opt0_flags} ${include_flag}"
			c_compiler_opt1="${c_compiler} ${define_flags} -c ${c_opt1_flags} ${include_flag}"
			c_compiler_opt2="${c_compiler} ${define_flags} -c ${c_opt2_flags} ${include_flag}"
			c_linker="${c_compiler} ${c_linker_flags}"
			c_linker_shared="${c_linker} -rpath ${sys_exe_dir}"
			c_linker_debug="${c_compiler} ${c_linker_flags} -Wextra -Wall -Wno-unused-parameter -Wno-unused-but-set-variable -Wconversion -Wno-sign-conversion -g"
			c_other_libs="-lm ${other_lib_flags}"

			f_compiler_debug="${f_compiler} ${define_flags} -c ${f_opt0_flags} -Wextra -Wall -Wno-unused-parameter -Wno-unused-but-set-variable -g"
			f_compiler_opt0="${f_compiler} ${define_flags} -c ${f_opt0_flags}"
			f_compiler_opt1="${f_compiler} ${define_flags} -c ${f_opt1_flags}"
			f_compiler_opt2="${f_compiler} ${define_flags} -c ${f_opt2_flags}"
			f_linker="${c_compiler} ${f_linker_flags}"
			f_linker_debug="${c_compiler} ${f_linker_flags} -Wextra -Wall -Wno-unused-parameter -Wno-unused-but-set-variable -g"
			f_other_libs="${other_lib_flags} ${f_arch_libs} ${arch_libs}"

			sanitize_options="-fsanitize=address -fno-optimize-sibling-calls -fno-omit-frame-pointer"
		;;

		*)
			echo "
*** WARNING Unknown System Type ***
"
			exit
		;;

	esac

# -----------------------------------------------------------
# Set all compiler flags to debug options if debug flag is on
# -----------------------------------------------------------

	if [ "${debug_flag}" != "" ]; then

		cpp_compiler_opt0="${cpp_compiler_debug}"
		cpp_compiler_opt1="${cpp_compiler_debug}"
		cpp_compiler_opt2="${cpp_compiler_debug}"
		cpp_linker="${cpp_linker_debug}"

		c_compiler_opt0="${c_compiler_debug}"
		c_compiler_opt1="${c_compiler_debug}"
		c_compiler_opt2="${c_compiler_debug}"
		c_linker="${c_linker_debug}"

		f_compiler_opt0="${f_compiler_debug}"
		f_compiler_opt1="${f_compiler_debug}"
		f_compiler_opt2="${f_compiler_debug}"
		f_linker="${f_linker_debug}"

		if [ "${sanitize_flag}" != "" ]; then

			cpp_compiler_opt0="${cpp_compiler_opt0} ${sanitize_options}"
			cpp_compiler_opt1="${cpp_compiler_opt1} ${sanitize_options}"
			cpp_compiler_opt2="${cpp_compiler_opt2} ${sanitize_options}"
			cpp_linker="${cpp_linker} ${sanitize_options}"

			c_compiler_opt0="${c_compiler_opt0} ${sanitize_options}"
			c_compiler_opt1="${c_compiler_opt1} ${sanitize_options}"
			c_compiler_opt2="${c_compiler_opt2} ${sanitize_options}"
			c_linker="${c_linker} ${sanitize_options}"

			f_compiler_opt0="${f_compiler_opt0} ${sanitize_options}"
			f_compiler_opt1="${f_compiler_opt1} ${sanitize_options}"
			f_compiler_opt2="${f_compiler_opt2} ${sanitize_options}"
			f_linker="${f_linker} ${sanitize_options}"
		fi
	fi
}
