From dd5f1b7f5e715b68841f9174f763482877e4ce54 Mon Sep 17 00:00:00 2001 From: David Allsopp Date: Mon, 26 Jan 2026 18:31:20 +0000 Subject: [PATCH 1/2] Add ${outputobj} to ocamltest instead of cxx.sh --- ocamltest/ocaml_actions.ml | 1 + ocamltest/ocaml_variables.ml | 4 ++++ ocamltest/ocaml_variables.mli | 2 ++ ocamltest/ocamltest_config.ml.in | 2 ++ ocamltest/ocamltest_config.mli | 3 +++ testsuite/tests/lib-unix/unix-sockaddr/cxx.sh | 19 ------------------- .../lib-unix/unix-sockaddr/sockaddr_cxx.ml | 14 +++++++++++--- 7 files changed, 23 insertions(+), 22 deletions(-) delete mode 100755 testsuite/tests/lib-unix/unix-sockaddr/cxx.sh diff --git a/ocamltest/ocaml_actions.ml b/ocamltest/ocaml_actions.ml index 33d0aa3c8fbd..9385f11335f0 100644 --- a/ocamltest/ocaml_actions.ml +++ b/ocamltest/ocaml_actions.ml @@ -1097,6 +1097,7 @@ let config_variables _log env = Ocaml_variables.cpp, Ocamltest_config.cpp; Ocaml_variables.cppflags, Ocamltest_config.cppflags; Ocaml_variables.cc, Ocamltest_config.cc; + Ocaml_variables.outputobj, Ocamltest_config.outputobj; Ocaml_variables.cflags, Ocamltest_config.cflags; Ocaml_variables.cxx, Ocamltest_config.cxx; Ocaml_variables.ccomp_type, Ocamltest_config.ccomp_type; diff --git a/ocamltest/ocaml_variables.ml b/ocamltest/ocaml_variables.ml index 3ec8f1c18700..426ff52309d1 100644 --- a/ocamltest/ocaml_variables.ml +++ b/ocamltest/ocaml_variables.ml @@ -47,6 +47,9 @@ let cppflags = make ("cppflags", let cc = make ("cc", "Command to use to invoke the C compiler") +let outputobj = make ("outputobj", + "Exact string to prefix a call to cc -c to name the object") + let cflags = make ("cflags", "Flags passed to the C compiler") @@ -259,6 +262,7 @@ let _ = List.iter register_variable cppflags; cc; cflags; + outputobj; cxx; caml_ld_library_path; codegen_exit_status; diff --git a/ocamltest/ocaml_variables.mli b/ocamltest/ocaml_variables.mli index 66cf0d788a0b..5de1c086fadf 100644 --- a/ocamltest/ocaml_variables.mli +++ b/ocamltest/ocaml_variables.mli @@ -32,6 +32,8 @@ val cppflags : Variables.t val cc : Variables.t +val outputobj : Variables.t + val cflags : Variables.t val cxx : Variables.t diff --git a/ocamltest/ocamltest_config.ml.in b/ocamltest/ocamltest_config.ml.in index 8d752b228dfa..0ce8e506519d 100644 --- a/ocamltest/ocamltest_config.ml.in +++ b/ocamltest/ocamltest_config.ml.in @@ -91,6 +91,8 @@ let exe = {@QS@|@EXEEXT@|@QS@} let mkdll = {@QS@|@mkdll_exp@|@QS@} let mkexe = {@QS@|@mkexe_exp@|@QS@} +let outputobj = {@QS@|@outputobj@|@QS@} + let bytecc_libs = {@QS@|@zstd_libs@ @cclibs@|@QS@} let nativecc_libs = {@QS@|@cclibs@|@QS@} diff --git a/ocamltest/ocamltest_config.mli b/ocamltest/ocamltest_config.mli index 1cc7d7aa2d74..14b2fd4d94a7 100644 --- a/ocamltest/ocamltest_config.mli +++ b/ocamltest/ocamltest_config.mli @@ -33,6 +33,9 @@ val cppflags : string val cc : string (** Command to use to invoke the C compiler *) +val outputobj : string +(** The exact string to use when running [cc -c] to name the object file *) + val cflags : string (** Flags to pass to the C compiler *) diff --git a/testsuite/tests/lib-unix/unix-sockaddr/cxx.sh b/testsuite/tests/lib-unix/unix-sockaddr/cxx.sh deleted file mode 100755 index d81f215b22b0..000000000000 --- a/testsuite/tests/lib-unix/unix-sockaddr/cxx.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -set -eu - -case "$ccomp_type" in - cc) outputobj='-o ' ;; - msvc) outputobj='-Fo' ;; - *) exit "$TEST_SKIP" ;; -esac - -if ${cxx} ${cppflags} ${cflags} \ - -I "${ocamlsrcdir}/runtime" \ - -I "${ocamlsrcdir}/otherlibs/unix" \ - ${outputobj}"${test_build_directory}/sockaddr_cxx_aux.${objext}" \ - -c "${test_source_directory}/sockaddr_cxx_aux.cpp"; then - exit "$TEST_PASS" -else - exit "$TEST_FAIL" -fi diff --git a/testsuite/tests/lib-unix/unix-sockaddr/sockaddr_cxx.ml b/testsuite/tests/lib-unix/unix-sockaddr/sockaddr_cxx.ml index 54bd1f1867d6..e11525f5eb1c 100644 --- a/testsuite/tests/lib-unix/unix-sockaddr/sockaddr_cxx.ml +++ b/testsuite/tests/lib-unix/unix-sockaddr/sockaddr_cxx.ml @@ -1,11 +1,15 @@ (* TEST has-cxx; - readonly_files = "sockaddr_cxx_aux.cpp cxx.sh"; + readonly_files = "sockaddr_cxx_aux.cpp"; hasunix; include unix; { setup-ocamlopt.byte-build-env; - script = "sh cxx.sh"; + script = "${cxx} ${cppflags} ${cflags} \ + -I ${ocamlsrcdir}/runtime \ + -I ${ocamlsrcdir}/otherlibs/unix \ + ${outputobj}${test_build_directory}/sockaddr_cxx_aux.${objext} \ + -c ${test_source_directory}/sockaddr_cxx_aux.cpp"; script; all_modules = "sockaddr_cxx_aux.${objext} sockaddr_cxx.ml"; ocamlopt.byte; @@ -16,7 +20,11 @@ } { setup-ocamlc.byte-build-env; - script = "sh cxx.sh"; + script = "${cxx} ${cppflags} ${cflags} \ + -I ${ocamlsrcdir}/runtime \ + -I ${ocamlsrcdir}/otherlibs/unix \ + ${outputobj}${test_build_directory}/sockaddr_cxx_aux.${objext} \ + -c ${test_source_directory}/sockaddr_cxx_aux.cpp"; script; all_modules = "sockaddr_cxx_aux.${objext} sockaddr_cxx.ml"; flags = "-output-complete-exe -cclib -lunixbyt"; From ca25a86e389fe635acf7a37e091483ce3496aafd Mon Sep 17 00:00:00 2001 From: David Allsopp Date: Mon, 26 Jan 2026 18:19:53 +0000 Subject: [PATCH 2/2] Refactor all_includes.ml as a C++ API linking test --- testsuite/tests/cxx-api/all-includes.h.sh | 12 --- testsuite/tests/cxx-api/all_includes.ml | 40 -------- testsuite/tests/cxx-api/cxx-sarif.sh | 93 ------------------- testsuite/tests/cxx-api/cxx_api.ml | 44 +++++++++ ...l_includes.reference => cxx_api.reference} | 0 testsuite/tests/cxx-api/deps.sh | 33 ------- testsuite/tests/cxx-api/stubs.cpp | 4 +- 7 files changed, 47 insertions(+), 179 deletions(-) delete mode 100755 testsuite/tests/cxx-api/all-includes.h.sh delete mode 100644 testsuite/tests/cxx-api/all_includes.ml delete mode 100755 testsuite/tests/cxx-api/cxx-sarif.sh create mode 100644 testsuite/tests/cxx-api/cxx_api.ml rename testsuite/tests/cxx-api/{all_includes.reference => cxx_api.reference} (100%) delete mode 100755 testsuite/tests/cxx-api/deps.sh diff --git a/testsuite/tests/cxx-api/all-includes.h.sh b/testsuite/tests/cxx-api/all-includes.h.sh deleted file mode 100755 index e12c8fb7f221..000000000000 --- a/testsuite/tests/cxx-api/all-includes.h.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -set -eu - -for lib in "$ocamlsrcdir"/runtime "$ocamlsrcdir"/otherlibs/*/; do - for file in "$lib"/caml/*.h; do - header="$(basename "$file")" - if [ "$header" != "jumptbl.h" ] && [ -e "$file" ]; then - echo "#include " >> "$test_build_directory"/all-includes.h - fi - done -done diff --git a/testsuite/tests/cxx-api/all_includes.ml b/testsuite/tests/cxx-api/all_includes.ml deleted file mode 100644 index fc6a4ba78880..000000000000 --- a/testsuite/tests/cxx-api/all_includes.ml +++ /dev/null @@ -1,40 +0,0 @@ -(* TEST - has-cxx; - hassysthreads; - readonly_files = "deps.sh all-includes.h.sh cxx-sarif.sh stubs.cpp"; - include runtime_events; - include systhreads; - script = "sh ${test_source_directory}/deps.sh"; - script; - { - setup-ocamlopt.byte-build-env; - script = "sh all-includes.h.sh"; - script; - script = "sh cxx-sarif.sh"; - script; - all_modules = "stubs.${objext} all_includes.ml"; - ocamlopt.byte; - output = "${test_build_directory}/program-output"; - stdout = "${output}"; - run; - check-program-output; - } - { - setup-ocamlc.byte-build-env; - script = "sh all-includes.h.sh"; - script; - script = "sh cxx-sarif.sh"; - script; - all_modules = "stubs.${objext} all_includes.ml"; - flags = "-output-complete-exe -cclib -lunixbyt -cclib -lthreads -cclib -lcamlruntime_eventsbyt"; - ocamlc.byte; - output = "${test_build_directory}/program-output"; - stdout = "${output}"; - run; - check-program-output; - } -*) - -external test_cxx : unit -> string = "test_cxx" - -let () = print_string (test_cxx ()) diff --git a/testsuite/tests/cxx-api/cxx-sarif.sh b/testsuite/tests/cxx-api/cxx-sarif.sh deleted file mode 100755 index 528455653309..000000000000 --- a/testsuite/tests/cxx-api/cxx-sarif.sh +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/sh - -set -eu - -# Try to build a C++ file including all of OCaml headers, and using a -# few functions from its API. -# -# Ask for a wide set of warnings from the C++ compiler, but explicitly -# ignore some warnings about C features that are not valid in C++ (but -# commonly supported as extensions), such as: -# -# - C99 flexible array member (FAM) -# + https://en.wikipedia.org/wiki/Flexible_array_member -# + https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-levels-2-and-4-c4200 -# -# The compiler's diagnostics are produced as SARIF, because it's -# easier to parse, and use jq to filter out errors we can safely -# ignore. - -case "$ccomp_type" in - cc) - # TODO: use GCC 15 -fdiagnostics-add-output for stderr and SARIF - # output sinks - if $cxx -Wall -Wextra -Wpedantic \ - -fdiagnostics-format=sarif-stderr \ - $cppflags $cflags \ - -I "$ocamlsrcdir"/runtime \ - -I "$ocamlsrcdir"/otherlibs/runtime_events \ - -I "$ocamlsrcdir"/otherlibs/str \ - -I "$ocamlsrcdir"/otherlibs/systhreads \ - -I "$ocamlsrcdir"/otherlibs/unix \ - -I "$test_build_directory" \ - -o "$test_build_directory"/stubs.o \ - -c "$test_source_directory"/stubs.cpp \ - 2> stubs.sarif; then - exit "$TEST_PASS" - else - cat <<'EOF' > filter.jq -.runs.[0].results.[] -| select(.message.text - # Allow flexible array member - | contains("ISO C++ forbids flexible array member") | not) -| length -EOF - fi - ;; - msvc) - if $cxx -W2 -permissive- \ - -experimental:log stubs \ - $cppflags $cflags \ - -I "$ocamlsrcdir"\\runtime \ - -I "$ocamlsrcdir"\\otherlibs\\runtime_events \ - -I "$ocamlsrcdir"\\otherlibs\\str \ - -I "$ocamlsrcdir"\\otherlibs\\systhreads \ - -I "$ocamlsrcdir"\\otherlibs\\unix \ - -I "$test_build_directory" \ - -Fo"$test_build_directory"\\stubs.obj \ - -c "$test_source_directory"\\stubs.cpp \ - >/dev/null 2>&1; then - exit "$TEST_PASS" - else - cat <<'EOF' > filter.jq -.runs.[0].results.[] -| select(.ruleId - # Allow flexible array member - | contains("C4200") | not) -| length -EOF - fi - ;; -esac - -length=$(jq -f filter.jq stubs.sarif) -if [ -z "$length" ]; then - exit "$TEST_PASS" -fi - -# pretty-print -jq . stubs.sarif > stubs.sarif.tmp -mv stubs.sarif.tmp stubs.sarif - -if [ "${GITHUB_ACTIONS:-false}" = true ]; then - echo - echo "::group::stubs.sarif content ($(wc -l stubs.sarif) lines)" - cat stubs.sarif - echo - echo '::endgroup::' -elif [ -n "${CI+true}" ]; then - cat stubs.sarif -fi -echo "$cxx reported errors at $test_build_directory/stubs.sarif" \ - >> "$ocamltest_response" -exit "$TEST_FAIL" diff --git a/testsuite/tests/cxx-api/cxx_api.ml b/testsuite/tests/cxx-api/cxx_api.ml new file mode 100644 index 000000000000..5e4226bc5e9e --- /dev/null +++ b/testsuite/tests/cxx-api/cxx_api.ml @@ -0,0 +1,44 @@ +(* TEST + has-cxx; + hassysthreads; + readonly_files = "stubs.cpp cxx.sh"; + include runtime_events; + include systhreads; + { + setup-ocamlopt.byte-build-env; + script = "${cxx} ${cppflags} ${cflags} \ + -I ${ocamlsrcdir}/runtime \ + -I ${ocamlsrcdir}/otherlibs/systhreads \ + -I ${ocamlsrcdir}/otherlibs/unix \ + ${outputobj}${test_build_directory}/stubs.${objext} \ + -c ${test_source_directory}/stubs.cpp"; + script; + all_modules = "stubs.${objext} cxx_api.ml"; + ocamlopt.byte; + output = "${test_build_directory}/program-output"; + stdout = "${output}"; + run; + check-program-output; + } + { + setup-ocamlc.byte-build-env; + script = "${cxx} ${cppflags} ${cflags} \ + -I ${ocamlsrcdir}/runtime \ + -I ${ocamlsrcdir}/otherlibs/systhreads \ + -I ${ocamlsrcdir}/otherlibs/unix \ + ${outputobj}${test_build_directory}/stubs.${objext} \ + -c ${test_source_directory}/stubs.cpp"; + script; + all_modules = "stubs.${objext} cxx_api.ml"; + flags = "-output-complete-exe -cclib -lunixbyt -cclib -lthreads -cclib -lcamlruntime_eventsbyt"; + ocamlc.byte; + output = "${test_build_directory}/program-output"; + stdout = "${output}"; + run; + check-program-output; + } +*) + +external test_cxx : unit -> string = "test_cxx" + +let () = print_string (test_cxx ()) diff --git a/testsuite/tests/cxx-api/all_includes.reference b/testsuite/tests/cxx-api/cxx_api.reference similarity index 100% rename from testsuite/tests/cxx-api/all_includes.reference rename to testsuite/tests/cxx-api/cxx_api.reference diff --git a/testsuite/tests/cxx-api/deps.sh b/testsuite/tests/cxx-api/deps.sh deleted file mode 100755 index 5e29696b83a5..000000000000 --- a/testsuite/tests/cxx-api/deps.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh - -set -eu - -if ! command -v jq >/dev/null 2>&1; then - echo "jq could not be found" >> "$ocamltest_response" - exit "$TEST_SKIP" -fi - -case "$ccomp_type" in - cc) - gnuc=$(echo '__GNUC__' | $cxx -E -P -) - - if [ "$gnuc" -lt 13 ]; then - echo "GCC 13 or later is required for SARIF diagnostics" \ - >> "$ocamltest_response" - exit "$TEST_SKIP" - fi - ;; - msvc) - if $cxx '/?' | head -n1 | grep -q 'clang LLVM compiler'; then - echo "MSVC (not clang-cl) is required for SARIF diagnostics" \ - >> "$ocamltest_response" - exit "$TEST_SKIP" - fi - ;; - *) - echo "Unknown ccomp_type $ccomp_type" >> "$ocamltest_response" - exit "$TEST_SKIP" - ;; -esac - -exit "$TEST_PASS" diff --git a/testsuite/tests/cxx-api/stubs.cpp b/testsuite/tests/cxx-api/stubs.cpp index 52a21119090e..562cc4458088 100644 --- a/testsuite/tests/cxx-api/stubs.cpp +++ b/testsuite/tests/cxx-api/stubs.cpp @@ -2,7 +2,9 @@ #error "A C++ compiler is required!" #endif -#include "all-includes.h" +#include +#include +#include #include extern "C" {