Make sure both C and C++ programs including gphoto2 headers compile

Check that programs including libgphoto2 headers compile
when compiled for a number of different language standards:

    C:   ansi c99 c11
    C++: ansi c++98 c++11 c++14 c++17

For each of these language standards, if the compiler does not
compile an empty example program, we do not test whether compiling
with the gphoto2/*.h headers included works.

This will work with GCC as the compiler, and also should work with
CLANG as the compiler as CLANG is mostly compatible in these matters.

On other compilers, the test compile of the empty program should
fail, and thus no checks with the gphoto2/*.h headers included will
be performed.

C90/ANSI C apparently does not define __STDC_VERSION__, so the
C source code needed to be changed to become ANSI C compatible.

In C++ pedantic compilation source, we now use actual C++ code
instead of relying on C code working when compiled as C++ code.

In Travis CI, we now actually require both C and C++.
This commit is contained in:
Hans Ulrich Niedermann
2020-02-18 21:18:55 +01:00
parent b56a50827f
commit 6f65d24796
5 changed files with 253 additions and 6 deletions

View File

@@ -83,6 +83,33 @@ dnl SED is supposed to be set in AC_LIBTOOL_SETUP, but the
dnl sequence seems to get mixed up.
SED=${SED-sed}
dnl If CXX is neither unset nor empty nor "no", presume we can compile
dnl C++ sources. A C++ compiler is not required for libgphoto2 itself,
dnl but is useful to make sure that the libgphoto2 header files
dnl compile when included into C++ source files.
AM_CONDITIONAL([HAVE_CXX], [test "x$CXX" != "x" && test "x$CXX" != "xno"])
dnl --------------------------------------------------------------------
dnl Determine the most pedantic compiler flags we can can find for both
dnl C and C++, so that we can test that the libgphoto2 headers compile
dnl with those flags.
dnl --------------------------------------------------------------------
GP_PEDANTIC_COMPILER_FLAGS([C90], [C], [-std=c90])
GP_PEDANTIC_COMPILER_FLAGS([C99], [C], [-std=c99])
GP_PEDANTIC_COMPILER_FLAGS([C11], [C], [-std=c11])
dnl
GP_PEDANTIC_COMPILER_FLAGS([CXX98], [C++], [-std=c++98])
GP_PEDANTIC_COMPILER_FLAGS([CXX11], [C++], [-std=c++11])
GP_PEDANTIC_COMPILER_FLAGS([CXX14], [C++], [-std=c++14])
GP_PEDANTIC_COMPILER_FLAGS([CXX17], [C++], [-std=c++17])
dnl Every compile example after here will be using the C language
AC_LANG([C])
dnl ---------------------------------------------------------------------------
dnl Turn on (almost) all warnings when using gcc
dnl ---------------------------------------------------------------------------
@@ -631,10 +658,6 @@ CPPFLAGS="$CPPFLAGS_save"
],[],[default-on],[http://www.sourceforge.net/projects/libexif])dnl
dnl FIXME: Is this accurate?
AM_CONDITIONAL([HAVE_CXX], [test -n "$CXX" && test "X$CXX" != "Xno"])
dnl ---------------------------------------------------------------------------
dnl Configure subprojects
dnl ---------------------------------------------------------------------------

View File

@@ -0,0 +1,123 @@
dnl ####################################################################
dnl GP_PEDANTIC_COMPILER_FLAGS & Co.
dnl ####################################################################
dnl
m4_pattern_forbid([_GP_])dnl
dnl
dnl
dnl ####################################################################
dnl _GP_CONDITIONAL_COMPILE_FLAGS(FLAG_VAR, FLAGS)
dnl ####################################################################
AC_DEFUN([_GP_CONDITIONAL_COMPILE_FLAGS], [dnl
# BEGIN $0($@)
AS_VAR_IF([$1], [], [dnl
$1="$2"
], [dnl
$1="[$]{$1} $2"
])
AC_MSG_CHECKING([whether $1="[$]$1" compiles])
AC_COMPILE_IFELSE([m4_case([$1], [CFLAGS], [dnl
AC_LANG_SOURCE([[
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
/* Use argc and argv to prevent warning about unused function params */
for (i=0; i<argc; ++i) {
printf(" %d %s\n", i, argv[i]);
}
return 0;
}
]])dnl
], [CXXFLAGS], [dnl
AC_LANG_SOURCE([[
#include <iostream>
int main(int argc, char *argv[])
{
int i;
/* Use argc and argv to prevent warning about unused function params */
for (i=0; i<argc; ++i) {
std::cout << " " << i << " " << argv[i] << std::endl;
}
return 0;
}
]])dnl
], [m4_fatal([wrong compiler flag])])], [dnl
: "Added flag $2 to $1 and it works"
AC_MSG_RESULT([yes])
], [dnl
: "Added flag $2 to $1 and it does not work"
AC_MSG_RESULT([no])
gp_have_pedantic_compiler=no
])
# END $0($@)
])dnl
dnl
dnl
dnl ####################################################################
dnl Params:
dnl $1 Depending on the language, CFLAGS or CXXFLAGS
dnl $2 The flag variable the caller wants us to set
dnl $3 The AM_CONDITIONAL the caller wants us to set
dnl $4 The -std= argument (such as -std=c++98 or -std=c99)
dnl ####################################################################
AC_DEFUN([__GP_PEDANTIC_COMPILER_FLAGS], [dnl
# BEGIN $0($@)
gp_have_pedantic_compiler=yes
_GP_CONDITIONAL_COMPILE_FLAGS([$1], [$4])dnl
AS_VAR_IF([gp_have_pedantic_compiler], [yes], [dnl
_GP_CONDITIONAL_COMPILE_FLAGS([$1], [-pedantic -Wall -Wextra -Werror])dnl
])
AM_CONDITIONAL([$3], [test "x$gp_have_pedantic_compiler" = "xyes"])
AC_SUBST([$2], ["[$]$1"])
AC_MSG_CHECKING([whether to test pedantic ][$4])
AM_COND_IF([$3], [dnl
AC_MSG_RESULT([yes])
], [dnl
AC_MSG_RESULT([no])
])
# END $0($@)
])dnl
dnl
dnl
dnl ####################################################################
dnl Params:
dnl $1 Depending on the language, CFLAGS or CXXFLAGS
dnl $2 The variable/conditional component the caller wants us to use
dnl $3 The -std= argument (such as -std=c++98 or -std=c99)
dnl ####################################################################
m4_pattern_allow([GP_PEDANTIC_CFLAGS_])dnl
m4_pattern_allow([GP_PEDANTIC_CXXFLAGS_])dnl
m4_pattern_allow([GP_HAVE_PEDANTIC_FLAGS_])dnl
AC_DEFUN([_GP_PEDANTIC_COMPILER_FLAGS], [dnl
# BEGIN $0($@)
gp_compiler_flags_saved_$1="[$]$1"
$1=""
__GP_PEDANTIC_COMPILER_FLAGS([$1],
[GP_PEDANTIC_][$1][_][$2],
[GP_HAVE_PEDANTIC_FLAGS_][$2],
[$3])
GP_PEDANTIC_$1_$2="[$]$1"
$1="[$]gp_compiler_flags_saved_$1"
# END $0($@)
])dnl
dnl
dnl
dnl ####################################################################
dnl GP_PEDANTIC_COMPILER_FLAGS(VAR_COMPONENT, LANG, std-arg)
dnl Start a new series of compiler flags
dnl ####################################################################
AC_DEFUN([GP_PEDANTIC_COMPILER_FLAGS], [dnl
# BEGIN $0($@)
AC_LANG_PUSH([$2])
_GP_PEDANTIC_COMPILER_FLAGS(m4_case($2,[C],[CFLAGS],[C++],[CXXFLAGS],[m4_fatal([Unknown language given: ][$2])]), [$1], [$3])
AC_LANG_POP([$2])
# END $0($@)
])dnl
dnl
dnl
dnl ####################################################################
dnl
dnl Local Variables:
dnl mode: autoconf
dnl End:

View File

@@ -143,6 +143,101 @@ test_pedantic_cxx_LDADD = \
$(INTLLIBS)
########################################################################
# Test pendantic compilation for multiple language standard
########################################################################
generic_pedantic_cppflags =
generic_pedantic_cppflags += -I$(top_srcdir)/libgphoto2_port
generic_pedantic_cppflags += -I$(top_srcdir)
if GP_HAVE_PEDANTIC_FLAGS_C90
TESTS += test-pedantic-c90
check_PROGRAMS += test-pedantic-c90
test_pedantic_c90_SOURCES = test-pedantic-compilation.c
test_pedantic_c90_CPPFLAGS = $(generic_pedantic_cppflags)
test_pedantic_c90_CFLAGS = $(GP_PEDANTIC_CFLAGS_C90)
test_pedantic_c90_LDADD =
test_pedantic_c90_LDFLAGS =
endif
if GP_HAVE_PEDANTIC_FLAGS_C99
TESTS += test-pedantic-c99
check_PROGRAMS += test-pedantic-c99
test_pedantic_c99_SOURCES = test-pedantic-compilation.c
test_pedantic_c99_CPPFLAGS = $(generic_pedantic_cppflags)
test_pedantic_c99_CFLAGS = $(GP_PEDANTIC_CFLAGS_C99)
test_pedantic_c99_LDADD =
test_pedantic_c99_LDFLAGS =
endif
if GP_HAVE_PEDANTIC_FLAGS_C11
TESTS += test-pedantic-c11
check_PROGRAMS += test-pedantic-c11
test_pedantic_c11_SOURCES = test-pedantic-compilation.c
test_pedantic_c11_CPPFLAGS = $(generic_pedantic_cppflags)
test_pedantic_c11_CFLAGS = $(GP_PEDANTIC_CFLAGS_C11)
test_pedantic_c11_LDADD =
test_pedantic_c11_LDFLAGS =
endif
if GP_HAVE_PEDANTIC_FLAGS_CXX98
if HAVE_CXX
TESTS += test-pedantic-cxx98
check_PROGRAMS += test-pedantic-cxx98
else
EXTRA_PROGRAMS += test-pedantic-cxx98
endif
test_pedantic_cxx98_SOURCES = test-pedantic-compilation.cxx
test_pedantic_cxx98_CPPFLAGS = $(generic_pedantic_cppflags)
test_pedantic_cxx98_CXXFLAGS = $(GP_PEDANTIC_CXXFLAGS_CXX98)
test_pedantic_cxx98_LDADD =
test_pedantic_cxx98_LDFLAGS =
endif
if GP_HAVE_PEDANTIC_FLAGS_CXX11
if HAVE_CXX
TESTS += test-pedantic-cxx11
check_PROGRAMS += test-pedantic-cxx11
else
EXTRA_PROGRAMS += test-pedantic-cxx11
endif
test_pedantic_cxx11_SOURCES = test-pedantic-compilation.cxx
test_pedantic_cxx11_CPPFLAGS = $(generic_pedantic_cppflags)
test_pedantic_cxx11_CXXFLAGS = $(GP_PEDANTIC_CXXFLAGS_CXX11)
test_pedantic_cxx11_LDADD =
test_pedantic_cxx11_LDFLAGS =
endif
if GP_HAVE_PEDANTIC_FLAGS_CXX14
if HAVE_CXX
TESTS += test-pedantic-cxx14
check_PROGRAMS += test-pedantic-cxx14
else
EXTRA_PROGRAMS += test-pedantic-cxx14
endif
test_pedantic_cxx14_SOURCES = test-pedantic-compilation.cxx
test_pedantic_cxx14_CPPFLAGS = $(generic_pedantic_cppflags)
test_pedantic_cxx14_CXXFLAGS = $(GP_PEDANTIC_CXXFLAGS_CXX14)
test_pedantic_cxx14_LDADD =
test_pedantic_cxx14_LDFLAGS =
endif
if GP_HAVE_PEDANTIC_FLAGS_CXX17
if HAVE_CXX
TESTS += test-pedantic-cxx17
check_PROGRAMS += test-pedantic-cxx17
else
EXTRA_PROGRAMS += test-pedantic-cxx17
endif
test_pedantic_cxx17_SOURCES = test-pedantic-compilation.cxx
test_pedantic_cxx17_CPPFLAGS = $(generic_pedantic_cppflags)
test_pedantic_cxx17_CXXFLAGS = $(GP_PEDANTIC_CXXFLAGS_CXX17)
test_pedantic_cxx17_LDADD =
test_pedantic_cxx17_LDFLAGS =
endif
########################################################################
# Implement the checks for the installed library
########################################################################

View File

@@ -17,10 +17,16 @@
#include <stdio.h>
#ifdef __STDC_VERSION__
unsigned long stdc_version = __STDC_VERSION__;
#endif
int main()
{
#ifdef __STDC_VERSION__
printf("stdc_version = %lu\n", stdc_version);
#else
printf("stdc_version = undefined\n");
#endif
return 0;
}

View File

@@ -15,12 +15,12 @@
#include <gphoto2/gphoto2-port-result.h>
#include <gphoto2/gphoto2-port-version.h>
#include <stdio.h>
#include <iostream>
unsigned long cxx_version = __cplusplus;
int main()
{
printf("cxx_version = %lu\n", cxx_version);
std::cout << "cxx_version = " << cxx_version << std::endl;
return 0;
}