# wm_library_constructors.m4 - Macros to see if compiler supports attributes "constructors" for libraries
#
# Copyright (c) 2021 Christophe CURIS
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, see <https://www.gnu.org/licenses/>.



# WM_LIBRARY_CONSTRUCTORS
# -----------------------
#
# GCC introduced the attribute 'constructor' which says that a function must be
# called when a library is loaded (needed for C++ support). However this may not
# be totally portable, so we may use the old method "_init" as a fall-back
# solution, which is considered Obsolete/Dangerous.
#
# This is explained here:
#   https://tldp.org/HOWTO/Program-Library-HOWTO/miscellaneous.html#INIT-AND-CLEANUP
#
# This macro is making sure that the compiler supports the attribute, because we
# need it for the WRaster library (see RStartup in wrlib/misc.c to see why).
AC_DEFUN_ONCE([WM_LIBRARY_CONSTRUCTORS],
[AC_CACHE_CHECK([how to declare a library constructor], [wm_cv_library_constructors],
    [save_CFLAGS="$CFLAGS"
     dnl We need this to cause a detectable failure in case of unsupported attribute name
     dnl if we don't do this, we just get a warning and AC_COMPILE suppose it was ok.
     CFLAGS="$CFLAGS -Werror"
     AC_COMPILE_IFELSE(
        [AC_LANG_SOURCE([[
static int is_initialised = 0;

void __attribute__ ((constructor)) special_function(void)
{
	is_initialised = 1;
}

int main(int argc, char **argv)
{
	/* To avoid warning on unused parameters, they could cause a false failure */
	(void) argc;
	(void) argv;
	return (is_initialised)?0:1;
}
]]) ],
        [wm_cv_library_constructors=attribute],
        [wm_cv_library_constructors=legacy])
     CFLAGS="$save_CFLAGS"])
 dnl In a perfect world we should also make sure that the feature works, but that implies
 dnl to be able to actually build and run a program, which is not compatible with a
 dnl cross-compiling user setup
 AS_IF([test "X$wm_cv_library_constructors" = "Xattribute"],
    [AC_DEFINE([WLIB_CONSTRUCTOR(func_name)], [__attribute__ ((constructor)) func_name],
        [Method for defining a library initialisation function])],
    [AC_DEFINE([WLIB_CONSTRUCTOR(func_name)], [_init],
        [Method for defining a library initialisation function])] )
])
