From 775db504605a8572e81698a699e30a48091e3070 Mon Sep 17 00:00:00 2001 From: Matthew Krupcale Date: Mar 04 2023 21:26:26 +0000 Subject: Add patches for git v2.38, libpkgconf v1.9.0, and C++23 std::aligned_storage Fedora updates to git, libpkgconf, and GCC require some additional patches [1] to build2 to build and run correctly. These patches [2-4] are now upstreamed, and we apply them here. * bpkg-git-v2.38.patch: patch for git v2.38 dropping submodule--helper commands * build2.spec: use and apply new patches * libbuild2-cxx23-aligned_storage-deprecation.patch: patch for C++23 std::aligned_storage deprecation * libbuild2-libpkgconf-error_handler-non-const-data.patch: patch for libpkgconf v1.9.0 changing the error handler function signature [1] https://lists.build2.org/archives/users/2023-March/001014.html [2] https://git.build2.org/cgit/bpkg/commit/?id=a97b12a027546b37f66d3e08064f92f5539cf79e [3] https://git.build2.org/cgit/build2/commit/?id=343d6e69e412166cfc21f268a51b692cb0201653 [4] https://git.build2.org/cgit/build2/commit/?id=417be15231cb34a2e858d26b63406d1fb5535cb9 --- diff --git a/bpkg-git-v2.38.patch b/bpkg-git-v2.38.patch new file mode 100644 index 0000000..7f4ca65 --- /dev/null +++ b/bpkg-git-v2.38.patch @@ -0,0 +1,367 @@ +commit a97b12a027546b37f66d3e08064f92f5539cf79e +Author: Karen Arutyunov +Date: 2022-10-26 18:38:32 +0300 + + Adapt to git 2.38 which drops submodule--helper-{list,name} subcommands + +diff --git a/bpkg/fetch-git.cxx b/bpkg/fetch-git.cxx +index 3f6115f..e2bfb2d 100644 +--- a/bpkg/fetch-git.cxx ++++ b/bpkg/fetch-git.cxx +@@ -877,24 +877,25 @@ namespace bpkg + text << "querying " << url; + + refs rs; +- fdpipe pipe (open_pipe ()); +- +- // Note: ls-remote doesn't print anything to stderr, so no progress +- // suppression is required. +- // +- process pr (start_git (co, +- pipe, 2 /* stderr */, +- timeout_opts (co, url.scheme), +- co.git_option (), +- "ls-remote", +- to_git_url (url))); +- +- // Shouldn't throw, unless something is severely damaged. +- // +- pipe.out.close (); + + for (;;) // Breakout loop. + { ++ fdpipe pipe (open_pipe ()); ++ ++ // Note: ls-remote doesn't print anything to stderr, so no progress ++ // suppression is required. ++ // ++ process pr (start_git (co, ++ pipe, 2 /* stderr */, ++ timeout_opts (co, url.scheme), ++ co.git_option (), ++ "ls-remote", ++ to_git_url (url))); ++ ++ // Shouldn't throw, unless something is severely damaged. ++ // ++ pipe.out.close (); ++ + try + { + ifdstream is (move (pipe.in), fdstream_mode::skip, ifdstream::badbit); +@@ -1683,6 +1684,255 @@ namespace bpkg + // If gitmodules is false, then don't check if the .gitmodules file is + // present, assuming this have already been checked. + // ++ static submodules ++ find_submodules (const common_options& co, ++ const dir_path& dir, ++ const dir_path& prefix, ++ bool gitmodules = true) ++ { ++ tracer trace ("find_submodules"); ++ ++ submodules r; ++ ++ if (gitmodules && !exists (dir / gitmodules_file)) ++ return r; ++ ++ auto failure = [&prefix] (const string& d, const exception* e = nullptr) ++ { ++ submodule_failure (d, prefix, e); ++ }; ++ ++ // Use git-config to obtain the submodules names/paths and then ++ // git-ls-files to obtain their commits. ++ // ++ // Note that previously we used git-submodule--helper-list subcommand to ++ // obtain the submodules commits/paths and then git-submodule--helper-name ++ // to obtain their names. However, git 2.38 has removed these subcommands. ++ ++ // Obtain the submodules names/paths. ++ // ++ for (;;) // Breakout loop. ++ { ++ fdpipe pipe (open_pipe ()); ++ ++ process pr (start_git (co, ++ pipe, 2 /* stderr */, ++ co.git_option (), ++ "-C", dir, ++ "config", ++ "--list", ++ "--file", gitmodules_file, ++ "-z")); ++ ++ // Shouldn't throw, unless something is severely damaged. ++ // ++ pipe.out.close (); ++ ++ try ++ { ++ ifdstream is (move (pipe.in), fdstream_mode::skip, ifdstream::badbit); ++ ++ for (string l; !eof (getline (is, l, '\0')); ) ++ { ++ auto bad = [&l] () ++ { ++ throw runtime_error ("invalid submodule option '" + l + "'"); ++ }; ++ ++ // The submodule configuration option line is NULL-terminated and ++ // has the following form: ++ // ++ // submodule.. ++ // ++ // For example: ++ // ++ // submodule.style.path ++ // doc/style ++ // ++ l4 ([&]{trace << "submodule option: " << l;}); ++ ++ // If this is a submodule path option, then extract its name and ++ // path and add the entry to the resulting list. ++ // ++ size_t n (l.find ('\n')); ++ ++ if (n != string::npos && ++ n >= 15 && ++ l.compare (0, 10, "submodule.") == 0 && ++ l.compare (n - 5, 5, ".path") == 0) ++ { ++ string nm (l, 10, n - 15); ++ dir_path p (l, n + 1, l.size () - n - 1); ++ ++ // For good measure verify that the name and path are not empty. ++ // ++ if (nm.empty () || p.empty ()) ++ bad (); ++ ++ r.push_back (submodule {move (p), move (nm), empty_string}); ++ } ++ } ++ ++ is.close (); ++ ++ if (pr.wait ()) ++ break; ++ ++ // Fall through. ++ } ++ catch (const invalid_path& e) ++ { ++ if (pr.wait ()) ++ failure ("invalid submodule directory path '" + e.path + "'"); ++ ++ // Fall through. ++ } ++ catch (const io_error& e) ++ { ++ if (pr.wait ()) ++ failure ("unable to read submodule options", &e); ++ ++ // Fall through. ++ } ++ // Note that the io_error class inherits from the runtime_error class, ++ // so this catch-clause must go last. ++ // ++ catch (const runtime_error& e) ++ { ++ if (pr.wait ()) ++ failure (e.what ()); ++ ++ // Fall through. ++ } ++ ++ // We should only get here if the child exited with an error status. ++ // ++ assert (!pr.wait ()); ++ ++ failure ("unable to list submodule options"); ++ } ++ ++ // Note that we could potentially bail out here if the submodules list is ++ // empty. Let's however continue and verify that via git-ls-files, for ++ // good measure. ++ ++ // Complete the resulting submodules information with their commits. ++ // ++ for (;;) // Breakout loop. ++ { ++ fdpipe pipe (open_pipe ()); ++ ++ process pr (start_git (co, ++ pipe, 2 /* stderr */, ++ co.git_option (), ++ "-C", dir, ++ "ls-files", ++ "--stage", ++ "-z")); ++ ++ // Shouldn't throw, unless something is severely damaged. ++ // ++ pipe.out.close (); ++ ++ try ++ { ++ ifdstream is (move (pipe.in), fdstream_mode::skip, ifdstream::badbit); ++ ++ for (string l; !eof (getline (is, l, '\0')); ) ++ { ++ auto bad = [&l] () ++ { ++ throw runtime_error ("invalid file description '" + l + "'"); ++ }; ++ ++ // The line describing a file is NULL-terminated and has the ++ // following form: ++ // ++ // ++ // ++ // The mode is a 6-digit octal representation of the file type and ++ // permission bits mask. For a submodule directory it is 160000 (see ++ // git index format documentation for gitlink object type). For ++ // example: ++ // ++ // 160000 59dcc1bea3509e37b65905ac472f86f4c55eb510 0 doc/style ++ // ++ if (!(l.size () > 50 && l[48] == '0' && l[49] == '\t')) ++ bad (); ++ ++ // For submodules permission bits are always zero, so we can match ++ // the mode as a string. ++ // ++ if (l.compare (0, 6, "160000") == 0) ++ { ++ l4 ([&]{trace << "submodule: " << l;}); ++ ++ dir_path d (l, 50, l.size () - 50); ++ ++ auto i (find_if (r.begin (), r.end (), ++ [&d] (const submodule& sm) {return sm.path == d;})); ++ ++ if (i == r.end ()) ++ bad (); ++ ++ i->commit = string (l, 7, 40); ++ } ++ } ++ ++ is.close (); ++ ++ if (pr.wait ()) ++ break; ++ ++ // Fall through. ++ } ++ catch (const invalid_path& e) ++ { ++ if (pr.wait ()) ++ failure ("invalid submodule directory path '" + e.path + "'"); ++ ++ // Fall through. ++ } ++ catch (const io_error& e) ++ { ++ if (pr.wait ()) ++ failure ("unable to read repository file list", &e); ++ ++ // Fall through. ++ } ++ // Note that the io_error class inherits from the runtime_error class, ++ // so this catch-clause must go last. ++ // ++ catch (const runtime_error& e) ++ { ++ if (pr.wait ()) ++ failure (e.what ()); ++ ++ // Fall through. ++ } ++ ++ // We should only get here if the child exited with an error status. ++ // ++ assert (!pr.wait ()); ++ ++ failure ("unable to list repository files"); ++ } ++ ++ // Make sure that we have deduced commits for all the submodules. ++ // ++ for (const submodule& sm: r) ++ { ++ if (sm.commit.empty ()) ++ failure ("unable to deduce commit for submodule " + sm.name); ++ } ++ ++ return r; ++ } ++ ++ // @@ TMP Old, submodule--helper-{list,name} subcommands-based, ++ // implementation of find_submodules(). ++ // ++#if 0 + static submodules + find_submodules (const common_options& co, + const dir_path& dir, +@@ -1792,6 +2042,7 @@ namespace bpkg + + submodule_failure ("unable to list submodules", prefix); + } ++#endif + + // Return commit id for the submodule directory or nullopt if the submodule + // is not initialized (directory doesn't exist, doesn't contain .git entry, +@@ -1839,13 +2090,15 @@ namespace bpkg + co.git_option (), + "-C", dir, + +- // Note that older git versions don't recognize the --super-prefix +- // option but seem to behave correctly without any additional +- // efforts when it is omitted. ++ // Note that git versions outside the [2.14.0 2.38.0) range don't ++ // recognize the --super-prefix option but seem to behave correctly ++ // without any additional efforts when it is omitted. + // +- !prefix.empty () && git_ver >= semantic_version {2, 14, 0} +- ? strings ({"--super-prefix", prefix.posix_representation ()}) +- : strings (), ++ (!prefix.empty () && ++ git_ver >= semantic_version {2, 14, 0} && ++ git_ver < semantic_version {2, 38, 0} ++ ? strings ({"--super-prefix", prefix.posix_representation ()}) ++ : strings ()), + + "submodule--helper", "init", + verb < 2 ? "-q" : nullptr)) +@@ -2188,7 +2441,7 @@ namespace bpkg + + for (string l; !eof (getline (is, l, '\0')); ) + { +- // The line describing a file is NUL-terminated and has the following ++ // The line describing a file is NULL-terminated and has the following + // form: + // + // +@@ -2198,8 +2451,6 @@ namespace bpkg + // + // 100644 165b42ec7a10fb6dd4a60b756fa1966c1065ef85 0 README + // +- l4 ([&]{trace << "file: " << l;}); +- + if (!(l.size () > 50 && l[48] == '0' && l[49] == '\t')) + throw runtime_error ("invalid file description '" + l + "'"); + +@@ -2207,7 +2458,11 @@ namespace bpkg + // mode as a string. + // + if (l.compare (0, 6, "120000") == 0) ++ { ++ l4 ([&]{trace << "symlink: " << l;}); ++ + r.push_back (make_pair (path (string (l, 50)), string (l, 7, 40))); ++ } + } + + is.close (); diff --git a/build2.spec b/build2.spec index 56f6964..02d9765 100644 --- a/build2.spec +++ b/build2.spec @@ -32,6 +32,12 @@ Source101: https://pkg.cppget.org/1/beta/odb/libodb-sqlite-%{libodb_bundle_ # driver.cxx:(.text+0x88): unresolvable R_PPC64_REL24 against `_ZGIW3foo4coreEv' # /usr/bin/ld: final link failed: bad value Patch0100: build2-disable-test-cc-modules-ppc64le.patch +# Upstream https://git.build2.org/cgit/build2/commit/?id=343d6e69e412166cfc21f268a51b692cb0201653 +Patch0000: libbuild2-libpkgconf-error_handler-non-const-data.patch +# Upstream https://git.build2.org/cgit/build2/commit/?id=417be15231cb34a2e858d26b63406d1fb5535cb9 +Patch0001: libbuild2-cxx23-aligned_storage-deprecation.patch +# Upstream https://git.build2.org/cgit/bpkg/commit/?id=a97b12a027546b37f66d3e08064f92f5539cf79e +Patch3000: bpkg-git-v2.38.patch BuildRequires: gcc-c++ BuildRequires: libpkgconf-devel @@ -263,11 +269,16 @@ This package contains the %{name} RPM macros. %else %setup -q -c -n %{name}-toolchain-%{version} -a 1 -a 2 -a 3 -a 4 -a 100 -a 101 %endif -%ifarch ppc64le pushd %{name}-%{version} +%ifarch ppc64le %patch -p 1 -P 0100 -popd %endif +%patch -p 1 -P 0000 +%patch -p 1 -P 0001 +popd +pushd bpkg-%{version} +%patch -p 1 -P 3000 +popd mv libbutl-%{version} %{name}-%{version} %build diff --git a/libbuild2-cxx23-aligned_storage-deprecation.patch b/libbuild2-cxx23-aligned_storage-deprecation.patch new file mode 100644 index 0000000..939b70b --- /dev/null +++ b/libbuild2-cxx23-aligned_storage-deprecation.patch @@ -0,0 +1,175 @@ +From 417be15231cb34a2e858d26b63406d1fb5535cb9 Mon Sep 17 00:00:00 2001 +From: Boris Kolpackov +Date: Thu, 2 Mar 2023 15:38:15 +0200 +Subject: Replace deprecated std::aligned_storage with alignas + +Based on patch by Matthew Krupcale. +--- + libbuild2/function.hxx | 9 +++++---- + libbuild2/scheduler.hxx | 5 +++-- + libbuild2/target.hxx | 8 ++++---- + libbuild2/variable.cxx | 10 +++++----- + libbuild2/variable.hxx | 7 ++++--- + 5 files changed, 21 insertions(+), 18 deletions(-) + +diff --git a/libbuild2/function.hxx b/libbuild2/function.hxx +index 323ac41..cda856a 100644 +--- a/libbuild2/function.hxx ++++ b/libbuild2/function.hxx +@@ -4,8 +4,9 @@ + #ifndef LIBBUILD2_FUNCTION_HXX + #define LIBBUILD2_FUNCTION_HXX + +-#include // index_sequence +-#include // aligned_storage ++#include // max_align_t ++#include // index_sequence ++#include // is_* + + #include + #include +@@ -133,8 +134,8 @@ namespace build2 + // Auxiliary data storage. Note that it is expected to be trivially + // copyable and destructible. + // +- std::aligned_storage::type data; +- static const size_t data_size = sizeof (decltype (data)); ++ static const size_t data_size = sizeof (void*) * 3; ++ alignas (std::max_align_t) unsigned char data[data_size]; + + function_overload (const char* an, + size_t mi, size_t ma, types ts, +diff --git a/libbuild2/scheduler.hxx b/libbuild2/scheduler.hxx +index c34d41b..b579d80 100644 +--- a/libbuild2/scheduler.hxx ++++ b/libbuild2/scheduler.hxx +@@ -7,7 +7,8 @@ + #include + #include + #include +-#include // aligned_storage, etc ++#include // max_align_t ++#include // decay, etc + + #include + #include +@@ -681,7 +682,7 @@ namespace build2 + // + struct task_data + { +- std::aligned_storage::type data; ++ alignas (std::max_align_t) unsigned char data[sizeof (void*) * 8]; + void (*thunk) (scheduler&, lock&, void*); + }; + +diff --git a/libbuild2/target.hxx b/libbuild2/target.hxx +index 26c7208..037b18c 100644 +--- a/libbuild2/target.hxx ++++ b/libbuild2/target.hxx +@@ -4,8 +4,9 @@ + #ifndef LIBBUILD2_TARGET_HXX + #define LIBBUILD2_TARGET_HXX + ++#include // max_align_t + #include // tags, etc. +-#include // aligned_storage ++#include // is_* + #include + + #include // map_iterator_adapter +@@ -189,7 +190,7 @@ namespace build2 + ? sizeof (string) + : sizeof (void*) * 4); + +- std::aligned_storage::type data_; ++ alignas (std::max_align_t) unsigned char data_[data_size]; + void (*data_dtor_) (void*) = nullptr; + + template ::type m_; ++ alignas (value_type) mutable unsigned char m_[sizeof (value_type)]; + }; + + iterator +diff --git a/libbuild2/variable.cxx b/libbuild2/variable.cxx +index 260d664..d55737b 100644 +--- a/libbuild2/variable.cxx ++++ b/libbuild2/variable.cxx +@@ -3,7 +3,7 @@ + + #include + +-#include // memcmp() ++#include // memcmp(), memcpy() + + #include + +@@ -57,7 +57,7 @@ namespace build2 + else if (type->copy_ctor != nullptr) + type->copy_ctor (*this, v, true); + else +- data_ = v.data_; // Copy as POD. ++ memcpy (data_, v.data_, size_); // Copy as POD. + } + } + +@@ -72,7 +72,7 @@ namespace build2 + else if (type->copy_ctor != nullptr) + type->copy_ctor (*this, v, false); + else +- data_ = v.data_; // Copy as POD. ++ memcpy (data_, v.data_, size_); // Copy as POD. + } + } + +@@ -106,7 +106,7 @@ namespace build2 + else if (auto f = null ? type->copy_ctor : type->copy_assign) + f (*this, v, true); + else +- data_ = v.data_; // Assign as POD. ++ memcpy (data_, v.data_, size_); // Assign as POD. + + null = v.null; + } +@@ -145,7 +145,7 @@ namespace build2 + else if (auto f = null ? type->copy_ctor : type->copy_assign) + f (*this, v, false); + else +- data_ = v.data_; // Assign as POD. ++ memcpy (data_, v.data_, size_); // Assign as POD. + + null = v.null; + } +diff --git a/libbuild2/variable.hxx b/libbuild2/variable.hxx +index 8a0adf8..b137789 100644 +--- a/libbuild2/variable.hxx ++++ b/libbuild2/variable.hxx +@@ -4,7 +4,8 @@ + #ifndef LIBBUILD2_VARIABLE_HXX + #define LIBBUILD2_VARIABLE_HXX + +-#include // aligned_storage ++#include // max_align_t ++#include // is_* + #include + + #include +@@ -423,8 +424,8 @@ namespace build2 + // specialization below). Types that don't fit will have to be handled + // with an extra dynamic allocation. + // +- static constexpr size_t size_ = sizeof (name_pair); +- std::aligned_storage::type data_; ++ static constexpr size_t size_ = sizeof (name_pair); ++ alignas (std::max_align_t) unsigned char data_[size_]; + + // Make sure we have sufficient storage for untyped values. + // +-- +cgit v1.1 + diff --git a/libbuild2-libpkgconf-error_handler-non-const-data.patch b/libbuild2-libpkgconf-error_handler-non-const-data.patch new file mode 100644 index 0000000..d309c26 --- /dev/null +++ b/libbuild2-libpkgconf-error_handler-non-const-data.patch @@ -0,0 +1,35 @@ +From 343d6e69e412166cfc21f268a51b692cb0201653 Mon Sep 17 00:00:00 2001 +From: Boris Kolpackov +Date: Thu, 2 Mar 2023 11:18:59 +0200 +Subject: Adapt to interface changes in libpkgconf 1.9 + +Patch by Matthew Krupcale. +--- + libbuild2/cc/pkgconfig-libpkgconf.cxx | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/libbuild2/cc/pkgconfig-libpkgconf.cxx b/libbuild2/cc/pkgconfig-libpkgconf.cxx +index 81a96c3..f3754d3 100644 +--- a/libbuild2/cc/pkgconfig-libpkgconf.cxx ++++ b/libbuild2/cc/pkgconfig-libpkgconf.cxx +@@ -81,10 +81,17 @@ namespace build2 + #endif + ; + ++#if defined(LIBPKGCONF_VERSION) && LIBPKGCONF_VERSION >= 10900 ++ static bool ++ pkgconf_error_handler (const char* msg, ++ const pkgconf_client_t*, ++ void*) ++#else + static bool + pkgconf_error_handler (const char* msg, + const pkgconf_client_t*, + const void*) ++#endif + { + error << runtime_error (msg); // Sanitize the message (trailing dot). + return true; +-- +cgit v1.1 +