diff --git a/.gitignore b/.gitignore index 869d7e07d09d..7186c9d41758 100644 --- a/.gitignore +++ b/.gitignore @@ -235,6 +235,7 @@ META /parsing/camlinternalMenhirLib.ml /parsing/camlinternalMenhirLib.mli +/runtime/api-testing /runtime/domain_state.inc /runtime/caml/m.h /runtime/caml/s.h diff --git a/Makefile b/Makefile index 5a6987e6a2b9..bc697c0cb9e5 100644 --- a/Makefile +++ b/Makefile @@ -1364,6 +1364,80 @@ runtime-all: \ $(runtime_BYTECODE_SHARED_LIBRARIES:%=runtime/lib%_shared$(EXT_DLL)) \ $(runtime_PROGRAMS:%=runtime/%$(EXE)) $(SAK) +# If the compiler is configured with --enable-warn-error (which is the default +# for development builds), then all the installed header files are tested with +# more warnings enabled. The test also ensures that each header can be included +# without any other headers. +ifneq "$(EXTRA_WARNINGS_CFLAGS)" "" +runtime-all: runtime-header-tests +endif + +# As with the runtime-header-tests, if a C++ compiler is available, then we also +# verify that the headers can be included in a C++ program without error. +ifneq "$(EXTRA_WARNINGS_CXXFLAGS)" "" +ifneq "$(TEST_CXX)" "" +runtime-all: runtime-header-cxx-tests +endif +endif + +# Unlike in COMPILE_C_FILE, this is just a convenience test, so we don't do any +# effort with the dependency computations worrying about DEP_CC and so forth, +# because most _development_ is done with feature-rich C compilers! +API_TESTING_DEP_FILES := $(wildcard runtime/api-testing/*.$(D)) +.PHONY: $(API_TESTING_DEP_FILES) +include $(API_TESTING_DEP_FILES) + +ALL_PUBLIC_HEADER_FILES := $(notdir $(sort $(wildcard \ + $(addsuffix /caml/*.h, $(addprefix otherlibs/, $(OTHERLIBS))) \ + runtime/caml/*.h \ + $(filter runtime/caml/%, $(runtime_BUILT_HEADERS))))) + +runtime-header-tests: \ + $(addprefix runtime/api-testing/,$(ALL_PUBLIC_HEADER_FILES:.h=.t)) + +runtime-header-cxx-tests: \ + $(addprefix runtime/api-testing/,$(ALL_PUBLIC_HEADER_FILES:.h=.tpp)) + +.PRECIOUS: runtime/api-testing +runtime/api-testing: + $(MKDIR) $@ + +runtime/api-testing/%.t: runtime/api-testing/%.c.$(O) + @touch $@ + +runtime/api-testing/%.tpp: runtime/api-testing/%.cpp.$(O) + @touch $@ + +runtime/api-testing/%.c.$(O): runtime/api-testing/%.c + $(V_CC)$(CC) \ + $(OC_CFLAGS) $(EXTRA_WARNINGS_CFLAGS) $(CFLAGS) \ + $(OC_CPPFLAGS) \ + $(call DEP_FLAGS,$@,$(@:.$(O)=.$(D))) \ + $(addprefix -I otherlibs/, $(OTHERLIBS)) $(CPPFLAGS) \ + $(OUTPUTOBJ)$@ -c $< + +runtime/api-testing/%.c: | runtime/api-testing + $(V_GEN){ \ + echo '#include '; \ + echo '#include '; \ + echo 'int answer = 42;'; \ + } > $@ + +runtime/api-testing/%.cpp.$(O): runtime/api-testing/%.cpp + $(V_CXX)$(TEST_CXX) \ + $(TEST_CXX_CXXFLAGS) $(EXTRA_WARNINGS_CXXFLAGS) $(CXXFLAGS) \ + $(TEST_CXX_CPPFLAGS) \ + $(call DEP_FLAGS,$@,$(@:.$(O)=.$(D))) \ + -I runtime $(addprefix -I otherlibs/, $(OTHERLIBS)) $(CPPFLAGS) \ + $(OUTPUTOBJ)$@ -c $< + +runtime/api-testing/%.cpp: | runtime/api-testing + $(V_GEN){ \ + echo '#include '; \ + echo '#include '; \ + echo 'int answer = 42;'; \ + } > $@ + .PHONY: runtime-allopt ifeq "$(NATIVE_COMPILER)" "true" runtime-allopt: \ @@ -2709,6 +2783,7 @@ endif otherlibs/dynlink/dynlink_platform_intf.mli $(MAKE) -C otherlibs distclean rm -f $(runtime_CONFIGURED_HEADERS) runtime/ld.conf + rm -rf runtime/api-testing $(MAKE) -C stdlib distclean $(MAKE) -C testsuite distclean rm -f tools/eventlog_metadata tools/*.bak diff --git a/Makefile.build_config.in b/Makefile.build_config.in index 6d3f6803163b..e2fb0309e076 100644 --- a/Makefile.build_config.in +++ b/Makefile.build_config.in @@ -81,6 +81,11 @@ DEP_FLAGS = endif COMPUTE_DEPS=@compute_deps@ +TEST_CXX = @ocamltest_CXX@ +TEST_CXX_CXXFLAGS = @common_cflags@ +TEST_CXX_CPPFLAGS = @common_cppflags@ +CXXFLAGS ?= + BUILD_PATH_LOGICAL = @srcdir_abs@ BUILD_PATH_PHYSICAL = @srcdir_abs_real@ BUILD_MAP_FLAGS = @build_map_flags@ @@ -107,6 +112,9 @@ OC_BYTECODE_CPPFLAGS = $(OC_INCLUDES) @oc_bytecode_cppflags@ OC_NATIVE_CPPFLAGS = $(OC_INCLUDES) @oc_native_cppflags@ +EXTRA_WARNINGS_CFLAGS = @cc_extra_warnings@ +EXTRA_WARNINGS_CXXFLAGS = @cxx_extra_warnings@ + # Additional link-time options # To support dynamic loading of shared libraries (they need to look at # our own symbols): diff --git a/Makefile.common b/Makefile.common index 23d22e015acb..a66fbcbda22e 100644 --- a/Makefile.common +++ b/Makefile.common @@ -46,6 +46,7 @@ V ?= 0 ifeq "$(V)" "0" V_CC = @$(info $ CC $@) +V_CXX = @$(info $ CXX $@) V_CCDEPS = @$(info $ CCDEPS $@) V_OCAMLC = @$(info $ OCAMLC $@) V_OCAMLOPT = @$(info $ OCAMLOPT $@) @@ -66,6 +67,7 @@ V_ODOC = @$(info $ ODOC $@) else V_CC = +V_CXX = V_CCDEPS = V_OCAMLC = V_OCAMLOPT = diff --git a/aclocal.m4 b/aclocal.m4 index 9b95b0971eb1..a1db7c2cc42d 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -651,3 +651,27 @@ AC_DEFUN([OCAML_CHECK_WINDOWS_TRIPLET], [ [*-pc-windows*], [AC_MSG_ERROR([unknown MSVC variant])]) ]) + +# It's difficult to use AC_PROG_CXX or AX_CXX_COMPILE_STDCXX conditionally. +# This macro is only used for ocamltest to call the C++11 compiler if the +# default C compiler also can build C++. +AC_DEFUN([OCAML_CXX_COMPILE_STDCXX_11], [ + AC_CACHE_CHECK([for a C++11 compiler], + [ocaml_cv_prog_cxx], [ + AS_CASE(["$ccomp_type"], + [cc], [ + saved_CC="$CC" + CC="$CC -xc++" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if !defined(__cplusplus) || __cplusplus < 201103L +#error "No C++11 support" +#endif + ]])], + [ocaml_cv_prog_cxx="$CC"], + [ocaml_cv_prog_cxx=""]) + CC="$saved_CC"], + [msvc], [ + # cl.exe selects between C and C++ based on the file extension + ocaml_cv_prog_cxx="$CC"], + [ocaml_cv_prog_cxx=""])]) + ocamltest_CXX="$ocaml_cv_prog_cxx"]) diff --git a/configure b/configure index 031a97718565..95808a019ac7 100755 --- a/configure +++ b/configure @@ -801,6 +801,8 @@ build_os build_vendor build_cpu build +cxx_extra_warnings +cc_extra_warnings runtime_search_target runtime_search suffixing @@ -870,6 +872,7 @@ cc_has_debug_prefix_map unix_directory unix_library ocamltest_libunix +ocamltest_CXX ocamltest_CPP optional_native_tools optional_bytecode_tools @@ -3568,6 +3571,7 @@ LINEAR_MAGIC_NUMBER=Caml1999L037 + # TODO: rename this variable @@ -3631,6 +3635,8 @@ LINEAR_MAGIC_NUMBER=Caml1999L037 + + @@ -15426,10 +15432,14 @@ fi case $ocaml_cc_vendor in #( xlc-*) : warn_error_flag='' + cc_extra_warnings='' + cxx_extra_warnings='' cc_warnings='-qflag=i:i' ;; #( # all warnings enabled sunc-*) : - cc_warnings="" ;; #( + cc_extra_warnings='' + cxx_extra_warnings='' + cc_warnings='' ;; #( msvc-*) : case $ocaml_cc_vendor in #( msvc-*-clang-*) : @@ -15437,10 +15447,14 @@ case $ocaml_cc_vendor in #( warn_error_flag='-WX' ;; #( *) : cc_warnings='-W2' - warn_error_flag='-WX -options:strict' ;; + cc_extra_warnings='-permissive-' + warn_error_flag='-WX -options:strict' + cxx_extra_warnings="$cc_extra_warnings $warn_error_flag" ;; esac ;; #( *) : warn_error_flag='-Werror' + cc_extra_warnings='-Wextra -Wpedantic -pedantic -std=c11' + cxx_extra_warnings='-Werror -Wextra -Wpedantic -pedantic' cc_warnings="-Wall -Wint-conversion -Wstrict-prototypes \ -Wold-style-definition -Wundef" ;; esac @@ -15581,7 +15595,8 @@ case $enable_warn_error,true in #( yes,*|,true) : cc_warnings="$cc_warnings $warn_error_flag" ;; #( *) : - ;; + cc_extra_warnings='' + cxx_extra_warnings='' ;; esac case $target in #( @@ -23881,7 +23896,54 @@ else $as_nop testsuite/tools/test_in_prefix" fi testsuite_tools='testsuite/tools/codegen testsuite/tools/expect' - optional_bytecode_tools="$optional_bytecode_tools $testsuite_tools" ;; #( + optional_bytecode_tools="$optional_bytecode_tools $testsuite_tools" + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a C++11 compiler" >&5 +printf %s "checking for a C++11 compiler... " >&6; } +if test ${ocaml_cv_prog_cxx+y} +then : + printf %s "(cached) " >&6 +else $as_nop + + case "$ccomp_type" in #( + cc) : + + saved_CC="$CC" + CC="$CC -xc++" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if !defined(__cplusplus) || __cplusplus < 201103L +#error "No C++11 support" +#endif + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ocaml_cv_prog_cxx="$CC" +else $as_nop + ocaml_cv_prog_cxx="" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + CC="$saved_CC" ;; #( + msvc) : + + # cl.exe selects between C and C++ based on the file extension + ocaml_cv_prog_cxx="$CC" ;; #( + *) : + ocaml_cv_prog_cxx="" ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ocaml_cv_prog_cxx" >&5 +printf "%s\n" "$ocaml_cv_prog_cxx" >&6; } + ocamltest_CXX="$ocaml_cv_prog_cxx" ;; #( *) : build_ocamltest=false ocamltest='' ;; diff --git a/configure.ac b/configure.ac index 3d918e242f89..b0e3953797be 100644 --- a/configure.ac +++ b/configure.ac @@ -219,6 +219,7 @@ AC_SUBST([optional_libraries]) AC_SUBST([optional_bytecode_tools]) AC_SUBST([optional_native_tools]) AC_SUBST([ocamltest_CPP]) +AC_SUBST([ocamltest_CXX]) AC_SUBST([ocamltest_libunix]) AC_SUBST([unix_library]) AC_SUBST([unix_directory]) @@ -288,6 +289,8 @@ AC_SUBST([native_runtime_id]) AC_SUBST([suffixing]) AC_SUBST([runtime_search]) AC_SUBST([runtime_search_target]) +AC_SUBST([cc_extra_warnings]) +AC_SUBST([cxx_extra_warnings]) ## Generated files @@ -1035,17 +1038,25 @@ AS_IF([test "x$interpval" = "xyes"], AS_CASE([$ocaml_cc_vendor], [xlc-*], [warn_error_flag='' + cc_extra_warnings='' + cxx_extra_warnings='' cc_warnings='-qflag=i:i'], # all warnings enabled [sunc-*], - [cc_warnings=""], + [cc_extra_warnings='' + cxx_extra_warnings='' + cc_warnings=''], [msvc-*], [AS_CASE([$ocaml_cc_vendor], [msvc-*-clang-*], [cc_warnings='-W4 -Wno-unused-parameter -Wno-sign-compare -Wundef' warn_error_flag='-WX'], [cc_warnings='-W2' - warn_error_flag='-WX -options:strict'])], + cc_extra_warnings='-permissive-' + warn_error_flag='-WX -options:strict' + cxx_extra_warnings="$cc_extra_warnings $warn_error_flag"])], [warn_error_flag='-Werror' + cc_extra_warnings='-Wextra -Wpedantic -pedantic -std=c11' + cxx_extra_warnings='-Werror -Wextra -Wpedantic -pedantic' cc_warnings="-Wall -Wint-conversion -Wstrict-prototypes \ -Wold-style-definition -Wundef"]) @@ -1068,7 +1079,9 @@ done AS_CASE([$enable_warn_error,OCAML__DEVELOPMENT_VERSION], [yes,*|,true], - [cc_warnings="$cc_warnings $warn_error_flag"]) + [cc_warnings="$cc_warnings $warn_error_flag"], + [cc_extra_warnings='' + cxx_extra_warnings='']) AS_CASE([$target], [*-w64-mingw32*|*-pc-windows], @@ -2831,7 +2844,8 @@ testsuite/tools/test_in_prefix.opt"], [optional_bytecode_tools="$optional_bytecode_tools \ testsuite/tools/test_in_prefix"]) testsuite_tools='testsuite/tools/codegen testsuite/tools/expect' - optional_bytecode_tools="$optional_bytecode_tools $testsuite_tools"], + optional_bytecode_tools="$optional_bytecode_tools $testsuite_tools" + OCAML_CXX_COMPILE_STDCXX_11], [build_ocamltest=false ocamltest='']) diff --git a/runtime/caml/sizeclasses.h b/runtime/caml/sizeclasses.h index ab4e7e37ffdd..86a1af361508 100644 --- a/runtime/caml/sizeclasses.h +++ b/runtime/caml/sizeclasses.h @@ -1,4 +1,8 @@ /* This file is generated by tools/gen_sizeclasses.ml */ + +#ifndef CAML_SIZECLASSES_H +#define CAML_SIZECLASSES_H + #define POOL_WSIZE 4096 #define POOL_HEADER_WSIZE 4 #define SIZECLASS_MAX 128 @@ -59,3 +63,5 @@ static const sizeclass sizeclass_wsize[SIZECLASS_MAX + 1] = /*115:*/ 30, 30, 30, 30, 31, /*120:*/ 31, 31, 31, 31, 31, /*125:*/ 31, 31, 31, 31 }; + +#endif /* CAML_SIZECLASSES_H */ diff --git a/tools/gen_sizeclasses.ml b/tools/gen_sizeclasses.ml index 513539e808a0..40093893f164 100644 --- a/tools/gen_sizeclasses.ml +++ b/tools/gen_sizeclasses.ml @@ -89,6 +89,8 @@ let print_list ppf li = let _ = printf "/* This file is generated by tools/gen_sizeclasses.ml */\n"; + printf "\n#ifndef CAML_SIZECLASSES_H\n"; + printf "#define CAML_SIZECLASSES_H\n\n"; printf "#define POOL_WSIZE %d\n" arena; printf "#define POOL_HEADER_WSIZE %d\n" header_size; printf "#define SIZECLASS_MAX %d\n" max_slot; @@ -115,3 +117,4 @@ static const unsigned char wastage_sizeclass[NUM_SIZECLASSES] =@[<2>{ %a };@] static const sizeclass sizeclass_wsize[SIZECLASS_MAX + 1] =@[<2>{ %a };@] |} print_list (255 :: size_slots 1); + printf "\n#endif /* CAML_SIZECLASSES_H */\n"