From 31d78d53217dc041f2816ee3643390c88e32ac55 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Thu, 26 Dec 2024 19:26:00 -0800 Subject: [PATCH 1/5] Require C++14 at minimum to build This is being done to ensure that lutok can leverage a bit more modern C++ idioms. Signed-off-by: Enji Cooper --- configure.ac | 10 +- m4/ac_cxx_compile_stdcxx.m4 | 1070 +++++++++++++++++++++++++++++++++++ m4/compiler-features.m4 | 20 - 3 files changed, 1076 insertions(+), 24 deletions(-) create mode 100644 m4/ac_cxx_compile_stdcxx.m4 diff --git a/configure.ac b/configure.ac index ad1d604..357a8d6 100644 --- a/configure.ac +++ b/configure.ac @@ -41,13 +41,14 @@ AC_CONFIG_SRCDIR([state.hpp]) AM_INIT_AUTOMAKE([1.9 check-news foreign subdir-objects -Wall]) -m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) + +AM_PROG_AR LT_INIT AC_LANG([C++]) AC_PROG_CXX -KYUA_REQUIRE_CXX +AX_CXX_COMPILE_STDCXX(14, noext, mandatory) KYUA_DEVELOPER_MODE([C++]) # Check for ATF and add --enable-atf flag @@ -59,12 +60,13 @@ AM_CONDITIONAL([WITH_ATF], [test "x$enable_atf" = "xyes"]) # ATF dependencies if test "x$enable_atf" = "xyes"; then - ATF_CHECK_CXX([>= 0.15]) - ATF_CHECK_SH([>= 0.15]) + ATF_CHECK_CXX([>= 0.22]) + ATF_CHECK_SH([>= 0.22]) else AC_MSG_NOTICE([ATF support disabled]) fi +ATF_ARG_WITH KYUA_DOXYGEN KYUA_LUA diff --git a/m4/ac_cxx_compile_stdcxx.m4 b/m4/ac_cxx_compile_stdcxx.m4 new file mode 100644 index 0000000..fe6ae17 --- /dev/null +++ b/m4/ac_cxx_compile_stdcxx.m4 @@ -0,0 +1,1070 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11', '14', '17', '20', or +# '23' for the respective C++ standard version. +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for no added switch, and then for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016, 2018 Krzesimir Nowak +# Copyright (c) 2019 Enji Cooper +# Copyright (c) 2020 Jason Merrill +# Copyright (c) 2021, 2024 Jörn Heusipp +# Copyright (c) 2015, 2022, 2023, 2024 Olly Betts +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 25 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], + [$1], [14], [ax_cxx_compile_alternatives="14 1y"], + [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [$1], [20], [ax_cxx_compile_alternatives="20"], + [$1], [23], [ax_cxx_compile_alternatives="23"], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + + m4_if([$2], [], [dnl + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi]) + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for alternative in ${ax_cxx_compile_alternatives}; do + switch="-std=gnu++${alternative}" + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + dnl MSVC needs -std:c++NN for C++17 and later (default is C++14) + for alternative in ${ax_cxx_compile_alternatives}; do + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}" MSVC; do + if test x"$switch" = xMSVC; then + dnl AS_TR_SH maps both `:` and `=` to `_` so -std:c++17 would collide + dnl with -std=c++17. We suffix the cache variable name with _MSVC to + dnl avoid this. + switch=-std:c++${alternative} + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_${switch}_MSVC]) + else + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + fi + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + if test x$ac_success = xyes; then + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11] +) + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14] +) + +dnl Test body for checking C++17 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17] +) + +dnl Test body for checking C++20 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_20] +) + +dnl Test body for checking C++23 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_23], + [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_23] +) + + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +// MSVC always sets __cplusplus to 199711L in older versions; newer versions +// only set it correctly if /Zc:__cplusplus is specified as well as a +// /std:c++NN switch: +// +// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ +// +// The value __cplusplus ought to have is available in _MSVC_LANG since +// Visual Studio 2015 Update 3: +// +// https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros +// +// This was also the first MSVC version to support C++14 so we can't use the +// value of either __cplusplus or _MSVC_LANG to quickly rule out MSVC having +// C++11 or C++14 support, but we can check _MSVC_LANG for C++17 and later. +#elif __cplusplus < 201103L && !defined _MSC_VER + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual ~Base() {} + virtual void f() {} + }; + + struct Derived : public Base + { + virtual ~Derived() override {} + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L && !defined _MSC_VER + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) + + +dnl Tests for new features in C++17 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L + +#error "This is not a C++17 compiler" + +#else + +#include +#include +#include + +namespace cxx17 +{ + + namespace test_constexpr_lambdas + { + + constexpr int foo = [](){return 42;}(); + + } + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template + int multiply(Args... args) + { + return (args * ... * 1); + } + + template + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_auto_brace_init_list + { + + auto foo = {5}; + auto bar {5}; + + static_assert(std::is_same, decltype(foo)>::value); + static_assert(std::is_same::value); + } + + namespace test_typename_in_template_template_parameter + { + + template typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + + namespace test_template_argument_deduction_for_class_templates + { + + template + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } + + namespace test_non_type_auto_template_parameters + { + + template + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + + namespace test_structured_bindings + { + + int arr[2] = { 1, 2 }; + std::pair pr = { 1, 2 }; + + auto f1() -> int(&)[2] + { + return arr; + } + + auto f2() -> std::pair& + { + return pr; + } + + struct S + { + int x1 : 2; + volatile double y1; + }; + + S f3() + { + return {}; + } + + auto [ x1, y1 ] = f1(); + auto& [ xr1, yr1 ] = f1(); + auto [ x2, y2 ] = f2(); + auto& [ xr2, yr2 ] = f2(); + const auto [ x3, y3 ] = f3(); + + } + + namespace test_exception_spec_type_system + { + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template + Bad + f(T*, T*); + + template + Good + f(T1*, T2*); + + static_assert (std::is_same_v); + + } + + namespace test_inline_variables + { + + template void f(T) + {} + + template inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L + +]]) + + +dnl Tests for new features in C++20 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202002L + +#error "This is not a C++20 compiler" + +#else + +#include + +namespace cxx20 +{ + +// As C++20 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx20 + +#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202002L + +]]) + + +dnl Tests for new features in C++23 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_23], [[ + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202302L + +#error "This is not a C++23 compiler" + +#else + +#include + +namespace cxx23 +{ + +// As C++23 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx23 + +#endif // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202302L + +]]) diff --git a/m4/compiler-features.m4 b/m4/compiler-features.m4 index 55ff4f4..e825789 100644 --- a/m4/compiler-features.m4 +++ b/m4/compiler-features.m4 @@ -26,26 +26,6 @@ dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -dnl -dnl KYUA_REQUIRE_CXX -dnl -dnl Ensures the C++ compiler detected by AC_PROG_CXX is present and works. -dnl The compiler check should be performed here, but it seems like Autoconf -dnl does not allow it. -dnl -AC_DEFUN([KYUA_REQUIRE_CXX], [ - AC_CACHE_CHECK([whether the C++ compiler works], - [atf_cv_prog_cxx_works], - [AC_LANG_PUSH([C++]) - AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], - [atf_cv_prog_cxx_works=yes], - [atf_cv_prog_cxx_works=no]) - AC_LANG_POP([C++])]) - if test "${atf_cv_prog_cxx_works}" = no; then - AC_MSG_ERROR([C++ compiler cannot create executables]) - fi -]) - dnl dnl KYUA_ATTRIBUTE_NORETURN dnl From 1ff4d8f13d329743f233fd7663e01a69cab082b4 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Wed, 25 Dec 2024 23:01:26 -0800 Subject: [PATCH 2/5] lua.m4: clean up file - Rely on pkg-config or pkgconf instead of lua-config when querying lua's build config: lua-config is no longer distributed with many distributions. - Bump the minimum version of lua to 5.3 (the last 5.2 release was in 2015). Signed-off-by: Enji Cooper --- m4/lua.m4 | 47 ++++++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/m4/lua.m4 b/m4/lua.m4 index be282da..2cd0d2d 100644 --- a/m4/lua.m4 +++ b/m4/lua.m4 @@ -33,37 +33,30 @@ dnl Helper macro to detect Lua in a variety of systems. dnl AC_DEFUN([KYUA_LUA], [ lua_found=no - - for lua_release in ${LUA_VERSION:-5.4 5.3 5.2 5.1}; do - if test "${lua_found}" = no; then + for lua_release in ${LUA_VERSION:-5.4 5.3}; do + AS_IF([test "${lua_found}" = no],[ PKG_CHECK_MODULES([LUA], [lua${lua_release} >= ${lua_release}], - [lua_found=yes], [true]) - fi - if test "${lua_found}" = no; then + [lua_found="lua${lua_release}"; break],[]) + ]) + AS_IF([test "${lua_found}" = no],[ PKG_CHECK_MODULES([LUA], [lua-${lua_release} >= ${lua_release}], - [lua_found=yes], [true]) - fi - if test "${lua_found}" = no; then + [lua_found="lua-${lua_release}"; break],[]) + ]) + AS_IF([test "${lua_found}" = no],[ PKG_CHECK_MODULES([LUA], [lua >= ${lua_release}], - [lua_found=yes], [true]) - fi - - test "${lua_found}" = no || break + [lua_found=lua; break],[]) + ]) done - if test "${lua_found}" = no; then - AC_PATH_PROGS([LUA_CONFIG], [lua-config], [unset]) - if test "${LUA_CONFIG}" != unset; then - AC_SUBST([LUA_CFLAGS], [$(${LUA_CONFIG} --include)]) - AC_SUBST([LUA_LIBS], [$(${LUA_CONFIG} --libs)]) - lua_found=yes - fi - fi + AS_IF([test "${lua_found}" = no],[],[ + AC_SUBST([LUA_CFLAGS], [$(${PKG_CONFIG} --cflags ${lua_found})]) + AC_SUBST([LUA_LIBS], [$(${PKG_CONFIG} --libs ${lua_found})]) + ]) - if test "${lua_found}" = no; then - AC_MSG_ERROR([lua (5.1 or newer) is required]) - else - AC_MSG_NOTICE([using LUA_CFLAGS = ${LUA_CFLAGS}]) - AC_MSG_NOTICE([using LUA_LIBS = ${LUA_LIBS}]) - fi + AS_IF([test "${lua_found}" = no], + [AC_MSG_ERROR([lua (5.3 or newer) is required])], + [ +AC_MSG_NOTICE([using LUA_CFLAGS = ${LUA_CFLAGS}]) +AC_MSG_NOTICE([using LUA_LIBS = ${LUA_LIBS}]) + ]) ]) From b66296e3ad8b30c010c3e6fdd45229628c38fa1f Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Wed, 25 Dec 2024 23:08:57 -0800 Subject: [PATCH 3/5] Remove `--with-atf` This flag was replaced by `--enable-atf` in 0.5. Signed-off-by: Enji Cooper --- INSTALL.md | 2 +- configure.ac | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index c658570..2389b23 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -128,7 +128,7 @@ The following flags are specific to Lutok's `configure` script: detection features regardless of the value of this flag. However, such warnings are only fatal when `--enable-developer` is set to "yes". -- `--with-atf` +- `--enable-atf` - **Possible values**: "yes", "no", "auto". - **Default**: "auto" diff --git a/configure.ac b/configure.ac index 357a8d6..7bed5c6 100644 --- a/configure.ac +++ b/configure.ac @@ -59,14 +59,13 @@ AC_ARG_ENABLE([atf], AM_CONDITIONAL([WITH_ATF], [test "x$enable_atf" = "xyes"]) # ATF dependencies -if test "x$enable_atf" = "xyes"; then - ATF_CHECK_CXX([>= 0.22]) - ATF_CHECK_SH([>= 0.22]) -else - AC_MSG_NOTICE([ATF support disabled]) -fi +m4_ifdef([ATF_CHECK_CXX],[ +AS_IF([test "x$enable_atf" = "xyes"],[ + ATF_CHECK_CXX([>= 0.21]) + ATF_CHECK_SH([>= 0.21]) +],[AC_MSG_NOTICE([ATF support disabled])]) +]) -ATF_ARG_WITH KYUA_DOXYGEN KYUA_LUA From 2de2e52dceed633d2fcae93897b5a5584be6bd7f Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Wed, 25 Dec 2024 23:37:03 -0800 Subject: [PATCH 4/5] Remove pre C++11 support C++14 is now required to build lutok. Remove all pre-C++11 oxbow code. Submitted by: Minsoo Choo Signed-off-by: Enji Cooper --- debug.hpp | 8 -------- state.hpp | 11 +---------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/debug.hpp b/debug.hpp index 6fc074d..6ada1fc 100644 --- a/debug.hpp +++ b/debug.hpp @@ -33,11 +33,7 @@ #define LUTOK_DEBUG_HPP #include -#if defined(_LIBCPP_VERSION) || __cplusplus >= 201103L #include -#else -#include -#endif namespace lutok { @@ -59,11 +55,7 @@ class debug { struct impl; /// Pointer to the shared internal implementation. -#if defined(_LIBCPP_VERSION) || __cplusplus >= 201103L std::shared_ptr< impl > _pimpl; -#else - std::tr1::shared_ptr< impl > _pimpl; -#endif public: debug(void); diff --git a/state.hpp b/state.hpp index 377aa06..3b088f1 100644 --- a/state.hpp +++ b/state.hpp @@ -32,13 +32,8 @@ #if !defined(LUTOK_STATE_HPP) #define LUTOK_STATE_HPP -#include - -#if defined(_LIBCPP_VERSION) || __cplusplus >= 201103L #include -#else -#include -#endif +#include namespace lutok { @@ -77,11 +72,7 @@ class state { struct impl; /// Pointer to the shared internal implementation. -#if defined(_LIBCPP_VERSION) || __cplusplus >= 201103L std::shared_ptr< impl > _pimpl; -#else - std::tr1::shared_ptr< impl > _pimpl; -#endif void* new_userdata_voidp(const size_t); void* to_userdata_voidp(const int); From e037e605d5b4c0712a104eb1d63604e30432b9a7 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Thu, 26 Dec 2024 16:42:21 -0800 Subject: [PATCH 5/5] Add initial GitHub Actions support for lutok This proposed GitHub Actions workflow file runs tests on MacOS and Ubuntu Linux, similar to what is being proposed in https://github.com/freebsd/atf/pull/93 . The delta between this change and the one being made in ATF mostly relates to the additional package dependencies, e.g., Lua, and build permutations, e.g., with and without ATF. Kyua is built from scratch because of issues with dependent packages and runtime linker collisions on both MacOS and Ubuntu. The binary package versions are built against a different version of Lutok, ergo they can have runtime linker collisions. Signed-off-by: Enji Cooper --- .github/workflows/build.yaml | 200 +++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 .github/workflows/build.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..20134cd --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,200 @@ +--- +# GitHub action to compile and test lutok on supported platforms. +# +# Steps executed: +# * Handle prerequisites +# * Install binary packages +# * Build packages from source (if needed). +# * Build +# * Install +# * Run tests +# +# On MacOS we build with: +# * latest clang from brew (system provided clang lacks sanitizers). +# * ld from system +# +# Notes re: building with Lua 5.3... +# * In order to build/test with 5.3 on MacOS, we would need to build lutok +# and kyua from scratch. Installing via the formula picks up the binary +# package, which is built against the default version of Lua (5.4). +# * I'm not sure why Ubuntu doesn't distribute the liblua5.3-dev package on +# 24.04. +env: + KYUA_REPO: freebsd/kyua + # XXX: kyua-0.13 doesn't build because of std::auto_array no longer being a thing.. + # KYUA_REF: kyua-0.13 + KYUA_REF: master + +name: build +on: + pull_request: + branches: + - master + push: + workflow_dispatch: + +permissions: + contents: read + +jobs: + build: + name: Build ${{ matrix.build-os }} ${{ matrix.compiler }} ${{ matrix.enable-atf }} + runs-on: "${{ matrix.build-os }}" + strategy: + fail-fast: false + matrix: + build-os: + - ubuntu-24.04 + - macos-latest + enable-atf: [--disable-atf, --enable-atf] + include: + - build-os: macos-latest + compiler: clang-19 + pkgs: + - llvm@19 + - autoconf + - automake + - libtool + - pkgconf + - lua@5.4 + enable-atf-dep-pkgs: + - atf + llvm-bindir: /opt/homebrew/opt/llvm/bin + - build-os: ubuntu-24.04 + compiler: clang-18 + pkgs: + - clang-18 + - autoconf + - automake + - libtool + - pkgconf + - liblua5.4-dev + - lua5.4 + enable-atf-dep-pkgs: + - atf-sh + - libatf-c++-2 + - libatf-c-1 + - libatf-dev + kyua-dep-pkgs: + - libsqlite3-dev + llvm-bindir: /usr/lib/llvm-18/bin + steps: + - name: Install Lutok base dependencies (macOS) + if: runner.os == 'macOS' + run: | + brew update --quiet || true + brew install ${{ join(matrix.pkgs, ' ') }} + - name: Install Lutok base dependencies (Ubuntu) + if: runner.os == 'Linux' + run: | + sudo apt -Uqy --no-install-suggests \ + --no-install-recommends install \ + ${{ join(matrix.pkgs, ' ') }} + - name: Install ATF/Kyua dependencies (MacOS) + if: runner.os == 'macOS' && matrix.enable-atf == '--enable-atf' + run: | + brew install \ + ${{ join(matrix.enable-atf-dep-pkgs, ' ') }} \ + ${{ join(matrix.kyua-dep-pkgs, ' ') }} + - name: Install ATF/Kyua dependencies (Ubuntu) + if: runner.os == 'Linux' && matrix.enable-atf == '--enable-atf' + run: | + sudo apt -Uqy --no-install-suggests \ + --no-install-recommends install \ + ${{ join(matrix.enable-atf-dep-pkgs, ' ') }} \ + ${{ join(matrix.kyua-dep-pkgs, ' ') }} + - name: Checking out source + uses: actions/checkout@v4 + with: + # Same as `LUTOK_SRCDIR`. + path: ${{ github.workspace }}/lutok-src + - name: Setup Environment + run: | + echo "AR=${{ matrix.llvm-bindir }}/llvm-ar" >> "${GITHUB_ENV}" + echo "CC=${{ matrix.llvm-bindir }}/clang" >> "${GITHUB_ENV}" + echo "CPP=${{ matrix.llvm-bindir }}/clang-cpp" >> "${GITHUB_ENV}" + echo "CXX=${{ matrix.llvm-bindir }}/clang++" >> "${GITHUB_ENV}" + echo "NM=${{ matrix.llvm-bindir }}/llvm-nm" >> "${GITHUB_ENV}" + echo "PKG_CONFIG_PATH='$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig'" >> "${GITHUB_ENV}" + echo "RANLIB=${{ matrix.llvm-bindir }}/llvm-ranlib" >> "${GITHUB_ENV}" + echo "OBJDUMP=${{ matrix.llvm-bindir }}/llvm-objdump" >> "${GITHUB_ENV}" + echo "STRIP=${{ matrix.llvm-bindir }}/llvm-strip" >> "${GITHUB_ENV}" + echo "KYUA_SRCDIR=${GITHUB_WORKSPACE}/kyua-src" >> "${GITHUB_ENV}" + echo "KYUA_OBJDIR=${GITHUB_WORKSPACE}/kyua-obj" >> "${GITHUB_ENV}" + echo "LUTOK_SRCDIR=${GITHUB_WORKSPACE}/lutok-src" >> "${GITHUB_ENV}" + echo "LUTOK_OBJDIR=${GITHUB_WORKSPACE}/lutok-obj" >> "${GITHUB_ENV}" + echo "LUTOK_PREFIX=/usr/local" >> "${GITHUB_ENV}" + echo "NPROC=`getconf _NPROCESSORS_ONLN 2>/dev/null || getconf NPROCESSORS_ONLN 2>/dev/null || echo 1`" >> "${GITHUB_ENV}" + - name: Build Lutok + run: | + CFG_OPTS="--disable-dependency-tracking ${{ matrix.enable-atf }}" + CFG_OPTS="${CFG_OPTS} --prefix=${LUTOK_PREFIX}" + echo "Building lutok with ${CFG_OPTS}..." + echo "uname -a: $(uname -a)" + echo "uname -m: $(uname -m)" + echo "uname -p: $(uname -p)" + echo "Build environment:" + cat "${GITHUB_ENV}" + cd "${LUTOK_SRCDIR}" + autoreconf -isv -I/usr/local/share/aclocal + mkdir -p "${LUTOK_OBJDIR}" + cd "${LUTOK_OBJDIR}" + "${LUTOK_SRCDIR}/configure" ${CFG_OPTS} + make -j${NPROC} all | tee lutok-make-all.log + - name: Install Lutok + run: | + cd "${LUTOK_OBJDIR}" + sudo make install + - name: Regenerate linker config (Ubuntu) + if: runner.os == 'Linux' && matrix.enable-atf == '--enable-atf' + run: | + sudo ldconfig + # Everything from here on out is --enable-atf related. + - name: Clone Kyua source + if: matrix.enable-atf == '--enable-atf' + uses: actions/checkout@v4 + with: + repository: "${{ env.KYUA_REPO }}" + ref: "${{ env.KYUA_REF }}" + # Same as `KYUA_SRCDIR`. + path: "${{ github.workspace }}/kyua-src" + - name: Build and Install Kyua + if: matrix.enable-atf == '--enable-atf' + run: | + CFG_OPTS="--disable-dependency-tracking" + CFG_OPTS="${CFG_OPTS} --prefix=${LUTOK_PREFIX}" + CXXFLAGS="$(pkgconf --cflags atf-c++ lutok)" + LDFLAGS="$(pkgconf --libs-only-L atf-c++ lutok)" + echo "Building lutok with ${CFG_OPTS}..." + echo "uname -a: $(uname -a)" + echo "uname -m: $(uname -m)" + echo "uname -p: $(uname -p)" + cd "${KYUA_SRCDIR}" + autoreconf -isv -I/usr/local/share/aclocal + mkdir -p "${KYUA_OBJDIR}" + cd "${KYUA_OBJDIR}" + set -x + env CXXFLAGS="${CXXFLAGS}" \ + LDFLAGS="${LDFLAGS}" \ + "${KYUA_SRCDIR}/configure" ${CFG_OPTS} + make -j${NPROC} all | tee kyua-make-all.log + sudo make install + - name: Test Lutok + if: matrix.enable-atf == '--enable-atf' + run: | + cd "${LUTOK_PREFIX}/tests/lutok" + kyua test + check_exit=$? + if [ $check_exit -eq 0 ]; then + echo "# ✅ All mandatory checks passed" >> $GITHUB_STEP_SUMMARY + else + echo "# ❌ Some checks failed" >> $GITHUB_STEP_SUMMARY + echo "::error file=.github/workflows/build.yaml,line=173,endLine=173,title=Checks failed!::checks failed" + fi + kyua report-html --output ${LUTOK_OBJDIR}/html # produces html subdirectory + # Include the plaintext and JUnit reports. + kyua report --verbose --results-filter=xfail,broken,failed > ${LUTOK_OBJDIR}/html/test-reportfailed.txt + kyua report-junit --output ${LUTOK_OBJDIR}/html/test-reportfailed.xml + # Include the kyua log. + cp -a ~/.kyua/logs ${LUTOK_OBJDIR}/html/ + exit $check_exit