/* Copyright 2003-2013, 2018, 2020-2022
Free Software Foundation, Inc.
This file is part of Guile.
Guile is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Guile 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 Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with Guile. If not, see
. */
/**********************************************************************
Description of Guile's public config header mechanics:
-----------------------------------------------------
Guile has three core headers:
config.h: Guile's private automatically generated configuration
header -- generated by configure.in and autoheader. *NOT*
installed during "make install" and so may not be referred to by
any public headers.
installed. It's only visible to the libguile sources
themselves, and it includes config.h, the private config header.
Among other things this file provides a place to make decisions
based on the information gathered in config.h.
libguile/scmconfig.h: Guile's public automatically generated
configuration header -- generated at build time by concatenating
the contents of libguile/scmconfig.h.top with the output from
libguile/gen-scmconfig. gen-scmconfig bases its output on the
information in the private config.h header, the contents of
gen-scmconfig.h (which is created by configure.in from
gen-scmconfig.h.in), and the information provided in this file,
gen-scmconfig.c.
libguile/scm.h: Guile's public core header. This file is
installed and publically visible. It includes
libguile/scmconfig.h, the public config header and provides a
place to make decisions based on the information gathered in
scmconfig.h to define things that other headers can depend on.
Notes and guidelines:
- use 1 and 0 for public #defines instead of "def and undef",
i.e. use #define SCM_HAVE_FOO rather than just not defining
SCM_HAVE_FOO whenever possible. See GNU Coding Guidelines for
rationale. The only notable non-deprecated exception to this rule
is GUILE_DEBUG which does not follow this convention in order to
retain backward compatibility.
- in the code below, be *VERY* careful not to use or rely on any
runtime-dynamic information below. For example, you cannot use
sizeof (FOO), but must use static information like SIZEOF_BAR
(from config.h) or SCM_SIZEOF_BAZ (from scmconfig.h). This is
because the gcc that is compiling gen-scmconfig.c and/or the
machine that is running gen-scmconfig may not be the same
compiler and/or hardware that will eventually be running Guile.
(i.e. keep the cross-compilation case in mind).
- try to avoid adding names to the public namespace when possible.
Note in the code below, that in a number of cases, we detect a
feature and based on that, we decide whether or not to print
anything at all. This decreases the extraneous #defines and
#ifdefery that we require in scmconfig.h
- try to avoid adding any duplicate definitions to config.h and
scmconfig.h. i.e. have just SCM_ENABLE_ELISP in scmconfig.h
rather than ENABLE_ELISP in config.h and SCM_ENABLE_ELISP in
scmconfig.h.
- in cases where you need to communicate information from
configure.in to gen-scmconfig.c, don't add an AC_DEFINE unless
you need it for other purposes. Just add a suitable SCM_I_GSC_*
variable to configure.in, set the value, AC_SUBST the value, and
add an appropriate line to gen-scmconfig.h.in. All gen-scmconfig
related AC_SUBST vars should be prefixed with SCM_I_GSC_.
- make sure that anything that we explicitly typedef publically is
prefixed with scm_t_. i.e. we used to typedef long to ptrdiff_t
if we didn't detect ptrdiff_t, but this has been changed so that
we typedef ptrdiff_t instead so that we won't conflict with
any non-guile header definitions of the same type. For types
like intptr_t and uintptr_t which we just try to detect and don't
actually define, it's fine not to have a corresponding scm_t_
type.
- we now use SCM_SIZEOF_FOO != 0 rather than SCM_HAVE_FOO for any
cases where the size might actually vary.
Rationales (not finished):
Why do we use a C program here rather than AC_OUTPUT_COMMANDS?
--------------------------------------------------------------
The main reason is that there are some values we would need
access to at AC_OUTPUT_COMMANDs that are determined by configure
but are not available at AC_OUTPUT time. The values are *only*
available via config.h. We use gen-scmconfig so we can see those
values and make decisions based on their settings.
Why have gen-scmconfig.h.in?
----------------------------
Without that header, we could end up needing multiple aliases for
public settings like SCM_ENABLE_ELISP. We can't define
SCM_ENABLE_ELISP in config.h since that header is private and any
definition in scmconfig.h would conflict (#ifndef might be
possible but runs the risk of conflicting directives), so a
likely solution would be to AC_DEFINE([SCM_I_ENABLE_ELISP]), and
then use SCM_I_ENABLE_ELISP in gen-scmconfig via config.h to
determine whether or not to #define SCM_ENABLE_ELISP, but this
leaves us with two #defined symbols for each public setting --
better to just have one value (public or private) that all code
uses.
Having this header means we can AC_SUBST a value like
SCM_I_GSC_ENABLE_ELISP and then set it in here via AC_OUTPUT
substitutions, and gen-scmconfig can use that definition to
determine whether or not to #define SCM_ENABLE_ELISP when
generating scmconfig.h, and we end up with nothing extraneous
added to config.h.
**********************************************************************/
#ifdef HAVE_CONFIG_H
# include
#endif
#include
#include
#include
#include
#include "gen-scmconfig.h"
#define pf printf
int
main (int argc, char *argv[])
{
pf ("/* This file is automatically generated --"
" see configure.in for details */\n"
"\n"
"#ifndef SCM_SCMCONFIG_H\n"
"#define SCM_SCMCONFIG_H\n");
/*** various important headers ***/
pf ("\n");
pf ("/* Important headers */\n");
pf ("#include \n");
pf ("#include \n");
pf ("#include \n");
#if HAVE_SYS_TIME_H
pf ("#include \n");
#else
pf ("/* sys/time.h not available */\n");
#endif
pf ("#include \n");
pf("\n");
pf ("#include \n");
# ifdef HAVE_SYS_TYPES_H
pf ("#include \n");
# endif
# ifdef HAVE_SYS_STDTYPES_H
pf ("#include \n");
# endif
pf ("#include \n");
pf("\n");
#ifdef HAVE_SYS_SELECT_H
pf ("#define SCM_HAVE_SYS_SELECT_H 1 /* 0 or 1 */\n");
#else
pf ("#define SCM_HAVE_SYS_SELECT_H 0 /* 0 or 1 */\n");
#endif
#ifdef HAVE_WINSOCK2_H
pf ("#define SCM_HAVE_WINSOCK2_H 1 /* 0 or 1 */\n");
#else
pf ("#define SCM_HAVE_WINSOCK2_H 0 /* 0 or 1 */\n");
#endif
/*** GUILE_DEBUG (defined or undefined) ***/
pf ("\n");
pf ("/* Define to include various undocumented debugging functions. */\n");
if (SCM_I_GSC_GUILE_DEBUG)
pf ("#define GUILE_DEBUG 1 /* defined or undefined */\n");
else
pf ("/* #undef GUILE_DEBUG */\n");
/*** SCM_ENABLE_DEPRECATED (0 or 1) ***/
pf ("\n");
pf ("/* Set to 1 if you want to enable deprecated features. */\n");
pf ("/* (value will be 0 or 1). */\n");
pf ("#define SCM_ENABLE_DEPRECATED %d\n", SCM_I_GSC_ENABLE_DEPRECATED);
/*** SCM_STACK_GROWS_UP (0 or 1) ***/
pf ("\n");
pf ("/* Set to 1 if the stack grows up, 0 otherwise. */\n");
pf ("#define SCM_STACK_GROWS_UP %d /* 0 or 1 */\n",
SCM_I_GSC_STACK_GROWS_UP);
/*** SCM_C_INLINE (defined to appropriate string or undefined) ***/
pf ("\n");
pf ("/* C compiler's syntax for inline functions if any,\n"
" otherwise undefined. */\n");
if (SCM_I_GSC_C_INLINE)
pf ("#define SCM_C_INLINE %s\n", SCM_I_GSC_C_INLINE);
else
pf ("/* #undef SCM_C_INLINE */\n");
pf ("\n");
pf ("/* Standard types. */\n");
pf ("#define SCM_SIZEOF_CHAR %d\n", SIZEOF_CHAR);
pf ("#define SCM_SIZEOF_UNSIGNED_CHAR %d\n", SIZEOF_UNSIGNED_CHAR);
pf ("#define SCM_SIZEOF_SHORT %d\n", SIZEOF_SHORT);
pf ("#define SCM_SIZEOF_UNSIGNED_SHORT %d\n", SIZEOF_UNSIGNED_SHORT);
pf ("#define SCM_SIZEOF_LONG %d\n", SIZEOF_LONG);
pf ("#define SCM_SIZEOF_UNSIGNED_LONG %d\n", SIZEOF_UNSIGNED_LONG);
pf ("#define SCM_SIZEOF_INT %d\n", SIZEOF_INT);
pf ("#define SCM_SIZEOF_UNSIGNED_INT %d\n", SIZEOF_UNSIGNED_INT);
pf ("#define SCM_SIZEOF_SIZE_T %d\n", SIZEOF_SIZE_T);
pf ("#define SCM_SIZEOF_LONG_LONG %d\n", SIZEOF_LONG_LONG);
pf ("#define SCM_SIZEOF_UNSIGNED_LONG_LONG %d\n", SIZEOF_UNSIGNED_LONG_LONG);
pf ("#define SCM_SIZEOF_INTMAX %d\n", SIZEOF_INTMAX_T);
pf ("#define SCM_SIZEOF_SCM_T_PTRDIFF %d\n", SIZEOF_PTRDIFF_T);
pf ("#define SCM_SIZEOF_INTPTR_T %d\n", SIZEOF_INTPTR_T);
pf ("#define SCM_SIZEOF_UINTPTR_T %d\n", SIZEOF_UINTPTR_T);
pf ("\n");
pf ("/* same as POSIX \"struct timespec\" -- always defined */\n");
#ifdef HAVE_SYSTEM_STRUCT_TIMESPEC
pf ("typedef struct timespec scm_t_timespec;\n");
#else
pf ("/* POSIX.4 structure for a time value. This is like a `struct timeval'"
" but has nanoseconds instead of microseconds. */\n");
pf ("typedef struct\n"
"{\n"
" long int tv_sec; /* Seconds. */\n"
" long int tv_nsec; /* Nanoseconds. */\n"
"} scm_t_timespec;\n");
#endif
pf ("\n");
pf ("/*** Threading model (scmconfig.h support not finished) ***/\n");
pf ("/* Define to 1 if using pthread multithreading. */\n");
pf ("#define SCM_USE_PTHREAD_THREADS %d /* 0 or 1 */\n",
SCM_I_GSC_USE_PTHREAD_THREADS);
pf ("/* Define to 1 if using one-thread 'multi'threading. */\n");
pf ("#define SCM_USE_NULL_THREADS %d /* 0 or 1 */\n",
SCM_I_GSC_USE_NULL_THREADS);
pf ("/* Define to 1 if need braces around PTHREAD_ONCE_INIT (for Solaris). */\n");
pf ("#define SCM_NEED_BRACES_ON_PTHREAD_ONCE_INIT %d /* 0 or 1 */\n",
SCM_I_GSC_NEED_BRACES_ON_PTHREAD_ONCE_INIT);
pf ("/* Define to 1 if need braces around PTHREAD_MUTEX_INITIALIZER\n"
" (for IRIX with GCC) */\n");
pf ("#define SCM_NEED_BRACES_ON_PTHREAD_MUTEX_INITIALIZER %d /* 0 or 1 */\n",
SCM_I_GSC_NEED_BRACES_ON_PTHREAD_MUTEX_INITIALIZER);
#ifdef HAVE_PTHREAD_SIGMASK
pf ("#define SCM_HAVE_PTHREAD_SIGMASK 1 /* 0 or 1 */\n");
#else
pf ("#define SCM_HAVE_PTHREAD_SIGMASK 0 /* 0 or 1 */\n");
#endif
#ifdef HAVE_GC_PTHREAD_CANCEL
pf ("#define SCM_HAVE_GC_PTHREAD_CANCEL 1 /* 0 or 1 */\n");
#else
pf ("#define SCM_HAVE_GC_PTHREAD_CANCEL 0 /* 0 or 1 */\n");
#endif
#ifdef HAVE_GC_PTHREAD_EXIT
pf ("#define SCM_HAVE_GC_PTHREAD_EXIT 1 /* 0 or 1 */\n");
#else
pf ("#define SCM_HAVE_GC_PTHREAD_EXIT 0 /* 0 or 1 */\n");
#endif
#ifdef HAVE_GC_PTHREAD_SIGMASK
pf ("#define SCM_HAVE_GC_PTHREAD_SIGMASK 1 /* 0 or 1 */\n");
#else
pf ("#define SCM_HAVE_GC_PTHREAD_SIGMASK 0 /* 0 or 1 */\n");
#endif
pf ("\n\n/*** File system access ***/\n");
pf ("/* Define to 1 if `struct dirent64' is available. */\n");
pf ("#define SCM_HAVE_STRUCT_DIRENT64 %d /* 0 or 1 */\n",
SCM_I_GSC_HAVE_STRUCT_DIRENT64);
pf ("/* Define to 1 if `readdir64_r ()' is available. */\n");
#ifdef HAVE_READDIR64_R
pf ("#define SCM_HAVE_READDIR64_R 1 /* 0 or 1 */\n");
#else
pf ("#define SCM_HAVE_READDIR64_R 0 /* 0 or 1 */\n");
#endif
/* Arrange so that we have a file offset type that reflects the one
used when compiling Guile, regardless of what the application's
`_FILE_OFFSET_BITS' says. See
http://lists.gnu.org/archive/html/bug-guile/2009-06/msg00018.html
for the original bug report.
Note that we can't define `scm_t_off' in terms of `off_t' or
`off64_t' because they may or may not be available depending on
how the application that uses Guile is compiled. */
#if defined GUILE_USE_64_CALLS && defined HAVE_STAT64
pf ("typedef int64_t scm_t_off;\n");
pf ("#define SCM_T_OFF_MAX INT64_MAX\n");
pf ("#define SCM_T_OFF_MIN INT64_MIN\n");
#elif SIZEOF_OFF_T == SIZEOF_INT
pf ("typedef int scm_t_off;\n");
pf ("#define SCM_T_OFF_MAX INT_MAX\n");
pf ("#define SCM_T_OFF_MIN INT_MIN\n");
#else
pf ("typedef long int scm_t_off;\n");
pf ("#define SCM_T_OFF_MAX LONG_MAX\n");
pf ("#define SCM_T_OFF_MIN LONG_MIN\n");
#endif
pf ("/* Define to 1 if the compiler supports the "
"`__thread' storage class. */\n");
if (SCM_I_GSC_HAVE_THREAD_STORAGE_CLASS)
pf ("#define SCM_HAVE_THREAD_STORAGE_CLASS\n");
else
pf ("/* #undef SCM_HAVE_THREAD_STORAGE_CLASS */\n");
#ifdef USE_DLL_IMPORT
pf ("\n");
pf ("/* Define some additional CPP macros on Win32 platforms. */\n");
pf ("# define __REGEX_IMPORT__ 1\n");
pf ("# define __CRYPT_IMPORT__ 1\n");
pf ("# define __READLINE_IMPORT__ 1\n");
pf ("# define QT_IMPORT 1\n");
#endif
pf ("\n");
pf ("/* Constants from uniconv.h. */\n");
pf ("#define SCM_ICONVEH_ERROR %d\n", SCM_I_GSC_ICONVEH_ERROR);
pf ("#define SCM_ICONVEH_QUESTION_MARK %d\n",
SCM_I_GSC_ICONVEH_QUESTION_MARK);
pf ("#define SCM_ICONVEH_ESCAPE_SEQUENCE %d\n",
SCM_I_GSC_ICONVEH_ESCAPE_SEQUENCE);
pf ("\n");
pf ("/* Define to 1 if there is an auxiliary stack, as in ia64. */\n");
pf ("#define SCM_HAVE_AUXILIARY_STACK %d\n", SCM_I_GSC_HAVE_AUXILIARY_STACK);
pf ("\n");
pf ("/* Define to 1 to use mini GMP. */\n");
#if SCM_I_GSC_ENABLE_MINI_GMP == 1
pf ("#define SCM_ENABLE_MINI_GMP 1\n");
#else
pf ("#define SCM_ENABLE_MINI_GMP 0\n");
#endif
printf ("#endif\n");
return 0;
}