Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apisupport #145

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# These also apply to all subdirectories.
*.o
apisupport-config.h
cpusupport-config.h
posix-flags.sh
# Test binaries and compiled files.
Expand Down
24 changes: 18 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,22 @@ TEST_CMD= tests/test_libcperciva.sh

### Shared code between Tarsnap projects.

all: cpusupport-config.h posix-flags.sh
all: apisupport-config.h cpusupport-config.h posix-flags.sh
export CFLAGS="$${CFLAGS:-${CFLAGS_DEFAULT}}"; \
. ./posix-flags.sh; \
. ./cpusupport-config.h; \
. ./apisupport-config.h; \
export HAVE_BUILD_FLAGS=1; \
for D in ${PROGS} ${TESTS}; do \
( cd $${D} && ${MAKE} all ) || exit 2; \
done

# For "loop-back" building of a subdirectory
buildsubdir: cpusupport-config.h posix-flags.sh
. ./cpusupport-config.h; \
. ./posix-flags.sh; \
export HAVE_BUILD_FLAGS=1; \
buildsubdir: apisupport-config.h cpusupport-config.h posix-flags.sh
. ./posix-flags.sh; \
. ./cpusupport-config.h; \
. ./apisupport-config.h; \
export HAVE_BUILD_FLAGS=1; \
cd ${BUILD_SUBDIR} && ${MAKE} ${BUILD_TARGET}

posix-flags.sh:
Expand All @@ -52,6 +54,16 @@ posix-flags.sh:
:; \
fi > $@

apisupport-config.h:
if [ -d ${LIBCPERCIVA_DIR}/apisupport/ ]; then \
export CC="${CC}"; \
command -p sh \
${LIBCPERCIVA_DIR}/apisupport/Build/apisupport.sh \
"$$PATH"; \
else \
:; \
fi > $@

cpusupport-config.h:
if [ -d ${LIBCPERCIVA_DIR}/cpusupport/ ]; then \
export CC="${CC}"; \
Expand All @@ -69,7 +81,7 @@ install: all
done

clean:
rm -f cpusupport-config.h posix-flags.sh
rm -f apisupport-config.h cpusupport-config.h posix-flags.sh
for D in ${PROGS} ${TESTS}; do \
( cd $${D} && ${MAKE} clean ) || exit 2; \
done
Expand Down
17 changes: 9 additions & 8 deletions Makefile.BSD
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ TESTS= tests/buildall \
tests/setuidgid \
tests/sha256 \
tests/valgrind
PUBLISH= ${PROGS} COPYRIGHT STYLE POSIX alg cpusupport crypto datastruct \
events network tests util
PUBLISH= ${PROGS} COPYRIGHT STYLE POSIX alg apisupport cpusupport \
datastruct events network tests util

### Shared code between Tarsnap projects.

# These definitions improve the readability of the below material.
MAKEBSD:= ${MAKE} -f Makefile.BSD
RELEASEDATE!= date "+%B %d, %Y"
CFLAGS_HARDCODED= -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\\\"cpusupport-config.h\\\"
CFLAGS_HARDCODED= -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -DCPUSUPPORT_CONFIG_FILE=\\\"cpusupport-config.h\\\" -DAPISUPPORT_CONFIG_FILE=\\\"apisupport-config.h\\\"

# This creates (and deletes) a fake cpusupport-config.h that is
# blank (and thus does not require any special CFLAGS to compile).
Expand All @@ -32,7 +32,7 @@ ${D}/Makefile::
echo '# AUTOGENERATED FILE, DO NOT EDIT' >> $@
( cd ${D} && printf 'PROG=' && ${MAKEBSD} -V PROG ) >> $@
( cd ${D} && printf 'MAN1=' && ${MAKEBSD} -V MAN1 ) >> $@
( cd ${D} && printf 'SRCS=' && ${MAKEBSD} -V SRCS | sed -e 's| cpusupport-config.h||' ) >> $@
( cd ${D} && printf 'SRCS=' && ${MAKEBSD} -V SRCS | sed -e 's| cpusupport-config.h||' | sed -e 's| apisupport-config.h||' ) >> $@
( cd ${D} && printf 'IDIRS=' && ${MAKEBSD} -V IDIRS ) >> $@
( cd ${D} && printf 'LDADD_REQ=' && ${MAKEBSD} -V LDADD_REQ ) >> $@
( cd ${D} && printf 'SUBDIR_DEPTH=' && ${MAKEBSD} -V SUBDIR_DEPTH ) >> $@
Expand All @@ -43,18 +43,19 @@ ${D}/Makefile::
else \
cat Makefile.prog >> $@ ; \
fi
rm -f cpusupport-config.h
touch cpusupport-config.h
rm -f apisupport-config.h cpusupport-config.h
touch apisupport-config.h cpusupport-config.h
( cd ${D} && ${MAKEBSD} -V SRCS | \
sed -e 's| cpusupport-config.h||' | \
sed -e 's| apisupport-config.h||' | \
tr ' ' '\n' | \
sed -E 's/.c$$/.o/' | \
while read F; do \
S=`${MAKEBSD} source-$${F}`; \
CF=`${MAKEBSD} cflags-$${F}`; \
IDIRS=`${MAKEBSD} -V IDIRS`; \
SUBDIR_DEPTH=`${MAKEBSD} -V SUBDIR_DEPTH`; \
echo `${CPP} $${S} -std=c99 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -I$${SUBDIR_DEPTH} $${IDIRS} -MM -MT $${F}` \
echo `${CPP} $${S} -std=c99 -DCPUSUPPORT_CONFIG_FILE=\"cpusupport-config.h\" -DAPISUPPORT_CONFIG_FILE=\"apisupport-config.h\" -I$${SUBDIR_DEPTH} $${IDIRS} -MM -MT $${F}` \
| sed -e 's| \\ | |g'; \
echo " \$${CC} \$${CFLAGS_POSIX} ${CFLAGS_HARDCODED} $${CF} -I$${SUBDIR_DEPTH} \$${IDIRS} \$${CPPFLAGS} \$${CFLAGS} -c $${S} -o $${F}"; \
done ) >> $@
Expand All @@ -81,7 +82,7 @@ ${D}/Makefile::
Makefile > Makefile.new ); \
( cd ${D} && mv Makefile.new Makefile ); \
fi
rm -f cpusupport-config.h
rm -f apisupport-config.h cpusupport-config.h
.endfor

Makefiles:
Expand Down
44 changes: 44 additions & 0 deletions apisupport/Build/apisupport.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Should be sourced by `command -p sh path/to/apisupport.sh "$PATH"` from
# within a Makefile.
if ! [ ${PATH} = "$1" ]; then
echo "WARNING: POSIX violation: $SHELL's command -p resets \$PATH" 1>&2
PATH=$1
fi
# Standard output should be written to apisupport-config.h, which is both a
# C header file defining APISUPPORT_ARCH_FEATURE macros and sourceable sh
# code which sets CFLAGS_ARCH_FEATURE environment variables.
SRCDIR=`command -p dirname "$0"`

feature() {
ARCH=$1
FEATURE=$2
shift 2;
if ! [ -f ${SRCDIR}/apisupport-$ARCH-$FEATURE.c ]; then
return
fi
printf "Checking if compiler supports $ARCH $FEATURE feature..." 1>&2
for CFLAG in "$@"; do
if ${CC} ${CFLAGS} -D_POSIX_C_SOURCE=200809L ${CFLAG} \
${SRCDIR}/apisupport-$ARCH-$FEATURE.c 2>/dev/null; then
rm -f a.out
break;
fi
CFLAG=NOTSUPPORTED;
done
case $CFLAG in
NOTSUPPORTED)
echo " no" 1>&2
;;
"")
echo " yes" 1>&2
echo "#define APISUPPORT_${ARCH}_${FEATURE} 1"
;;
*)
echo " yes, via $CFLAG" 1>&2
echo "#define APISUPPORT_${ARCH}_${FEATURE} 1"
echo "#ifdef apisupport_dummy"
echo "export CFLAGS_${ARCH}_${FEATURE}=\"${CFLAG}\""
echo "#endif"
;;
esac
}
106 changes: 106 additions & 0 deletions apisupport/apisupport.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#ifndef _APISUPPORT_H_
#define _APISUPPORT_H_

/*
* To enable support for non-portable API features at compile time, one or
* more APISUPPORT_ARCH_FEATURE macros should be defined. This can be done
* directly on the compiler command line via -D APISUPPORT_ARCH_FEATURE or
* -D APISUPPORT_ARCH_FEATURE=1; or a file can be created with the
* necessary #define lines and then -D APISUPPORT_CONFIG_FILE=apiconfig.h
* (or similar) can be provided to include that file here.
*/
#ifdef APISUPPORT_CONFIG_FILE
#include APISUPPORT_CONFIG_FILE
#endif

/**
* The APISUPPORT_FEATURE macro declares the necessary variables and
* functions for detecting API feature support at run time. The function
* defined in the macro acts to cache the result of the ..._detect function
* using the ..._present and ..._init variables. The _detect function and the
* _present and _init variables are turn defined by APISUPPORT_FEATURE_DECL in
* appropriate apisupport_foo_bar.c file.
*
* In order to allow APISUPPORT_FEATURE to be used for features which do not
* have corresponding APISUPPORT_FEATURE_DECL blocks in another source file,
* we abuse the C preprocessor: If APISUPPORT_${enabler} is defined to 1, then
* we access _present_1, _init_1, and _detect_1; but if it is not defined, we
* access _present_APISUPPORT_${enabler} etc., which we define as static, thus
* preventing the compiler from emitting a reference to an external symbol.
*
* In this way, it becomes possible to issue APISUPPORT_FEATURE invocations
* for nonexistent features without running afoul of the requirement that
* "If an identifier declared with external linkage is used... in the entire
* program there shall be exactly one external definition" (C99 standard, 6.9
* paragraph 5). In practice, this means that users of the apisupport code
* can omit build and runtime detection files without changing the framework
* code.
*/
#define APISUPPORT_FEATURE__(arch_feature, enabler, enabled) \
static int apisupport_ ## arch_feature ## _present ## _APISUPPORT_ ## enabler; \
static int apisupport_ ## arch_feature ## _init ## _APISUPPORT_ ## enabler; \
static inline int apisupport_ ## arch_feature ## _detect ## _APISUPPORT_ ## enabler(void) { return (0); } \
extern int apisupport_ ## arch_feature ## _present_ ## enabled; \
extern int apisupport_ ## arch_feature ## _init_ ## enabled; \
int apisupport_ ## arch_feature ## _detect_ ## enabled(void); \
\
static inline int \
apisupport_ ## arch_feature(void) \
{ \
\
if (apisupport_ ## arch_feature ## _present_ ## enabled) \
return (1); \
else if (apisupport_ ## arch_feature ## _init_ ## enabled) \
return (0); \
apisupport_ ## arch_feature ## _present_ ## enabled = \
apisupport_ ## arch_feature ## _detect_ ## enabled(); \
apisupport_ ## arch_feature ## _init_ ## enabled = 1; \
return (apisupport_ ## arch_feature ## _present_ ## enabled); \
} \
static void (* apisupport_ ## arch_feature ## _dummyptr)(void); \
static inline void \
apisupport_ ## arch_feature ## _dummyfunc(void) \
{ \
\
(void)apisupport_ ## arch_feature ## _present ## _APISUPPORT_ ## enabler; \
(void)apisupport_ ## arch_feature ## _init ## _APISUPPORT_ ## enabler; \
(void)apisupport_ ## arch_feature ## _detect ## _APISUPPORT_ ## enabler; \
(void)apisupport_ ## arch_feature ## _present_ ## enabled; \
(void)apisupport_ ## arch_feature ## _init_ ## enabled; \
(void)apisupport_ ## arch_feature ## _detect_ ## enabled; \
(void)apisupport_ ## arch_feature ## _dummyptr; \
} \
static void (* apisupport_ ## arch_feature ## _dummyptr)(void) = apisupport_ ## arch_feature ## _dummyfunc; \
struct apisupport_ ## arch_feature ## _dummy
#define APISUPPORT_FEATURE_(arch_feature, enabler, enabled) \
APISUPPORT_FEATURE__(arch_feature, enabler, enabled)
#define APISUPPORT_FEATURE(arch, feature, enabler) \
APISUPPORT_FEATURE_(arch ## _ ## feature, enabler, APISUPPORT_ ## enabler)

/*
* APISUPPORT_FEATURE_DECL(arch, feature):
* Macro which defines variables and provides a function declaration for
* detecting the presence of "feature" on the "arch" architecture. The
* function body following this macro expansion must return nonzero if the
* feature is present, or zero if the feature is not present or the detection
* fails for any reason.
*/
#define APISUPPORT_FEATURE_DECL(arch, feature) \
extern int apisupport_ ## arch ## _ ## feature ## _present_1; \
extern int apisupport_ ## arch ## _ ## feature ## _init_1; \
int apisupport_ ## arch ## _ ## feature ## _present_1 = 0; \
int apisupport_ ## arch ## _ ## feature ## _init_1 = 0; \
int apisupport_ ## arch ## _ ## feature ## _detect_1(void); \
int \
apisupport_ ## arch ## _ ## feature ## _detect_1(void)

/*
* List of features. If a feature here is not enabled by the appropriate
* APISUPPORT_ARCH_FEATURE macro being defined, it has no effect; but if the
* relevant macro may be defined (e.g., by Build/apisupport.sh successfully
* compiling Build/apisupport-ARCH-FEATURE.c) then the C file containing the
* corresponding run-time detection code (apisupport_arch_feature.c) must be
* compiled and linked in.
*/

#endif /* !_APISUPPORT_H_ */
Loading