public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/mcrouter] rawhide: Build with getdeps and vendored dependencies via %getdeps_* macros
@ 2026-09-25 7:33 Michel Lind
0 siblings, 0 replies; only message in thread
From: Michel Lind @ 2026-09-25 7:33 UTC (permalink / raw)
To: git-commits
A new commit has been pushed.
Repo : rpms/mcrouter
Branch : rawhide
Commit : 83f92333b257226c96a37f8dad92d4b6d12a6d65
Author : Michel Lind <salimma@fedoraproject.org>
Date : 2026-09-25T08:30:01+01:00
Stats : +821/-240 in 13 file(s)
URL : https://src.fedoraproject.org/rpms/mcrouter/c/83f92333b257226c96a37f8dad92d4b6d12a6d65?branch=rawhide
Log:
Build with getdeps and vendored dependencies via %getdeps_* macros
- Update to snapshot d8b07b00, one commit past v2026.09.21.00 and the
first to ship build/fbcode_builder; the build now goes through
getdeps, vendoring folly, fizz, wangle, mvfst, fbthrift and liboqs
instead of requiring the retired Fedora packages of the Meta stack
- Ship the mcrouter and mcpiper executables statically linked; nothing
else (no libraries or headers)
- Re-enable ppc64le: the folly F14 fallback ambiguity behind
rhbz#2344416 is fixed by a carried patch and the scratch build passes
- Version is the upstream weekly tag, with ^<distance>.<shortcommit>
appended for a snapshot; pass it to CMake as MCROUTER_PACKAGE_VERSION,
which the CMake conversion had left at "0.1.0-dev"
- Declare SourceLicense; the License tag lists the vendored projects'
licenses and is verified against the vendored tree in %check
- Add vendor.sh and snapshot.sh; drop the autotools-era distutils patch
The autotools spec built against folly-devel, fizz-devel, wangle-devel and
fbthrift-devel pinned to one upstream tag, which is why the package was
retired with the rest of the stack. Upstream's getdeps.py can now vendor
the dependencies it cannot take from the system and build offline from
that tree, so the spec drives it through the %%getdeps_* macros in
folly-rpm-macros 46, the same way as cachelib: BuildRequires generated
from the getdeps manifests, the vendored trees from Source1 (produced by
./vendor.sh, recorded in vendor/getdeps-vendor.txt), bundled() Provides
for each, a DESTDIR install of getdeps' build directory with the
libraries, headers and CMake config pruned. ragel is the only system
package the old spec did not already need.
mcrouter ships no build/deps/github_hashes yet, so the vendored trees are
each project's main at the time ./vendor.sh ran; the tarball's manifest
records the exact commits (folly 5060f891, fizz a94be934, wangle
deeb66af, mvfst 614035f7, fbthrift 2e1a4623). Pins are being added
upstream, after which the spec switches to the weekly tag.
Patches, all upstream or submitted: the vendored folly against OpenSSL
4.0 (facebook/folly#2706; wangle's counterpart, facebook/wangle#254, has
landed and is not carried), fbthrift's THRIFT_DATA_MEMBER section moved
to .data.rel.ro (facebook/fbthrift#712, landed and reverted over an
unrelated internal size limit; without it every object gets an RWX
segment that --error-rwx-segments refuses), folly's F14 fallback
forwarding exact-key lookups instead of using-declarations that collide
with libstdc++ 16's heterogeneous overloads (the ppc64le fix), mcrouter
itself against current folly (explicit gflags includes) and Boost 1.90
(filesystem/convenience.hpp and complete() removed), and getdeps
recording the checked-out commit rather than "main" in
getdeps-vendor.txt.
Tests stay disabled (%%bcond_with check) as before. A koji scratch build
of this SRPM passed on x86_64, aarch64 and ppc64le.
Assisted-by: Claude Code:claude-fable-5-1
Signed-off-by: Michel Lind <salimma@fedoraproject.org>
(cherry picked from commit 3892472c6c58cf63369b0865abad695c8d12f2d6)
---
diff --git a/.gitignore b/.gitignore
index 650bc0b..a97404d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
/mcrouter-????.??.??.00.tar.gz
+/mcrouter-2026.09.21.00^1.d8b07b0-vendor.tar.xz
+/mcrouter-2026.09.21.00^1.d8b07b0.tar.gz
diff --git a/0001-folly-build-against-OpenSSL-4.0.patch b/0001-folly-build-against-OpenSSL-4.0.patch
new file mode 100644
index 0000000..6eea3a3
--- /dev/null
+++ b/0001-folly-build-against-OpenSSL-4.0.patch
@@ -0,0 +1,105 @@
+diff --git a/vendor/folly/folly/io/async/ssl/OpenSSLUtils.cpp b/vendor/folly/folly/io/async/ssl/OpenSSLUtils.cpp
+index 4ece63edd..6f39c52f5 100644
+--- a/vendor/folly/folly/io/async/ssl/OpenSSLUtils.cpp
++++ b/vendor/folly/folly/io/async/ssl/OpenSSLUtils.cpp
+@@ -122,9 +122,11 @@ bool OpenSSLUtils::validatePeerCertNames(
+ for (int i = 0; i < sk_GENERAL_NAME_num(altNames); i++) {
+ auto name = sk_GENERAL_NAME_value(altNames, i);
+ if ((addr4 != nullptr || addr6 != nullptr) && name->type == GEN_IPADD) {
+- // Extra const-ness for paranoia
+- unsigned char const* const rawIpStr = name->d.iPAddress->data;
+- auto const rawIpLen = size_t(name->d.iPAddress->length);
++ // ASN1_STRING is opaque since OpenSSL 4.0; use the accessors, which
++ // work on all supported versions.
++ unsigned char const* const rawIpStr =
++ ASN1_STRING_get0_data(name->d.iPAddress);
++ auto const rawIpLen = size_t(ASN1_STRING_length(name->d.iPAddress));
+
+ if (rawIpLen == 4 && addr4 != nullptr) {
+ if (::memcmp(rawIpStr, &addr4->sin_addr, rawIpLen) == 0) {
+@@ -285,7 +287,9 @@ std::string OpenSSLUtils::getCommonName(X509* x509) {
+ if (x509 == nullptr) {
+ return "";
+ }
+- X509_NAME* subject = X509_get_subject_name(x509);
++ // X509_get_subject_name() returns const X509_NAME* since OpenSSL 4.0;
++ // auto keeps this compiling on older versions too.
++ auto subject = X509_get_subject_name(x509);
+ char buf[ub_common_name + 1];
+ int length =
+ X509_NAME_get_text_by_NID(subject, NID_commonName, buf, sizeof(buf));
+diff --git a/vendor/folly/folly/ssl/OpenSSLCertUtils.cpp b/vendor/folly/folly/ssl/OpenSSLCertUtils.cpp
+index 67a066d3a..b699e3b98 100644
+--- a/vendor/folly/folly/ssl/OpenSSLCertUtils.cpp
++++ b/vendor/folly/folly/ssl/OpenSSLCertUtils.cpp
+@@ -33,7 +33,7 @@ std::string getOpenSSLErrorString(unsigned long err) {
+ return std::string(errBuff.data());
+ }
+
+-std::string asn1ToString(ASN1_STRING* a) {
++std::string asn1ToString(const ASN1_STRING* a) {
+ auto strType = ASN1_STRING_type(a);
+ if (strType == V_ASN1_UTF8STRING || strType == V_ASN1_OCTET_STRING) {
+ long len = ASN1_STRING_length(a);
+@@ -90,9 +90,12 @@ std::optional<GeneralName> getSubjectAltName(const GENERAL_NAME& name) {
+ return std::nullopt;
+ }
+
+-std::string getExtOid(X509_EXTENSION* extension) {
++std::string getExtOid(const X509_EXTENSION* extension) {
+ CHECK_NOTNULL(extension);
+- ASN1_OBJECT* object = X509_EXTENSION_get_object(extension);
++ // X509_EXTENSION_get_object() takes a non-const parameter before
++ // OpenSSL 4.0; the cast is a no-op there.
++ const ASN1_OBJECT* object =
++ X509_EXTENSION_get_object(const_cast<X509_EXTENSION*>(extension));
+ // Query for extension OID
+ constexpr int buf_size = 256;
+ std::string ret(buf_size, '\0');
+@@ -107,18 +110,24 @@ std::string getExtOid(X509_EXTENSION* extension) {
+ return ret;
+ }
+
+-std::string getExtData(X509_EXTENSION* extension) {
++std::string getExtData(const X509_EXTENSION* extension) {
+ CHECK_NOTNULL(extension);
+- auto asnValue = X509_EXTENSION_get_data(extension);
++ // X509_EXTENSION_get_data() takes a non-const parameter before
++ // OpenSSL 4.0; the cast is a no-op there.
++ auto asnValue =
++ X509_EXTENSION_get_data(const_cast<X509_EXTENSION*>(extension));
+ return asnValue ? asn1ToString(asnValue) : std::string();
+ }
+
+-Optional<std::string> commonName(X509_NAME* name) {
++Optional<std::string> commonName(const X509_NAME* name) {
+ if (!name) {
+ return none;
+ }
+
+- auto cnLoc = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
++ // X509_NAME_get_index_by_NID() takes a non-const parameter before
++ // OpenSSL 3.0; the cast is a no-op there.
++ auto cnLoc = X509_NAME_get_index_by_NID(
++ const_cast<X509_NAME*>(name), NID_commonName, -1);
+ if (cnLoc < 0) {
+ return none;
+ }
+@@ -276,7 +285,7 @@ std::vector<std::string> OpenSSLCertUtils::getExtension(
+ const X509& x509, folly::StringPiece oid) {
+ std::vector<std::string> extValues;
+ for (int i = 0; i < X509_get_ext_count(&x509); i++) {
+- X509_EXTENSION* extension = X509_get_ext(&x509, i);
++ const X509_EXTENSION* extension = X509_get_ext(&x509, i);
+ std::string extensionOid = getExtOid(extension);
+ if (extensionOid == oid) {
+ extValues.push_back(getExtData(extension));
+@@ -289,7 +298,7 @@ std::vector<std::pair<std::string, std::string>>
+ OpenSSLCertUtils::getAllExtensions(const X509& x509) {
+ std::vector<std::pair<std::string, std::string>> extensions;
+ for (int i = 0; i < X509_get_ext_count(&x509); i++) {
+- X509_EXTENSION* extension = X509_get_ext(&x509, i);
++ const X509_EXTENSION* extension = X509_get_ext(&x509, i);
+ std::string oid = getExtOid(extension);
+ std::string value = getExtData(extension);
+ extensions.push_back(std::make_pair(oid, value));
diff --git a/0003-fbthrift-keep-thrift-data-out-of-a-writable-rodata-section.patch b/0003-fbthrift-keep-thrift-data-out-of-a-writable-rodata-section.patch
new file mode 100644
index 0000000..55a0760
--- /dev/null
+++ b/0003-fbthrift-keep-thrift-data-out-of-a-writable-rodata-section.patch
@@ -0,0 +1,46 @@
+From 8f02f06da08cfcb33a029173838a381e41fe60da Mon Sep 17 00:00:00 2001
+From: Michel Lind <salimma@fedoraproject.org>
+Date: Fri, 18 Sep 2026 16:15:54 +0100
+Subject: [PATCH] cpp2: keep TStructDataStorage members out of a writable
+ .rodata section
+
+THRIFT_DATA_MEMBER places every TStructDataStorage<T> member in
+".rodata.thrift.data" so the linker cannot garbage-collect the unused
+ones. Some of those members (name, fields_names) hold string_views, i.e.
+pointers that need relocations, so in a -fPIC or -fPIE build the compiler
+has to make that section writable (the assembler warns "setting incorrect
+section attributes for .rodata.thrift.data"). The linker then merges a
+writable .rodata into the text segment and the resulting shared object
+or PIE has a single RWX LOAD segment. On aarch64, where -z separate-code
+is not the default, glibc's loader crashes on such an object when it also
+carries a BTI GNU_PROPERTY note (SIGSEGV in _dl_setup_hash), so every
+shared library that links thrift-generated code was unloadable; with
+binutils' --error-rwx-segments, as Fedora now passes by default, the
+link fails outright.
+
+Name the section .data.rel.ro.thrift.data instead: it still groups the
+members so gc-sections cannot strip them, and RELRO is the right home for
+constant data that carries relocations.
+
+Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
+Signed-off-by: Michel Lind <salimma@fedoraproject.org>
+---
+ thrift/lib/cpp2/gen/module_data_cpp.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/vendor/fbthrift/thrift/lib/cpp2/gen/module_data_cpp.h b/vendor/fbthrift/thrift/lib/cpp2/gen/module_data_cpp.h
+index af62970c81..6f41948cc7 100644
+--- a/vendor/fbthrift/thrift/lib/cpp2/gen/module_data_cpp.h
++++ b/vendor/fbthrift/thrift/lib/cpp2/gen/module_data_cpp.h
+@@ -32,7 +32,7 @@
+ // is then unable to remove unused data without also removing used data.
+ // This has a similar effect to the "retain" attribute, but works with older
+ // toolchains.
+-#define THRIFT_DATA_MEMBER [[gnu::used]] [[gnu::section(".rodata.thrift.data")]]
++#define THRIFT_DATA_MEMBER [[gnu::used]] [[gnu::section(".data.rel.ro.thrift.data")]]
+ #else
+ #define THRIFT_DATA_MEMBER
+ #endif
+--
+2.55.0
+
diff --git a/0004-folly-F14-fallback-forward-exact-key-lookups.patch b/0004-folly-F14-fallback-forward-exact-key-lookups.patch
new file mode 100644
index 0000000..850a7b1
--- /dev/null
+++ b/0004-folly-F14-fallback-forward-exact-key-lookups.patch
@@ -0,0 +1,117 @@
+From 4193514ebc75c8d36a606505b18e266a9643fc28 Mon Sep 17 00:00:00 2001
+From: Michel Lind <salimma@fedoraproject.org>
+Date: Fri, 18 Sep 2026 19:14:04 +0100
+Subject: [PATCH] F14 fallback: forward exact-key lookups instead of
+ using-declarations
+
+F14SetFallback and F14MapFallback derive from std::unordered_set/map and
+add heterogeneous find/count/contains/equal_range templates next to
+`using Super::find;` and friends. Since C++20 (P0919R3, P1690R1) the
+standard containers have heterogeneous overloads of the same shape,
+enabled whenever the hasher and key_equal are transparent, which
+folly's defaults are. With libstdc++ from GCC 16 the using-declaration
+then brings in a second viable template and every heterogeneous lookup
+is ambiguous:
+
+ folly/container/EvictingCacheMap.h:765:26: error: call of overloaded
+ 'find(const long unsigned int&)' is ambiguous
+ candidate 1: std::unordered_set<...>::find(const _Kt&) const
+ /usr/include/c++/16/bits/unordered_set.h:790:9
+ candidate 2: folly::f14::detail::F14BasicSet<...>::find(K const&) const
+ folly/container/detail/F14SetFallback.h:266:46
+ folly/container/detail/F14SetFallback.h:274:16: error: call of
+ overloaded 'find(const std::basic_string_view<char>&)' is ambiguous
+ (from Immutables.cpp:40 globalFrozenSettingProjects().rlock()->contains(project))
+
+Only the fallback is affected, i.e. targets without SSE2 or NEON such as
+ppc64le, which is where the Fedora build of CacheLib failed:
+https://koji.fedoraproject.org/koji/taskinfo?taskID=150370573
+(folly at d8d3f3f6, gcc-16.2.1-2.fc46, libstdc++ 16, -std=gnu++20).
+
+Replace the using-declarations with exact-key_type overloads that
+forward to Super, which hide the base class's templates. F14MapFallback
+already did this for find, count and contains and only had equal_range
+via using-declaration; F14SetFallback had all of count, find and
+equal_range via using-declarations. contains was already forwarded in
+both, which is why it never appeared in the errors on its own.
+
+Verified with GCC 16.2.1 on aarch64 by forcing the fallback:
+
+ g++ -std=gnu++20 -fsyntax-only -DFOLLY_F14_FORCE_FALLBACK=1 t.cpp
+
+where t.cpp exercises heterogeneous find/contains/equal_range on
+F14FastSet<std::string> and F14FastMap<std::string, int> with a
+string_view key, the exact-key overloads on const and non-const
+containers, and the F14HashToken find path. Before: 4 ambiguity errors
+(and the same failure inside F14SetFallback.h's contains). After: none,
+with or without the forced fallback.
+
+Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
+Signed-off-by: Michel Lind <salimma@fedoraproject.org>
+---
+ folly/container/detail/F14MapFallback.h | 9 ++++++++-
+ folly/container/detail/F14SetFallback.h | 15 ++++++++++++---
+ 2 files changed, 20 insertions(+), 4 deletions(-)
+
+diff --git a/vendor/folly/folly/container/detail/F14MapFallback.h b/vendor/folly/folly/container/detail/F14MapFallback.h
+index b6fcaec99..9513954e9 100644
+--- a/vendor/folly/folly/container/detail/F14MapFallback.h
++++ b/vendor/folly/folly/container/detail/F14MapFallback.h
+@@ -427,7 +427,14 @@ class F14BasicMap : public std::unordered_map<K, M, H, E, A> {
+ }
+
+ public:
+- using Super::equal_range;
++ std::pair<iterator, iterator> equal_range(key_type const& key) {
++ return Super::equal_range(key);
++ }
++
++ std::pair<const_iterator, const_iterator> equal_range(
++ key_type const& key) const {
++ return Super::equal_range(key);
++ }
+
+ template <typename K2>
+ EnableHeterogeneousFind<K2, std::pair<iterator, iterator>> equal_range(
+diff --git a/vendor/folly/folly/container/detail/F14SetFallback.h b/vendor/folly/folly/container/detail/F14SetFallback.h
+index 623f6a60a..33b711b04 100644
+--- a/vendor/folly/folly/container/detail/F14SetFallback.h
++++ b/vendor/folly/folly/container/detail/F14SetFallback.h
+@@ -248,14 +248,16 @@ class F14BasicSet
+ }
+
+ public:
+- using Super::count;
++ size_type count(key_type const& key) const { return Super::count(key); }
+
+ template <typename K>
+ EnableHeterogeneousFind<K, size_type> count(K const& key) const {
+ return contains(key) ? 1 : 0;
+ }
+
+- using Super::find;
++ iterator find(key_type const& key) { return Super::find(key); }
++
++ const_iterator find(key_type const& key) const { return Super::find(key); }
+
+ template <typename K>
+ EnableHeterogeneousFind<K, iterator> find(K const& key) {
+@@ -286,7 +288,14 @@ class F14BasicSet
+ }
+
+ public:
+- using Super::equal_range;
++ std::pair<iterator, iterator> equal_range(key_type const& key) {
++ return Super::equal_range(key);
++ }
++
++ std::pair<const_iterator, const_iterator> equal_range(
++ key_type const& key) const {
++ return Super::equal_range(key);
++ }
+
+ template <typename K>
+ EnableHeterogeneousFind<K, std::pair<iterator, iterator>> equal_range(
+--
+2.55.0
+
diff --git a/0005-Build-against-current-folly-and-Boost-1.90.patch b/0005-Build-against-current-folly-and-Boost-1.90.patch
new file mode 100644
index 0000000..aa2a2d3
--- /dev/null
+++ b/0005-Build-against-current-folly-and-Boost-1.90.patch
@@ -0,0 +1,97 @@
+From: Michel Lind <salimma@fedoraproject.org>
+Date: Mon, 21 Sep 2026 19:30:00 +0100
+Subject: [PATCH] Build against current folly and Boost 1.90
+
+Two toolchain moves that mcrouter's own CI (Ubuntu 24.04 recipes) does
+not see yet:
+
+- folly's headers no longer include gflags transitively, so the files
+ that use DECLARE_bool/DEFINE_bool need <folly/portability/GFlags.h>
+ themselves:
+
+ mcrouter/lib/MessageQueue.h:21:13: error: expected constructor,
+ destructor, or type conversion before '(' token
+ mcrouter/lib/MessageQueue.h:377:11: error:
+ 'FLAGS_mcrouter_propagate_folly_request_context' was not declared
+
+- Boost 1.90 removed boost/filesystem/convenience.hpp and
+ boost::filesystem::complete; absolute() is the documented
+ replacement:
+
+ mcrouter/FileDataProvider.cpp:13:10: fatal error:
+ boost/filesystem/convenience.hpp: No such file or directory
+
+Found building mcrouter d8b07b00 with getdeps on Fedora Rawhide aarch64
+(GCC 16.2, Boost 1.90, folly main); with these, mcrouter and mcpiper
+build, link and start.
+
+Signed-off-by: Michel Lind <salimma@fedoraproject.org>
+Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
+---
+diff --git a/mcrouter/CarbonRouterInstance.cpp b/mcrouter/CarbonRouterInstance.cpp
+index e91b7cfe..b92e0476 100644
+--- a/mcrouter/CarbonRouterInstance.cpp
++++ b/mcrouter/CarbonRouterInstance.cpp
+@@ -17,6 +17,7 @@
+ #include "mcrouter/McrouterLogFailure.h"
+ #include "mcrouter/config.h"
+ #include "mcrouter/lib/RuntimeVarsData.h"
++#include <folly/portability/GFlags.h>
+
+ DEFINE_int32(
+ mcrouter_web_proxy_thread_niceness,
+diff --git a/mcrouter/FileDataProvider.cpp b/mcrouter/FileDataProvider.cpp
+index c48d5b7a..7d341017 100644
+--- a/mcrouter/FileDataProvider.cpp
++++ b/mcrouter/FileDataProvider.cpp
+@@ -10,15 +10,15 @@
+ #include <poll.h>
+ #include <sys/inotify.h>
+
+-#include <boost/filesystem/convenience.hpp>
+ #include <boost/filesystem/operations.hpp>
+ #include <boost/filesystem/path.hpp>
+ #include <glog/logging.h>
+
+ #include <folly/FileUtil.h>
+ #include <folly/Format.h>
++#include <folly/portability/GFlags.h>
+
+-using boost::filesystem::complete;
++using boost::filesystem::absolute;
+ using boost::filesystem::path;
+ using boost::filesystem::read_symlink;
+
+@@ -77,7 +77,7 @@ void FileDataProvider::updateInotifyWatch() {
+ break;
+ }
+ // We read a link
+- file = complete(file, link.parent_path());
++ file = absolute(file, link.parent_path());
+ std::swap(link, file);
+ }
+ inotify_ = std::move(tmpInotify);
+diff --git a/mcrouter/lib/MessageQueue.h b/mcrouter/lib/MessageQueue.h
+index 94e31190..4edba3b4 100644
+--- a/mcrouter/lib/MessageQueue.h
++++ b/mcrouter/lib/MessageQueue.h
+@@ -17,6 +17,7 @@
+ #include <folly/Random.h>
+ #include <folly/io/async/EventHandler.h>
+ #include <folly/io/async/VirtualEventBase.h>
++#include <folly/portability/GFlags.h>
+
+ DECLARE_bool(mcrouter_propagate_folly_request_context);
+
+diff --git a/mcrouter/lib/carbon/connection/ExternalCarbonConnectionImpl-inl.h b/mcrouter/lib/carbon/connection/ExternalCarbonConnectionImpl-inl.h
+index 3bea8f08..dcc313a3 100644
+--- a/mcrouter/lib/carbon/connection/ExternalCarbonConnectionImpl-inl.h
++++ b/mcrouter/lib/carbon/connection/ExternalCarbonConnectionImpl-inl.h
+@@ -19,6 +19,7 @@
+ #include "mcrouter/lib/carbon/ExternalCarbonConnectionStats.h"
+ #include "mcrouter/lib/network/ConnectionOptions.h"
+ #include "mcrouter/lib/network/Transport.h"
++#include <folly/portability/GFlags.h>
+
+ namespace carbon {
+ namespace detail {
diff --git a/0006-getdeps-record-the-checked-out-commit-in-getdeps-vendor.txt.patch b/0006-getdeps-record-the-checked-out-commit-in-getdeps-vendor.txt.patch
new file mode 100644
index 0000000..13366d7
--- /dev/null
+++ b/0006-getdeps-record-the-checked-out-commit-in-getdeps-vendor.txt.patch
@@ -0,0 +1,155 @@
+From: Michel Lind <salimma@fedoraproject.org>
+Date: Mon, 21 Sep 2026 20:10:00 +0100
+Subject: [PATCH] getdeps: record the checked-out commit in getdeps-vendor.txt
+
+`getdeps.py vendor` wrote fetcher.hash() next to each vendored project,
+which is the manifest's idea of the version: for a git project without a
+pinned rev that is the branch name, so a project that ships no
+build/deps/github_hashes (mcrouter) got
+
+ folly main
+ fizz main
+
+recorded, identifying nothing. Ask the checkout for HEAD instead, and
+keep hash() for fetchers that are not git checkouts (tarballs already
+record their content hash). A downstream consumer relies on this file to
+say which revision of each dependency it bundled.
+
+Signed-off-by: Michel Lind <salimma@fedoraproject.org>
+Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
+---
+ build/fbcode_builder/getdeps/cli.py | 28 ++++++++++++-
+ build/fbcode_builder/getdeps/test/vendor_test.py | 53 ++++++++++++++++++++++++
+ 2 files changed, 80 insertions(+), 1 deletion(-)
+
+diff --git a/build/fbcode_builder/getdeps/cli.py b/build/fbcode_builder/getdeps/cli.py
+index cbd4589f..2e209a6c 100644
+--- a/build/fbcode_builder/getdeps/cli.py
++++ b/build/fbcode_builder/getdeps/cli.py
+@@ -26,6 +26,7 @@ from .dyndeps import create_dyn_dep_munger
+ from .errors import TransientFailure
+ from .fetcher import (
+ file_name_is_cmake_file,
++ GitFetcher,
+ is_public_commit,
+ list_files_under_dir_newer_than_timestamp,
+ safe_extractall,
+@@ -260,7 +261,7 @@ class VendorCmd(ProjectCmdBase):
+ ignore=shutil.ignore_patterns(".git"),
+ ignore_dangling_symlinks=True,
+ )
+- vendored.append("%s %s\n" % (m.name, fetcher.hash()))
++ vendored.append("%s %s\n" % (m.name, _vendored_revision(fetcher)))
+ vendored_names.add(m.name)
+ # Drop trees recorded by a previous run that are no longer
+ # dependencies (e.g. after --allow-system-packages or --no-tests
+@@ -289,6 +290,31 @@ class VendorCmd(ProjectCmdBase):
+ f.writelines(vendored)
+
+
++def _vendored_revision(fetcher) -> str:
++ """The revision to record for a vendored tree.
++
++ fetcher.hash() is the manifest's idea of the version, which for a git
++ project without a pinned rev is a branch name ("main"); record the
++ commit that was actually checked out so the vendor manifest identifies
++ the sources. Falls back to hash() when there is no checkout to ask."""
++ if isinstance(fetcher, GitFetcher):
++ repo_dir = fetcher.get_src_dir()
++ if os.path.isdir(os.path.join(repo_dir, ".git")):
++ try:
++ return (
++ subprocess.check_output(
++ ["git", "rev-parse", "HEAD"],
++ cwd=repo_dir,
++ stderr=subprocess.DEVNULL,
++ )
++ .decode("utf-8")
++ .strip()
++ )
++ except (subprocess.CalledProcessError, OSError):
++ pass
++ return fetcher.hash()
++
++
+ @cmd("install-system-deps", "Install system packages to satisfy the deps for a project")
+ class InstallSysDepsCmd(ProjectCmdBase):
+ def setup_project_cmd_parser(self, parser):
+diff --git a/build/fbcode_builder/getdeps/test/vendor_test.py b/build/fbcode_builder/getdeps/test/vendor_test.py
+index 1d96fea6..69837de7 100644
+--- a/build/fbcode_builder/getdeps/test/vendor_test.py
++++ b/build/fbcode_builder/getdeps/test/vendor_test.py
+@@ -9,6 +9,7 @@ import contextlib
+ import io
+ import os
+ import shutil
++import subprocess
+ import tempfile
+ import unittest
+ from unittest.mock import MagicMock, patch
+@@ -16,6 +17,7 @@ from unittest.mock import MagicMock, patch
+ from ..buildopts import BuildOptions
+ from ..cli import VendorCmd
+ from ..fetcher import (
++ GitFetcher,
+ ChangeStatus,
+ LocalDirFetcher,
+ PreinstalledNopFetcher,
+@@ -119,6 +121,57 @@ class VendorCmdTest(unittest.TestCase):
+ with open(os.path.join(self.output_dir, "getdeps-vendor.txt")) as f:
+ self.assertEqual(f.read(), "depa %s\n" % ("a" * 40))
+
++ def test_records_checked_out_commit_for_git_projects(self) -> None:
++ # An unpinned git project has rev "main"; the manifest must name the
++ # commit that was actually vendored, not the branch.
++ build_opts = MagicMock()
++ build_opts.scratch_dir = self.tmp
++ fetcher = GitFetcher(
++ build_opts,
++ MagicMock(),
++ "https://example.invalid/depa.git",
++ rev=None,
++ depth=None,
++ branch="main",
++ )
++ repo = fetcher.get_src_dir()
++ os.makedirs(repo)
++ # independent of the developer's git config (identity, signing, hooks)
++ git = [
++ "git",
++ "-c",
++ "user.name=t",
++ "-c",
++ "user.email=t@t",
++ "-c",
++ "commit.gpgsign=false",
++ "-c",
++ "core.hooksPath=/dev/null",
++ ]
++ subprocess.check_call(git + ["init", "-q", "-b", "main"], cwd=repo)
++ subprocess.check_call(
++ git + ["commit", "-q", "--allow-empty", "-m", "x"], cwd=repo
++ )
++ head = (
++ subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=repo)
++ .decode()
++ .strip()
++ )
++ fetcher.update = lambda: ChangeStatus() # no network
++ self.assertEqual(fetcher.hash(), "main")
++
++ self.run_vendor(
++ [make_manifest("depa"), make_manifest("top")],
++ {
++ "depa": fetcher,
++ "top": FakeSourceFetcher(self.make_src_tree("top"), "t" * 40),
++ },
++ )
++
++ with open(os.path.join(self.output_dir, "getdeps-vendor.txt")) as f:
++ self.assertEqual(f.read(), "depa %s\n" % head)
++ self.assertEqual(len(head), 40)
++
+ def test_replaces_stale_vendored_tree(self) -> None:
+ stale = os.path.join(self.output_dir, "depa", "stale.txt")
+ os.makedirs(os.path.dirname(stale))
diff --git a/README.md b/README.md
index 68b7a30..de05b75 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,39 @@
# mcrouter
-The mcrouter package
+Fedora package of [mcrouter](https://github.com/facebook/mcrouter), built with
+its own `getdeps.py` via the `%getdeps_*` macros from folly-rpm-macros, the
+same way as cachelib (see that package's README for the details; the two
+share `vendor.sh`, `snapshot.sh` and the license configuration).
+
+Dependencies that Fedora packages come from the system; the `BuildRequires`
+for them are generated from the getdeps manifests at build time. The rest of
+the Meta stack (folly, fizz, wangle, mvfst, fbthrift) plus liboqs is vendored:
+`Source1` is a tarball of their sources. mcrouter ships no
+`build/deps/github_hashes`, so the vendored revisions are whatever each
+project's `main` was when `./vendor.sh` ran; `vendor/getdeps-vendor.txt` in
+the tarball records them.
+
+The package ships two statically linked executables, `mcrouter` and
+`mcpiper`, and nothing else: no libraries or headers (they would need the
+vendored folly and fbthrift headers, which Fedora does not ship).
+
+To update:
+
+1. Set `%global basetag vYYYY.MM.DD.00` to the weekly tag. For a tag build
+ that is all: `Version` is the tag without its `v`. For a snapshot past the
+ tag, also paste the `%global commit` and `%global commits` lines that
+ `./snapshot.sh [ref]` prints (`git describe --tags --match 'v20??.??.??.??'`
+ gives the same values from a clone); `Version` becomes
+ `<tag>^<distance>.<shortcommit>`.
+2. `./vendor.sh` to download `Source0` and produce the matching `Source1`,
+ with the generated BuildRequires installed so getdeps vendors exactly
+ what the build will look for.
+3. `fedpkg new-sources <Source0> <Source1>`.
+
+`getdeps-vendor-licenses.toml` configures the license scan of the vendored
+tree; regenerate the per-project breakdown behind the `License` tag with
+
+ awk '{ print "# " $1 " v" $2 }' vendor/getdeps-vendor.txt > vendor/modules.txt
+ go_vendor_license --config getdeps-vendor-licenses.toml report all -L
+
+from the unpacked source root with the vendor tarball extracted.
diff --git a/getdeps-vendor-licenses.toml b/getdeps-vendor-licenses.toml
new file mode 100644
index 0000000..e0645c1
--- /dev/null
+++ b/getdeps-vendor-licenses.toml
@@ -0,0 +1,94 @@
+# Configuration for %getdeps_vendor_license_check / _install (go-vendor-tools).
+# Shared with the cachelib package; keep the two in sync.
+# Paths are relative to the unpacked source tree.
+[licensing]
+detector = "askalono"
+# Not compiled into mcrouter: each Meta project's copy of the fbcode_builder
+# build scripts (MIT) and fbthrift's Go bindings. Excluding them keeps the License
+# tag to what the binaries actually contain.
+exclude_directories = [
+ "vendor/folly/build/fbcode_builder",
+ "vendor/fizz/build/fbcode_builder",
+ "vendor/wangle/build/fbcode_builder",
+ "vendor/mvfst/build/fbcode_builder",
+ "vendor/fbthrift/build/fbcode_builder",
+ "vendor/fbthrift/thrift/lib/go",
+ # liboqs is built with OQS_MINIMAL_BUILD limited to Kyber and ML-KEM (see
+ # the liboqs manifest); the other algorithm families are never compiled
+ "vendor/liboqs/liboqs-0.12.0/src/kem/bike",
+ "vendor/liboqs/liboqs-0.12.0/src/kem/classic_mceliece",
+ "vendor/liboqs/liboqs-0.12.0/src/kem/frodokem",
+ "vendor/liboqs/liboqs-0.12.0/src/kem/hqc",
+ "vendor/liboqs/liboqs-0.12.0/src/kem/ntruprime",
+ "vendor/liboqs/liboqs-0.12.0/src/sig/cross",
+ "vendor/liboqs/liboqs-0.12.0/src/sig/dilithium",
+ "vendor/liboqs/liboqs-0.12.0/src/sig/falcon",
+ "vendor/liboqs/liboqs-0.12.0/src/sig/mayo",
+ "vendor/liboqs/liboqs-0.12.0/src/sig/ml_dsa",
+ "vendor/liboqs/liboqs-0.12.0/src/sig/sphincs",
+ "vendor/liboqs/liboqs-0.12.0/src/sig_stfl/lms",
+ "vendor/liboqs/liboqs-0.12.0/src/sig_stfl/xmss",
+]
+
+# The pqcrystals Kyber/ML-KEM reference and AVX2 code carries a one-line
+# notice, "Public Domain (CC0) or Apache 2.0 License", that askalono does
+# not recognise. Same file in every variant; pinned by hash.
+[[licensing.licenses]]
+path = "vendor/liboqs/liboqs-0.12.0/src/kem/kyber/pqcrystals-kyber_kyber1024_avx2/LICENSE"
+sha256sum = "53681bce13fd98721b4cabcd0b6184c6a92d9de813a02536161cc706e4ea9f2e"
+expression = "CC0-1.0 OR Apache-2.0"
+
+[[licensing.licenses]]
+path = "vendor/liboqs/liboqs-0.12.0/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/LICENSE"
+sha256sum = "53681bce13fd98721b4cabcd0b6184c6a92d9de813a02536161cc706e4ea9f2e"
+expression = "CC0-1.0 OR Apache-2.0"
+
+[[licensing.licenses]]
+path = "vendor/liboqs/liboqs-0.12.0/src/kem/kyber/pqcrystals-kyber_kyber512_avx2/LICENSE"
+sha256sum = "53681bce13fd98721b4cabcd0b6184c6a92d9de813a02536161cc706e4ea9f2e"
+expression = "CC0-1.0 OR Apache-2.0"
+
+[[licensing.licenses]]
+path = "vendor/liboqs/liboqs-0.12.0/src/kem/kyber/pqcrystals-kyber_kyber512_ref/LICENSE"
+sha256sum = "53681bce13fd98721b4cabcd0b6184c6a92d9de813a02536161cc706e4ea9f2e"
+expression = "CC0-1.0 OR Apache-2.0"
+
+[[licensing.licenses]]
+path = "vendor/liboqs/liboqs-0.12.0/src/kem/kyber/pqcrystals-kyber_kyber768_avx2/LICENSE"
+sha256sum = "53681bce13fd98721b4cabcd0b6184c6a92d9de813a02536161cc706e4ea9f2e"
+expression = "CC0-1.0 OR Apache-2.0"
+
+[[licensing.licenses]]
+path = "vendor/liboqs/liboqs-0.12.0/src/kem/kyber/pqcrystals-kyber_kyber768_ref/LICENSE"
+sha256sum = "53681bce13fd98721b4cabcd0b6184c6a92d9de813a02536161cc706e4ea9f2e"
+expression = "CC0-1.0 OR Apache-2.0"
+
+[[licensing.licenses]]
+path = "vendor/liboqs/liboqs-0.12.0/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-1024_avx2/LICENSE"
+sha256sum = "53681bce13fd98721b4cabcd0b6184c6a92d9de813a02536161cc706e4ea9f2e"
+expression = "CC0-1.0 OR Apache-2.0"
+
+[[licensing.licenses]]
+path = "vendor/liboqs/liboqs-0.12.0/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-1024_ref/LICENSE"
+sha256sum = "53681bce13fd98721b4cabcd0b6184c6a92d9de813a02536161cc706e4ea9f2e"
+expression = "CC0-1.0 OR Apache-2.0"
+
+[[licensing.licenses]]
+path = "vendor/liboqs/liboqs-0.12.0/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-512_avx2/LICENSE"
+sha256sum = "53681bce13fd98721b4cabcd0b6184c6a92d9de813a02536161cc706e4ea9f2e"
+expression = "CC0-1.0 OR Apache-2.0"
+
+[[licensing.licenses]]
+path = "vendor/liboqs/liboqs-0.12.0/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-512_ref/LICENSE"
+sha256sum = "53681bce13fd98721b4cabcd0b6184c6a92d9de813a02536161cc706e4ea9f2e"
+expression = "CC0-1.0 OR Apache-2.0"
+
+[[licensing.licenses]]
+path = "vendor/liboqs/liboqs-0.12.0/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-768_avx2/LICENSE"
+sha256sum = "53681bce13fd98721b4cabcd0b6184c6a92d9de813a02536161cc706e4ea9f2e"
+expression = "CC0-1.0 OR Apache-2.0"
+
+[[licensing.licenses]]
+path = "vendor/liboqs/liboqs-0.12.0/src/kem/ml_kem/pqcrystals-kyber-standard_ml-kem-768_ref/LICENSE"
+sha256sum = "53681bce13fd98721b4cabcd0b6184c6a92d9de813a02536161cc706e4ea9f2e"
+expression = "CC0-1.0 OR Apache-2.0"
diff --git a/mcrouter-0.41.0-no_distutils.patch b/mcrouter-0.41.0-no_distutils.patch
deleted file mode 100644
index d870fcc..0000000
--- a/mcrouter-0.41.0-no_distutils.patch
+++ /dev/null
@@ -1,178 +0,0 @@
-From cda674a71f598e3f7125c63e74f13c0415b12f08 Mon Sep 17 00:00:00 2001
-From: Michel Alexandre Salim <salimma@fedoraproject.org>
-Date: Mon, 19 Jul 2021 16:22:00 -0700
-Subject: [PATCH] Stop using distutils
-
-distutils is deprecated in Python 3.10 and will be removed in 3.12.
-
-Most of the usages here can be replaced by using `sysconfig`; one
-fallback no longer exists and simply has to be removed.
-
-Minimum Python version is now 3.2.0, which introduces `sysconfig`:
-https://docs.python.org/3/library/sysconfig.html
-
-Signed-off-by: Michel Alexandre Salim <salimma@fedoraproject.org>
----
- mcrouter/m4/ax_python_devel.m4 | 63 ++++++++++++++++------------------
- 1 file changed, 29 insertions(+), 34 deletions(-)
-
-diff --git a/mcrouter/m4/ax_python_devel.m4 b/mcrouter/m4/ax_python_devel.m4
-index ef86fcb4..67fe81a1 100644
---- a/mcrouter/m4/ax_python_devel.m4
-+++ b/mcrouter/m4/ax_python_devel.m4
-@@ -25,7 +25,7 @@
- # version number. Don't use "PYTHON_VERSION" for this: that environment
- # variable is declared as precious and thus reserved for the end-user.
- #
--# This macro should work for all versions of Python >= 2.1.0. As an end
-+# This macro should work for all versions of Python >= 3.2.0. As an end
- # user, you can disable the check for the python version by setting the
- # PYTHON_NOVERSIONCHECK environment variable to something else than the
- # empty string.
-@@ -88,19 +88,21 @@ AC_DEFUN([AX_PYTHON_DEVEL],[
- fi
-
- #
-- # Check for a version of Python >= 2.1.0
-+ # Check for a version of Python >= 3.2.0
- #
-- AC_MSG_CHECKING([for a version of Python >= '2.1.0'])
-+ AC_MSG_CHECKING([for a version of Python >= '3.2.0'])
- ac_supports_python_ver=`$PYTHON -c "import sys; \
-- ver = sys.version.split ()[[0]]; \
-- print (ver >= '2.1.0')"`
-+ ver = sys.version.split()[[0]].split('.'); \
-+ major_ver = int(ver[[0]]); \
-+ minor_ver = int(ver[[1]]); \
-+ print (major_ver > 3 or major_ver == 3 and minor_ver >= 2)"`
- if test "$ac_supports_python_ver" != "True"; then
- if test -z "$PYTHON_NOVERSIONCHECK"; then
- AC_MSG_RESULT([no])
- AC_MSG_FAILURE([
- This version of the AC@&t@_PYTHON_DEVEL macro
- doesn't work properly with versions of Python before
--2.1.0. You may need to re-run configure, setting the
-+3.2.0. You may need to re-run configure, setting the
- variables PYTHON_CPPFLAGS, PYTHON_LIBS, PYTHON_SITE_PKG,
- PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand.
- Moreover, to disable this check, set PYTHON_NOVERSIONCHECK
-@@ -135,17 +137,17 @@ variable to configure. See ``configure --help'' for reference.
- fi
-
- #
-- # Check if you have distutils, else fail
-+ # Check if you have sysconfig, else fail
- #
-- AC_MSG_CHECKING([for the distutils Python package])
-- ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
-- if test -z "$ac_distutils_result"; then
-+ AC_MSG_CHECKING([for the sysconfig Python library])
-+ ac_sysconfig_result=`$PYTHON -c "import sysconfig" 2>&1`
-+ if test -z "$ac_sysconfig_result"; then
- AC_MSG_RESULT([yes])
- else
- AC_MSG_RESULT([no])
-- AC_MSG_ERROR([cannot import Python module "distutils".
-+ AC_MSG_ERROR([cannot import Python module "sysconfig".
- Please check your Python installation. The error was:
--$ac_distutils_result])
-+$ac_sysconfig_result])
- PYTHON_VERSION=""
- fi
-
-@@ -154,10 +156,10 @@ $ac_distutils_result])
- #
- AC_MSG_CHECKING([for Python include path])
- if test -z "$PYTHON_CPPFLAGS"; then
-- python_path=`$PYTHON -c "import distutils.sysconfig; \
-- print (distutils.sysconfig.get_python_inc ());"`
-- plat_python_path=`$PYTHON -c "import distutils.sysconfig; \
-- print (distutils.sysconfig.get_python_inc (plat_specific=1));"`
-+ python_path=`$PYTHON -c "import sysconfig; \
-+ print (sysconfig.get_paths()[['include']]);"`
-+ plat_python_path=`$PYTHON -c "import sysconfig; \
-+ print (sysconfig.get_paths()[['platinclude']]);"`
- if test -n "${python_path}"; then
- if test "${plat_python_path}" != "${python_path}"; then
- python_path="-I$python_path -I$plat_python_path"
-@@ -181,7 +183,7 @@ $ac_distutils_result])
-
- # join all versioning strings, on some systems
- # major/minor numbers could be in different list elements
--from distutils.sysconfig import *
-+from sysconfig import get_config_var
- e = get_config_var('VERSION')
- if e is not None:
- print(e)
-@@ -204,8 +206,8 @@ EOD`
- ac_python_libdir=`cat<<EOD | $PYTHON -
-
- # There should be only one
--import distutils.sysconfig
--e = distutils.sysconfig.get_config_var('LIBDIR')
-+import sysconfig
-+e = sysconfig.get_config_var('LIBDIR')
- if e is not None:
- print (e)
- EOD`
-@@ -213,8 +215,8 @@ EOD`
- # Now, for the library:
- ac_python_library=`cat<<EOD | $PYTHON -
-
--import distutils.sysconfig
--c = distutils.sysconfig.get_config_vars()
-+import sysconfig
-+c = sysconfig.get_config_vars()
- if 'LDVERSION' in c:
- print ('python'+c[['LDVERSION']])
- else:
-@@ -230,13 +232,6 @@ EOD`
- # use the official shared library
- ac_python_library=`echo "$ac_python_library" | sed "s/^lib//"`
- PYTHON_LIBS="-L$ac_python_libdir -l$ac_python_library"
-- else
-- # old way: use libpython from python_configdir
-- ac_python_libdir=`$PYTHON -c \
-- "from distutils.sysconfig import get_python_lib as f; \
-- import os; \
-- print (os.path.join(f(plat_specific=1, standard_lib=1), 'config'));"`
-- PYTHON_LIBS="-L$ac_python_libdir -lpython$ac_python_version"
- fi
-
- if test -z "PYTHON_LIBS"; then
-@@ -254,8 +249,8 @@ EOD`
- #
- AC_MSG_CHECKING([for Python site-packages path])
- if test -z "$PYTHON_SITE_PKG"; then
-- PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
-- print (distutils.sysconfig.get_python_lib(0,0));"`
-+ PYTHON_SITE_PKG=`$PYTHON -c "import sysconfig; \
-+ print (sysconfig.get_paths()[['platlib']]);"`
- fi
- AC_MSG_RESULT([$PYTHON_SITE_PKG])
- AC_SUBST([PYTHON_SITE_PKG])
-@@ -265,8 +260,8 @@ EOD`
- #
- AC_MSG_CHECKING(python extra libraries)
- if test -z "$PYTHON_EXTRA_LDFLAGS"; then
-- PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \
-- conf = distutils.sysconfig.get_config_var; \
-+ PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import sysconfig; \
-+ conf = sysconfig.get_config_var; \
- print (conf('LIBS') + ' ' + conf('SYSLIBS'))"`
- fi
- AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS])
-@@ -277,8 +272,8 @@ EOD`
- #
- AC_MSG_CHECKING(python extra linking flags)
- if test -z "$PYTHON_EXTRA_LIBS"; then
-- PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \
-- conf = distutils.sysconfig.get_config_var; \
-+ PYTHON_EXTRA_LIBS=`$PYTHON -c "import sysconfig; \
-+ conf = sysconfig.get_config_var; \
- print (conf('LINKFORSHARED'))"`
- fi
- AC_MSG_RESULT([$PYTHON_EXTRA_LIBS])
---
-2.31.1
-
diff --git a/mcrouter.spec b/mcrouter.spec
index 37028ab..fa19b76 100644
--- a/mcrouter.spec
+++ b/mcrouter.spec
@@ -1,53 +1,110 @@
-%bcond_without debug
+%bcond_with toolchain_clang
-# tests fail with multiple Error: symbol ... is already defined
+%if %{with toolchain_clang}
+%global toolchain clang
+%endif
+
+# The test suite was never run in this package (it failed to even link in
+# the autotools days). Enable once a mock run shows what it needs.
%bcond_with check
-%if %{without debug}
-%global debug_package %{nil}
+# Upstream cuts a weekly tag, vYYYY.MM.DD.NN; Version is the tag without its
+# v. For a snapshot past the tag, also paste the two %%global lines
+# ./snapshot.sh prints (the commit and its distance from the tag): Version
+# becomes <tag>^<distance>.<shortcommit>, the guidelines' <number>.<revision>
+# snapshot form, and the distance keeps several snapshots between two tags in
+# order. 0.41.0.20250203, the last build of the autotools-era scheme, sorts
+# below.
+%global basetag v2026.09.21.00
+# Snapshot: the first commit shipping build/fbcode_builder, which the
+# %%getdeps_* macros need; the next weekly tag will contain it.
+%global commit d8b07b00c72e94237d3710db0e36ec58de414b6c
+%global commits 1
+%global tagver %(echo %{basetag} | sed 's|^v||')
+%if 0%{?commit:1}
+%global shortcommit %(c=%{commit}; echo ${c:0:7})
+%global snapinfo ^%{commits}.%{shortcommit}
+%global archive_ref %{commit}
+%global archive_dir mcrouter-%{commit}
+%else
+%global archive_ref %{basetag}
+%global archive_dir mcrouter-%{tagver}
%endif
-%global forgeurl https://github.com/facebook/mcrouter
-%global tag 2025.02.03.00
-%global date %(echo %{tag} | sed -e 's|.00$||' | sed -e 's|\\.||g')
-
-# lib/fbi/cpp/LowerBoundPrefixMap.cpp includes folly/container/tape.h
-# which uses std::ranges which is part of C++20
-%global optflags %optflags -std=c++20
+# The CMake conversion left the version to the builder ("0.1.0-dev" by
+# default); this is what --version and the startup log print. getdeps has no
+# per-project CMake defines, so it is passed to every project it builds.
+# Contents of a JSON object; the macro adds the braces.
+%global getdeps_extra_cmake_defines "MCROUTER_PACKAGE_VERSION": "%{version}"
Name: mcrouter
-Version: 0.41.0.%{date}
+Version: %{tagver}%{?snapinfo}
Release: %autorelease
Summary: Memcached protocol router for scaling memcached deployments
-License: MIT
-URL: %{forgeurl}
-Source: %{url}/archive/v%{tag}/%{name}-%{tag}.tar.gz
-# distutils deprecated in Python 3.10
-Patch: %{name}-0.41.0-no_distutils.patch
-
-# Temporarily drop ppc64le due to a bug in folly's F14Set fallback
-# rhbz#2344416
-ExclusiveArch: x86_64 aarch64
-
-BuildRequires: autoconf
-BuildRequires: automake
-BuildRequires: libtool
-BuildRequires: make
-BuildRequires: sed
+# SourceLicense needs rpm >= 4.19; EPEL 9 (rpm 4.16) gets the full expression
+# on the SRPM as before
+%if !0%{?rhel} || 0%{?rhel} >= 10
+SourceLicense: MIT
+%endif
+# Vendored projects (getdeps-vendor.txt), as %%check's go_vendor_license report
+# breaks them down; the config is getdeps-vendor-licenses.toml:
+# Apache-2.0 folly, wangle, fbthrift
+# BSD-3-Clause fizz
+# MIT AND BSD-2-Clause AND BSD-3-Clause mvfst (third-party code)
+# MIT AND CC0-1.0 AND (Apache-2.0 OR CC0-1.0) liboqs (Kyber/ML-KEM only)
+# CC0-1.0 is liboqs' aarch64 Kyber code, as in Fedora's own liboqs License tag.
+License: %{shrink:
+ MIT AND
+ Apache-2.0 AND
+ BSD-2-Clause AND
+ BSD-3-Clause AND
+ CC0-1.0 AND
+ (Apache-2.0 OR CC0-1.0)
+}
+URL: https://github.com/facebook/mcrouter
+# GitHub ignores the last path component of an archive URL, so the file is
+# named after the version, like Source1 (Packaging Guidelines, SourceURL:
+# git hosting services)
+Source0: %{url}/archive/%{archive_ref}/%{name}-%{version}.tar.gz
+# The dependencies getdeps cannot take from Fedora packages, at the revisions
+# recorded in vendor/getdeps-vendor.txt; produced by ./vendor.sh
+Source1: %{name}-%{version}-vendor.tar.xz
+Source2: getdeps-vendor-licenses.toml
+
+# Patches to the vendored trees (vendor/<project>/...) are applied at build
+# time, after Source1 is unpacked; ./vendor.sh skips them when vendoring.
+# folly against OpenSSL 4.0 (Fedora 45+): facebook/folly#2706, in review
+# (wangle's counterpart, facebook/wangle#254, has landed)
+Patch0: 0001-folly-build-against-OpenSSL-4.0.patch
+# fbthrift puts relocated metadata in a .rodata section, which -fPIC/-fPIE
+# makes writable; the linker then emits an RWX segment that Fedora's
+# --error-rwx-segments refuses and glibc's aarch64 loader crashes on.
+# facebook/fbthrift#712 landed and was reverted for an unrelated internal
+# size limit; carried until it lands again.
+Patch1: 0003-fbthrift-keep-thrift-data-out-of-a-writable-rodata-section.patch
+# folly's F14 fallback (no SSE2/NEON: ppc64le) is ambiguous against
+# libstdc++ 16's own heterogeneous lookup; submitted internally from
+# michel-slm/folly 4193514eb
+Patch2: 0004-folly-F14-fallback-forward-exact-key-lookups.patch
+# mcrouter itself against current folly (explicit gflags includes) and
+# Boost 1.90 (filesystem/convenience.hpp removed); submitted internally
+Patch3: 0005-Build-against-current-folly-and-Boost-1.90.patch
+# getdeps-vendor.txt recorded "main" for the unpinned dependencies; record
+# the checked-out commit instead (applied by vendor.sh before vendoring)
+Patch4: 0006-getdeps-record-the-checked-out-commit-in-getdeps-vendor.txt.patch
+
+# ppc64le was dropped in 0.41.0.20250203 over the folly F14 fallback bug
+# (rhbz#2344416); Patch2 fixes the current incarnation of it, and cachelib
+# builds on ppc64le with the same patch.
+ExclusiveArch: x86_64 aarch64 ppc64le
+
+BuildRequires: folly-rpm-macros >= 46
+%if %{with toolchain_clang}
+BuildRequires: clang
+%else
BuildRequires: gcc-c++
-BuildRequires: folly-devel
-BuildRequires: fizz-devel
-BuildRequires: wangle-devel
-BuildRequires: fbthrift-devel
-BuildRequires: fbthrift
-BuildRequires: libatomic
-# for free
-BuildRequires: procps-ng
-BuildRequires: python3-devel
-BuildRequires: ragel
-# Test dependencies
-BuildRequires: gtest-devel
+%endif
%description
Mcrouter (pronounced mc router) is a memcached protocol router for scaling
@@ -61,41 +118,36 @@ mcrouter, which was designed to be a drop-in proxy between the client and
memcached hosts.
+%generate_buildrequires
+%getdeps_generate_buildrequires
+%getdeps_vendor_license_buildrequires -c %{SOURCE2}
+
+
%prep
-%autosetup -p1 -n %{name}-%{tag}
-pushd %{name}
-# Fix detecting ppc64le: bug 1943729
-sed -i m4/ax_boost_base.m4 -e 's@ppc64|@ppc64|ppc64le|@'
-echo "%{version}" > VERSION
-autoreconf --install
+%autosetup -n %{archive_dir} -a1 -p1
%build
-pushd %{name}
-export FBTHRIFT_BIN="%{_bindir}"
-export INSTALL_DIR="%{_prefix}"
-export PYTHON_VERSION="%{python3_version}"
-%configure --enable-shared --disable-static
-# do not eat all memory
-%make_build %{limit_build -m 4096}
+%getdeps_build %{?with_check:-t}
%install
-pushd %{name}
-%make_install
+%getdeps_install
+%getdeps_vendor_license_install -c %{SOURCE2}
-%if %{with check}
%check
-pushd %{name}
-%make_build check
+# -L: liboqs's LICENSE.txt sits in a versioned subdirectory of its tree
+%getdeps_vendor_license_check -c %{SOURCE2} -L
+%if %{with check}
+%getdeps_test
%endif
-%files
-%license LICENSE
+%files -f %{getdeps_vendor_license_filelist}
%doc README.md
-%{_bindir}/*
+%{_bindir}/mcrouter
+%{_bindir}/mcpiper
%changelog
diff --git a/snapshot.sh b/snapshot.sh
new file mode 100755
index 0000000..ef1d2c3
--- /dev/null
+++ b/snapshot.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+# Print the %global lines for building a snapshot of mcrouter: the weekly tag
+# it is based on, the full commit, and the commit's distance from the tag.
+# The spec turns them into Version <tag>^<distance>.<shortcommit>, so several
+# snapshots between two tags order correctly. This uses the GitHub API (gh,
+# logged in), no clone needed; from a clone of any forge, git describe gives
+# all three values at once:
+# git describe --tags --match 'v20??.??.??.??' <ref> # v2026.09.14.00-38-gee4c153
+# git rev-parse <ref>
+# ./snapshot.sh # upstream main
+# ./snapshot.sh <ref> # a branch, tag or commit
+set -eu
+repo=facebook/mcrouter
+ref=${1:-main}
+commit=$(gh api "repos/$repo/commits/$ref" --jq .sha)
+# weekly tags are vYYYY.MM.DD.NN; the dotted glob keeps out old-style vYYYYMMDD tags
+tag=$(git ls-remote --tags --sort=-v:refname "https://github.com/$repo" 'refs/tags/v20??.??.??.??' | head -1 | sed 's|.*refs/tags/||')
+commits=$(gh api "repos/$repo/compare/$tag...$commit" --jq .ahead_by)
+echo "# $commits commits since $tag"
+echo "%global basetag $tag"
+echo "%global commit $commit"
+echo "%global commits $commits"
diff --git a/sources b/sources
index 70f75ba..b2171bf 100644
--- a/sources
+++ b/sources
@@ -1 +1,2 @@
-SHA512 (mcrouter-2025.02.03.00.tar.gz) = f236dbcf110adc3acd5dd5882fad619866e7b306bd55ce3d8e4863061fa390cb65b259dc3cd83d5510691cf4f5b692cc0ae249f165246a0dc2e976ab61bec46c
+SHA512 (mcrouter-2026.09.21.00^1.d8b07b0-vendor.tar.xz) = 454fa45d5cde24911faff092d429be74e5edd1af8f3053724538d5c62caba9dd8f4538198216ced790b2e02b098c1cfa8ba1d5b7fce1762fb6bfeaabedde2177
+SHA512 (mcrouter-2026.09.21.00^1.d8b07b0.tar.gz) = 59e1433d6e95ff5005f4db4e9e4dd363e10343df2a792056073f0c204517cd676e310d14d9c6a86517580e9792e93575e2c7240852778be313c564888211cf07
diff --git a/vendor.sh b/vendor.sh
new file mode 100755
index 0000000..e7c884b
--- /dev/null
+++ b/vendor.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+# Produce Source1, the tarball of getdeps-vendored dependencies, for the
+# Source0 the spec currently references. Nothing here is specific to cachelib
+# beyond the spec it reads. getdeps vendors whatever it cannot
+# take from installed packages, so for a minimal tarball first install the
+# packages the build will have (getdeps.py --allow-system-packages
+# install-system-deps --recursive cachelib, from the unpacked source; the
+# spec's BuildRequires are generated, so dnf builddep cannot see them). A
+# tarball made with fewer packages installed still works, it is only larger.
+set -eu
+# usage: vendor.sh [package.spec] (defaults to the single spec in the cwd)
+spec=${1:-$(ls ./*.spec)}
+name=$(rpmspec -q --srpm --qf '%{name}\n' "$spec")
+version=$(rpmspec -q --srpm --qf '%{version}\n' "$spec")
+spectool -g -s 0 "$spec"
+source0=$(spectool -S -s 0 "$spec" | awk '{print $2}')
+# on disk, not tmpfs: the extracted source plus getdeps' scratch space run to
+# gigabytes, and getdeps defaults its scratch dir to /tmp outside $tmp
+tmp=$(mktemp -d -p "${TMPDIR:-/var/tmp}")
+trap 'rm -rf "$tmp"' EXIT
+tar xf "$(basename "$source0")" -C "$tmp"
+srcdir=$(find "$tmp" -mindepth 1 -maxdepth 1 -type d)
+# the spec's patches may change what getdeps takes from the system; those
+# touching the vendored trees themselves cannot apply yet and are skipped
+for p in $(spectool -P "$spec" | awk '{print $2}'); do
+ grep -q '^+++ b/vendor/' "$p" && continue
+ patch -d "$srcdir" -p1 --quiet < "$p"
+done
+python3 "$srcdir/build/fbcode_builder/getdeps.py" --allow-system-packages \
+ --scratch-path "$tmp/scratch" vendor --no-tests --output-dir "$tmp/vendor" "${GETDEPS_PROJECT:-$name}"
+tar -C "$tmp" -cJf "$name-$version-vendor.tar.xz" vendor
+echo "wrote $name-$version-vendor.tar.xz"
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-09-25 7:33 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-25 7:33 [rpms/mcrouter] rawhide: Build with getdeps and vendored dependencies via %getdeps_* macros Michel Lind
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox