43 Commits
Author SHA1 Message Date
CHEN FengandClaude Opus 4.8 6320851cd6 thirdparty: make foreign_build.bld Starlark-parseable (#212)
blade-go's front-end is Starlark, which (unlike Python) has no generator
expressions or implicit string concatenation. Convert foreign_build.bld to the
equivalent Starlark forms so it can be include()'d there, with no behavior change
under Python Blade:

- generator expr -> list comprehension in the rpath ' '.join(...).
- adjacent-string-literal concatenation -> explicit '+' in dyld_path, the
  autotools configure command, and the cmake generate command (parenthesized so
  the trailing `% (...)` still applies to the whole concatenation).
- fix cmake_cc_library, which was dead-but-unparseable: it referenced undefined
  package_name/deps/with_packages. Give it deps/with_packages params, pass
  package_name=name and source_package through (mirrors autotools_cc_library).

Same Starlark-compat class as the cc_flare_library change in the build_rules.bld.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 22:23:35 +08:00
CHEN FengandClaude Opus 4.8 3a5c410c18 build: make cc_flare_library front-end-agnostic; upgrade vendored blade (#211)
Rewrite the two Python-only constructs in the cc_flare_library extension so it
parses under a Starlark front-end as well as Blade's (restricted) Python DSL,
with identical behaviour under Blade:

- `assert len(srcs) == 1, msg` -> `if len(srcs) != 1: fail(msg)`
- `deps is None` -> `deps == None`
- implicit adjacent-string concatenation -> explicit `+`

`isinstance` is kept (both front-ends provide it). This lets flare build under a
Go reimplementation of Blade (blade-go) without changing the current build.

Also upgrade the vendored blade (thirdparty/blade/blade.zip + GITVERSION) to
blade-build master, which adds the `fail()` builtin the change above uses.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 21:14:34 +08:00
CHEN FengandClaude Opus 4.8 71698ba232 thirdparty: pin AR/RANLIB in autotools foreign builds (fix macOS jemalloc link) (#210)
_configure passed CC/CXX from the resolved toolchain but let AR/RANLIB fall
through to PATH. On macOS, a stray GNU-format `ar` ahead of /usr/bin/ar (e.g.
Homebrew binutils / an llvm-ar in --format=gnu mode) builds a package's static
archive in GNU format -- with `/` and `//` index members -- which Apple's ld
rejects at link time:

  ld: archive member '/' not a mach-o file in '.../lib/libjemalloc.a'

This surfaced on je_server (jemalloc's libjemalloc.a is built by a direct
$(AR) crus Makefile rule, so it picks up the PATH ar; libtool-built archives
like libtcmalloc/jsoncpp/ctemplate were unaffected because libtool drives the
archiver consistently). The gperftools profiler archives hit the same GNU
format but are gated Linux-only, so they never reached a macOS link.

Pin AR/RANLIB the same way CC/CXX already are: force the system BSD
ar/ranlib on macOS (they emit a `__.SYMDEF` archive ld accepts), and honor
the toolchain ar elsewhere (GNU archives are fine for GNU ld). Passed both as
env and as autoconf precious-vars so the generated Makefile uses them
(verified: `AR = /usr/bin/ar`, archive members are `__.SYMDEF SORTED` + objects,
je_server links).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 22:44:52 +08:00
CHEN Feng 91a27b93e5 thirdparty/blade: bump vendored blade to v3.0.0 (dd0d2ae) (#208)
Blade 3.0.0 is released. Bump the vendored blade from 3100733 (2026-06-23)
to the 3.0.0 release commit dd0d2ae (2026-06-27): regenerated blade.zip via
dist_blade and updated GITVERSION.
2026-06-27 19:51:25 +08:00
CHEN Feng 92f15f5412 thirdparty/blade: bump vendored blade to 3100733 (#203)
Catches flare's vendored blade up to blade-build master (from 34883163). What
this pulls in, user-visible:

- Cross-platform PGO: instrumentation (--profile-generate/--profile-use) and
  sample-based AutoFDO (--autofdo-generate/--autofdo-use) on gcc/clang, plus
  native MSVC (LTCG PGO / SPGO). Opt-in; no effect on flare's normal builds.
- --sanitizer now rejects an invalid combo (e.g. address,thread) at the command
  line instead of mid-build after the load/analyze pass and build-dir creation.
- Robustness: blade no longer crashes when git/svn is absent in a versioned
  workspace (SCM info degrades to 'unknown').
- MSVC C/C++ test coverage + coverage_config(exclude=...) (Windows-only; N/A to
  flare's Linux/macOS builds).

No flare BUILD/source changes needed; verified flare builds clean on the new
blade (base/encoding, a cc_test) and that --sanitizer=address still builds while
address,thread is rejected instantly.
2026-06-24 00:23:37 +08:00
CHEN FengandClaude Opus 4.8 83acfc7bf9 macOS: portable fiber stack under ASan + bump vendored blade (#202)
Two changes that together make `blade build/test --sanitizer / --coverage` work
on macOS:

- fiber: `GetMasterFiberStack()` used `pthread_getattr_np` (Linux/glibc only),
  which fails to compile on macOS clang under ASan (`FLARE_INTERNAL_USE_ASAN`).
  Add a macOS branch using `pthread_get_stackaddr_np` / `pthread_get_stacksize_np`
  (the stack grows down, so bottom = stackaddr - stacksize).
- thirdparty/blade: bump the vendored blade (blade.zip + GITVERSION) to
  blade-build 3488316, which includes the build-dir naming modernization, the
  fixes that stop `cc_check_undefined` from flagging the coverage/sanitizer
  runtime symbols (`__llvm_gcda_*`, `__ubsan_*`, the TSan `Annotate*` dynamic
  annotations, ...), and the --gprof/--coverage platform gating (no more dead
  `-pg` warnings on macOS).
- .gitignore: the new blade default build dir is `build_<profile>[_<variant>]`;
  ignore `/build_*/` (keeping the legacy `build{32,64}_*`).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 21:26:23 +08:00
CHEN FengandClaude Opus 4.8 92a08ae18b tracing: migrate opentracing-cpp → opentelemetry-cpp (API only) (#201)
* tracing: migrate opentracing-cpp -> opentelemetry-cpp (API only)

opentracing-cpp is deprecated/superseded by OpenTelemetry. flare ships no real
tracer -- it exposes a pluggable abstraction (TracingOpsProvider / QuickerSpan /
TracingOps) over the tracing-API types, with providers plugged in by users.
Re-base that abstraction on the opentelemetry-cpp **API** (header-only, v1.27.0)
and drop opentracing-cpp from both build systems.

Scope: API only -- no SDK/exporter, so no protobuf/grpc is pulled in and the
deliberately-pinned (abseil-free) protobuf 3.21.12 stays intact. The
abstraction and the opaque `bytes tracing_context` wire format are kept; only
the types/bodies change.

Source (flare/rpc/tracing/):
- tracing_ops_provider.h: re-typed virtuals; new flare-owned SpanStartOptions
  (parent SpanContext + SpanKind + timestamps + start attrs) replacing
  opentracing::StartSpanOptions/ChildOf. Extract -> std::optional<SpanContext>.
- tracing_ops.h/.cc: span_ is nostd::shared_ptr<trace::Span>; SetAttribute/
  AddEvent/End; SpanContext is a value type; buffered ops keep flare's owning
  variant and convert to (non-owning) AttributeValue only at flush.
- framework_tags.h -> constexpr std::string_view; string_view_interop.h ->
  ToStd/ToOtel (nostd<->std). Standard-tag table is a literal allowlist;
  span.kind moves from a tag to SpanStartOptions::kind.
- Call sites rpc_channel.cc / normal_connection_handler.cc updated; rpc_meta.proto
  comment updated (wire field unchanged).
- Tests/benchmark rewritten onto a recording fake otel::trace::Span (OTel's noop
  span can't be asserted on); integration test asserts span kind via the
  provider-recorded "span.kind" instead of an opentracing tag.

Build:
- blade: BLADE_ROOT vcpkg_config gains opentelemetry-cpp; thin wrapper
  //thirdparty/opentelemetry-cpp:api (refs opentelemetry_common -- the api
  component is header-only with no .a; that lib's include dir carries the api +
  absl headers). opentracing thirdparty dir removed.
- bazel: deps.bzl http_archive for opentelemetry-cpp 1.27.0 + api-only
  bazel/opentelemetry-cpp.BUILD (header-only, bundled nostd -> no abseil);
  patch_cmds drop the archive's nested BUILDs so the api headers can be globbed.
  opentracing BUILD/patch + .bazelignore/.gitattributes entries removed.

Verified: blade and bazel both build //flare/rpc/tracing/... and pass
tracing_ops_test + integration_test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* ci: bazelignore thirdparty/opentelemetry-cpp (blade BUILD)

The repo-wide `bazel build ...` job parses every BUILD file; the blade thin
wrapper thirdparty/opentelemetry-cpp/BUILD uses blade-only syntax
(vcpkg#...:lib, visibility='PUBLIC'). Add it to .bazelignore (the opentracing
entry was removed but its replacement wasn't added).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* tracing: clang-format (v15) the migrated files

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: drop accidentally-committed .claude/ tooling files

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* doc(tracing): note provider ABI contract for OpenTelemetry nostd types

The TracingOpsProvider interface uses OpenTelemetry API types
(nostd::shared_ptr<Span>, nostd::string_view, AttributeValue) directly.
The nostd:: backing is a compile-time choice (bundled / std via
OPENTELEMETRY_STL_VERSION / abseil) and the three are mutually
incompatible types, so a provider must be built with the same
OpenTelemetry configuration as flare. flare leaves the default nostd
in place.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: gitignore .claude/ (Claude Code local tooling)

Prevents accidentally re-committing .claude/settings*.json (cf. review
comments on PR #201).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* tracing: address PR #201 review follow-ups (non-blocking)

- forcibly_sampled now routes `flare.sampling_priority` through the
  provider's `SetFrameworkTag` translation (before `IsSampled`) instead of
  a raw `SetAttribute`, keeping the `flare.`-prefixed tag consistent with
  every other framework tag and letting providers honor the force-sample
  signal. Add `ext::kSamplingPriority`.
- An empty log key (single-arg `AddTracingLog`) now materializes as the
  default event name "log" so backends that group/display by event name
  don't render a blank one; document the per-log-event mapping.
- Guard `QuickerValue`'s reliance on P0608R3 (C++20) with a static_assert
  so a future standard downgrade can't silently bind `const char*` to bool.
- Reset `DummySpan`'s inline-static tags/logs at the start of the recording
  test so assertions can't observe leftovers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 00:36:01 +08:00
CHEN FengandClaude Opus 4.8 3c103bd249 bazel/blade: drop hardcoded well_known_protos; auto-discover from vcpkg protobuf (#195)
blade-build#1339 (merged) makes blade auto-discover the well-known protos
(google/protobuf/*.proto) from the protobuf include tree when
proto_library_config.well_known_protos is empty. With the vcpkg#protobuf
provider that resolves to the installed include/, so the list need not be
hand-maintained in BLADE_ROOT and stays correct across protobuf versions.

Empty the list (blade falls back to a built-in canonical set if the include
tree is ever unresolvable) and vendor the blade.zip built from the merged
blade master. Verified: building flare/rpc/... still passes
--direct_dependencies with the same 12 google/protobuf protos, now discovered.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 23:28:26 +08:00
CHEN FengandClaude Opus 4.8 5a0132028e docs(thirdparty): mark openssl/nghttp2/curl migrated; only jsoncpp left (#191)
The curl cluster (#190) moved openssl (->3.x), nghttp2 and curl to vcpkg, so
they move from the blocked table to the migrated table. jsoncpp is the sole
remaining #179 lib (0.x->1.x API change).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 08:32:33 +08:00
CHEN FengandClaude Opus 4.8 ed29968f5a thirdparty: migrate openssl/nghttp2/curl to vcpkg (#179 curl cluster) (#190)
* thirdparty: migrate openssl/nghttp2/curl to vcpkg (#179 curl cluster)

vcpkg has no openssl 1.1.1, so this upgrades the cluster to 3.x and migrates all
three off foreign builds. Consumers' //thirdparty/{openssl,nghttp2,curl} targets
are unchanged (thin vcpkg wrappers).

- openssl -> vcpkg 3.x. flare's crypto/init code adapted for 3.x:
  - flare/io/util/openssl.cc: gut the obsolete OpenSSL-1.0.x ceremony
    (SSL_library_init, ERR_load_*, ENGINE_*, CRYPTO_set_locking_callback /
    CRYPTO_num_locks). OpenSSL 1.1+ auto-initializes and is internally
    thread-safe, so both entry points are now empty no-ops.
  - flare/base/crypto/{md5,sha}: -Wno-deprecated-declarations -- the low-level
    MD5/SHA/HMAC APIs are deprecated in 3.x (provider/EVP migration) but still
    valid until 4.0, so suppress rather than rewrite to EVP.
- nghttp2, curl -> vcpkg (API-stable version bumps). curl built with the openssl
  + http2 features; its macOS frameworks (SystemConfiguration/Security/
  CoreFoundation/CoreServices) link via blade's new pkg-config -framework
  support. Wrapper declares the sibling vcpkg deps (openssl/nghttp2/zlib).
- thirdparty/blade/blade.zip: rebuilt with that -framework support.
- Drop the vendored tarballs and patches (openssl/curl/nghttp2, curl dyld patch).

Verified: full `blade test flare/...` green on macOS (crypto/ssl/curl/cos all
pass).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* thirdparty/openssl: drop redundant #dl/#pthread

blade now auto-propagates libcrypto's pkg-config system libs (Libs.private:
-ldl) via the #1322 mechanism, and flare links pthread globally on Linux
(cc_config). So the wrapper's explicit #dl/#pthread are redundant.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci: checkout the pinned vcpkg baseline (not just fetch)

Fetching only the baseline commit let 'git show <baseline>:versions/baseline.json'
resolve the baseline version, but vcpkg reads the per-port versions/*.json from
the working tree -- still the runner's stale HEAD. For ports whose baseline
version is newer than that HEAD (openssl 3.6.3, nghttp2 1.69, curl 8.20) vcpkg
errors 'no version database entry'. Checkout the baseline so the whole version
DB / ports tree is consistent (matching local dev).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 08:09:28 +08:00
CHEN FengandClaude Opus 4.8 5fb5dbbbf0 thirdparty/protobuf: fix proto_test gtest include after vcpkg migration (#189)
proto_test.cc included the old in-tree full path
"thirdparty/googletest/gtest/gtest.h", which no longer resolves after gtest
moved to vcpkg (#187) -- only gtest_prod.h remains in-tree; gtest headers now
come from vcpkg as "gtest/gtest.h" via the cc_test's gtest_libs include path.
ubuntu-24.04 caught it on a cold build64_release; macOS/22.04 passed on cached
objects. Switch to the standard "gtest/gtest.h".

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 03:01:58 +08:00
CHEN FengandClaude Opus 4.8 ee31d650b0 docs(thirdparty): update vcpkg migration status (#188)
- gtest is migrated (#187) -> move to the ✅ table; note *_main libs resolve
  under vcpkg's lib/manual-link/ and the UnitTest-registry singleton is handled
  by the now-default 'auto' linkage.
- Reflect blade's new default linkage='auto' (cc_library-like): singletons get
  one shared instance with no per-port annotation; only non-default choices
  (benchmark 'static', link_all_symbols/include_prefix/cmake_options) are spelled
  out. Drop the explicit linkage='auto' from the gflags/glog/yaml-cpp/protobuf
  rows; correct the yaml-cpp note (the old "wrapper .dylib exports" story was
  wrong) and add the protobuf descriptor-pool-singleton rationale.
- Record the confirmed non-migratable libs: opentracing-cpp (vcpkg 1.6.0's
  variant.hpp uses std::result_of, removed in C++20 — needs the foreign build's
  patches), and blake3/rapidxml (in-tree vendored, not foreign builds).

No code/BUILD changes: ctemplate and opentracing were evaluated for vcpkg this
round and confirmed unmigratable, so they stay foreign.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 02:35:33 +08:00
CHEN FengandClaude Opus 4.8 158f72be83 thirdparty: migrate googletest to vcpkg; adopt blade default 'auto' linkage (#187)
- googletest: thin wrappers over vcpkg gtest (gtest/gtest_main/gmock/gmock_main,
  pinned 1.17.0); drop the vendored tarballs and generate_dynamic.patch. gtest's
  *_main libs come from vcpkg's lib/manual-link/ (resolved by the updated blade).
- BLADE_ROOT: update blade.zip to the build with default 'auto' linkage + the
  manual-link fix. With 'auto' the default, the explicit linkage='auto' on
  protobuf/gflags/glog/yaml-cpp/gtest is now redundant and removed; only the
  non-default choices remain (benchmark -> 'static' as it has no shared build;
  link_all_symbols / include_prefix / cmake_options where needed).
- BLADE_ROOT: drop the hardcoded vcpkg `root` path -- blade reads $VCPKG_ROOT,
  else finds vcpkg on PATH (portable; CI uses the runner's vcpkg).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 02:15:29 +08:00
CHEN FengandClaude Opus 4.8 a1678b2278 thirdparty: migrate benchmark to vcpkg (pinned 1.7.1) (#186)
Replace the vendored google/benchmark 1.5.3 foreign build with a thin
vcpkg wrapper. Consumers keep depending on //thirdparty/benchmark:{benchmark,
benchmark_main}; cc_config.benchmark_libs / benchmark_main_libs are unchanged.

Pinned to 1.7.1: 1.8.0 deprecated benchmark::DoNotOptimize(const T&), which
flare's *_benchmark.cc use heavily, and flare builds gcc with
-Werror=deprecated-declarations (clang/macOS doesn't trigger it). 1.7.1 is the
last series before that deprecation.

vcpkg ships benchmark at its native include/benchmark/ layout, so no
include_prefix is needed. Drops the vendored tarball and the
remove_unused_var.patch.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 22:47:12 +08:00
CHEN Feng 7b68301df9 thirdparty: migrate yaml-cpp to vcpkg (#185)
yaml-cpp 0.6.3 -> vcpkg 0.9.0. linkage=auto + link_all_symbols (whole-archive the static .a into the wrapper shared lib so it exports symbols -- the real cause of the convert_to_map "ABI" undefined). thirdparty-only.
2026-06-17 15:57:21 +08:00
CHEN Feng ff0449e6dd thirdparty: upgrade protobuf to vcpkg 3.21.12 (last abseil-free) (#184)
Migrate protobuf from vendored 3.4.1 to vcpkg 3.21.12 (last release before Abseil became mandatory). vcpkg protoc + libprotobuf; source fixes for the 3.4->3.21 API (cpp_helpers.h, duplicate ext registration, Status::ToString); remove the ~47MB vendored 3.4.1 tree. Both blade and bazel builds + proto/RPC tests pass; protobuf install is abseil-free.
2026-06-17 13:56:31 +08:00
CHEN Feng 2bfd54cdea thirdparty/blade: update blade.zip — print progress without cursor control (#183)
Update vendored blade to master 168ce01 (blade-build#1334): print ninja status lines when the terminal has no cursor control (CI/pipe), keeping builds observable. Honors --quiet, keeps the completion summary.
2026-06-17 09:26:10 +08:00
CHEN Feng 55d97852f7 thirdparty: migrate fmt/gflags/glog/zlib/lz4/zstd/snappy/xxhash to vcpkg (#180)
Migrate eight third-party libraries (fmt, gflags, glog, zlib, lz4, zstd, snappy, xxhash) from in-tree foreign builds to vcpkg, via blade native vcpkg support. Bundles the matching blade.zip (proto import-root + vcpkg protoc + transitive Requires linking + textual_hdrs) and the CI/Bazel adjustments (pinned vcpkg baseline; xxhash externalized for Bazel).
2026-06-17 07:17:10 +08:00
CHEN FengandClaude Opus 4.8 24ab46abc2 thirdparty/blade: upgrade blade core and rewrite launcher for macOS (#178)
Update the vendored blade.zip (git-lfs) to the current build and rewrite
the `blade` wrapper to locate the core next to the script and run it with
a suitable Python interpreter, adding macOS support alongside Linux.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:49:53 +08:00
CHEN FengandClaude Opus 4.8 092eb31166 thirdparty/gtest: build both static and shared libs to fix empty test registries on macOS (#177)
On macOS shared-library builds, several `:main`-based tests
(http_mock_test, cos_mock_test, hbase_channel_test) ran zero test cases
and printed "This test program does NOT link in any test case", even
though their sources define real TEST()s.

Root cause: gtest was static-only. Release builds default to
dynamic_link, but with no libgtest.dylib the dynamic label fell back to
the static archive, which then got force_loaded (link_all_symbols) into
every mock/main dylib. Each dylib ended up exporting its own copy of
gtest's UnitTest registry singleton, so TEST() registration bound to one
copy while RUN_ALL_TESTS() (in libmain.dylib) read another. Whether a
test tripped this depended purely on dylib link order.

Fix: ship a shared libgtest so the registry is a single process-wide
instance. googletest's CMake keys solely off BUILD_SHARED_LIBS and emits
either static or shared per configure, so a single pass can't produce
both. Add an optional second configure+install pass to cmake_build
(`shared_cmake_options`) and use it for googletest: the static pass keeps
libgtest.a for static_link consumers, the shared pass adds libgtest.dylib
for dynamic_link ones. No source patch, so nothing to re-port on the next
gtest bump (the stale generate_dynamic.patch was written for 1.10 and no
longer applies to 1.17).

Verified: both .a and .dylib are produced; the three tests now link
libgtest.dylib and pass (8/3/2); ordinary gtest_main tests still pass;
full //flare/... build links clean.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:39:09 +08:00
CHEN FengandClaude Opus 4.7 d3bda1c595 thirdparty: route foreign_cc include dirs through -isystem (#171)
Two coupled changes:

1. Bump thirdparty/blade.zip from 9306687 to 5b305b0, picking up
   blade-build#1247 which adds the system_export_incs / system_include
   plumbing.

2. Switch foreign_build.bld's autotools_build and cmake_build gen_rules
   from ``export_incs=`` to ``system_export_incs=`` for the install
   include directory. Consumers now compile with
   ``-isystem<install_dir>/include`` instead of ``-I<install_dir>/include``,
   so diagnostics raised inside vendored third-party headers (glog
   self-deprecation, openssl pedantic notes, etc.) are no longer
   promoted to errors by our ``-Werror`` build.

3. Drop thirdparty/glog/silence_self_deprecation.patch + its entry in
   glog/BUILD's patches list. The patch was added in #168 to work
   around gcc-10's lack of the deprecated-inside-deprecated heuristic
   (every TU pulling in <glog/logging.h> hit the warning); the matrix
   moved to gcc-11 in #169 (where the heuristic suppresses it anyway),
   and -isystem now suppresses it generally on all toolchains.
   Two layers of belt + suspenders -> just the belt.

Verified locally on macOS: a full ``./blade build ...`` (2118 actions)
succeeds; emitted compile lines have ``-isystem<path>`` for every
thirdparty include dir and unchanged ``-I<path>`` for flare's own
export_incs.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-04 13:28:59 +08:00
CHEN FengandClaude Opus 4.7 154c68adcc thirdparty/foreign_build: source cmake's CC/CXX from the resolved toolchain (#170)
* thirdparty/foreign_build: source cmake's CC/CXX from the resolved toolchain

cmake_build hard-coded ``CC=gcc CXX=g++`` for every cmake subbuild
(glog, jsoncpp, fmt, etc.), so the thirdparty layer always invoked
the distro-default compiler regardless of what blade had picked at
config time.

This was previously masked because:

1. flare's BLADE_ROOT doesn't declare a cc_toolchain_config, so blade
   falls back to shutil.which('gcc') -- on a stock ubuntu_22 runner
   that's gcc-11 (the distro default), which happens to match what
   the cmake subbuilds were also hardcoding.
2. flare's CI workflow used to pass ``CC=gcc-10 CXX=g++-10`` as a shell
   env prefix; blade itself ignores it (no env handling), but the cmake
   subbuild *did* see it -- through the shell, not the hardcoded
   prefix. So foreign_cc and flare-side disagreed but only on a
   compiler version no longer in the matrix after #168.

After #168 + #169 the gap is benign for now (everything is gcc-11 or
clang anyway), but the hardcoded values would silently desync the
moment anyone:

- adds a cc_toolchain_config(name='ci', cc='gcc-13', ...) to BLADE_ROOT
  and runs ``./blade --cc-toolchain=ci`` -- flare libs build with
  gcc-13, glog/fmt/jsoncpp etc. build with gcc-11
- pins a non-default compiler via blade.getenv('CC', 'gcc')
- ports flare to a system where 'gcc' is not the desired compiler

Read CC/CXX from blade.cc_toolchain.tool() at config time. The proxy
returns the full path of whatever blade resolved (cc_toolchain_config
> shutil.which('gcc')). Verified locally: a forced glog rebuild now
emits ``CXX=/usr/bin/g++ CC=/usr/bin/gcc`` (the full resolved path)
instead of the bare names. Behaviour on the current CI matrix is
unchanged; the divergence is just no longer possible.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* thirdparty/foreign_build: also pass toolchain CC/CXX to autotools configure

Mirror of the previous commit for the autotools path. Without this,
configure pulls CC/CXX from $CC/$CXX in the environment (which blade
itself doesn't set) or falls back to its own autoconf detection --
both of which can disagree with whatever blade.cc_toolchain.tool()
resolved at config time. Setting CC/CXX on the configure command line
puts the thirdparty layer in lockstep with the rest of the build,
matching the cmake fix.

Verified on macOS local: a forced curl rebuild succeeds and the
emitted configure rule now contains ``CC=/usr/bin/gcc CXX=/usr/bin/g++``
(the full resolved path), rather than relying on environment leakage.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-04 08:07:12 +08:00
CHEN FengandClaude Opus 4.7 802aa0b0b3 ci(test): tighten per-test timeout via --test-timeout-multiplier (#169)
* ci(test): tighten per-test timeout via blade --test-timeout-multiplier

Three coupled changes:

1. **Bump thirdparty/blade.zip** from a76de22 to 9306687, picking up
   three new blade features merged today:
   - #1241 live test output streamed to <run_dir>/blade-test.log
   - #1244 blade.getenv() for opt-in env-driven config (config phase)
   - #1246 --test-timeout-multiplier CLI flag (run-time test-timeout scaling)

2. **Lower global_config.test_timeout from 600s to 60s.** The old 600s
   was a "fits all environments" compromise that meant a hung fast unit
   test took 10+ minutes to fail (witness: dumper_integration_test
   recently stuck 60+ min on a flaky ubuntu_22 runner). Profiling on
   M2 release/-O2 shows the slowest legitimate tests today are CPU-heavy
   ones around 30-40s -- and those are all already exclusive=True so
   they don't contend with the parallel pool. 60s gives ~50% headroom
   over the slowest legit case; anything blowing past it is almost
   certainly hung and worth failing fast.

3. **Scale up via --test-timeout-multiplier=5 in CI.** GHA runners
   are slower and contended; 5x = 300s effective ceiling. Tight enough
   that a real hang fails inside the GH step timeout (~6 hours), loose
   enough to absorb routine CI variance.

Net effect: dev-machine timeouts catch hangs in 60s, CI absorbs runner
slowness, and the cap-on-slowness lives in the CI workflow (where it
belongs -- it's a property of the runner) rather than in BLADE_ROOT
(which describes the project's intrinsic test cost).

Verified locally: ./blade test ... --full-test passes all 235 tests
under the 60s baseline.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(build): drop unconditional -lpthread from gtest_libs on macOS

Every cc_test that pulled gtest got '-lpthread' appended to the link
line regardless of platform. On macOS Apple's ld then warns:

  ld: warning: ignoring duplicate libraries: '-lpthread'

(pthread is part of libSystem and auto-linked; the explicit -lpthread
is redundant and triggers the duplicate-library diagnostic on the new
Xcode 16 linker).

Wrap gtest_libs in a lambda that adds '#pthread' only when targeting
Linux, matching the pattern already used for chrono / time_keeper /
thread_pool and the thirdparty glog/gflags/etc. cc_test entries.

Verified locally: every cc_test ninja file regenerated after this
change has '-lpthread' gone on macOS; nothing changes on Linux
(blade.cc_toolchain.target_os == 'linux' branch still emits it).

Note: -lrt warnings observed in CI still appear, but those come from
foreign_cc subbuilds (jemalloc / lz4 configure scripts) honoring the
host environment via autoconf detection; they're internal to those
packages, not from flare's link lines.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(build): guard unconditional '-ldl' / '-lm' with Linux check

Three places listed POSIX libraries as deps without a target_os check:

- flare/base/internal:cpu      -> '#dl'  (uses dlsym for symbol lookup)
- flare/base/internal:curl     -> '#dl'  (curl bindings)
- thirdparty/openssl:crypto    -> '#dl'  (openssl needs dlopen at runtime)
- thirdparty/protobuf-3.4.1    -> '#m'   (math symbols)

On macOS these symbols all live in libSystem and are auto-linked; the
explicit '-ldl' / '-lm' is redundant. They don't typically trigger ld's
"ignoring duplicate libraries" warning the way unconditional '#pthread'
in BLADE_ROOT.gtest_libs did (since the .tbd stubs are designed for
this redundancy), but the inconsistency was confusing and a single
"-l<x>" arriving from two places anywhere downstream would tip into a
real duplicate warning.

Wrap each in the existing `target_os == 'linux'` / `_is_linux` pattern
used elsewhere in the file. macOS link lines no longer contain
'-ldl'/'-lm'; Linux is unchanged.

Note: gperftools' BUILD still has unconditional '#pthread'/'#rt', but
gperftools is excluded on darwin entirely (the macOS port routes
through jemalloc instead), so those don't matter on macOS.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-04 05:53:22 +08:00
CHEN FengandClaude Opus 4.7 ed1e854280 ci: bump oldest-supported gcc to 11; make matrix.cc actually pick the matrix version (#168)
* ci: make matrix.cc actually pick the matrix gcc version

The Build and Test workflow's matrix promises gcc-10 on ubuntu_22 and
gcc-13 on ubuntu_24, but until now both jobs were actually compiling
with the distro default (gcc-11 / gcc-13) for the bulk of the build.

Cause: ``apt-get install gcc-10`` only installs the versioned binaries
(``/usr/bin/gcc-10`` etc.); ``/usr/bin/gcc`` keeps pointing at the
system default. Blade resolves the compiler via ``shutil.which('gcc')``
and reads no environment variable, so the ``CC=gcc-10 CXX=g++-10`` env
prefix on the Build step was decorative for the main build. Only
thirdparty foreign_cc subbuilds, which read $CC, actually saw gcc-10.

Effect on ubuntu_22 (the more important case -- gcc-10 is the
oldest-supported compiler the matrix claims to cover): the matrix
labelled "gcc-10" was silently testing gcc-11 for everything blade
compiled directly. Real gcc-10 compatibility was not under test.

Fix: register the matrix version with update-alternatives in Install
dependencies. After this, ``which gcc`` resolves to the matrix
version; both blade's compiler discovery and ccache's dispatch see
the right one. Drop the decorative ``CC=...`` prefixes from the Build
and Run tests steps now that they are no longer load-bearing (and
would have been misleading to future readers).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* thirdparty/glog: patch self-referencing deprecated overload for gcc-10

PR #168 switched ubuntu_22_04 from the distro-default gcc-11 (which the
prior workflow was silently using) to the actually-promised gcc-10. That
flipped the lid on a long-standing latent issue in glog 0.7.1:

  glog/logging.h:494-505 declares a [[deprecated]] type alias
  `CustomPrefixCallback` inside a `#pragma GCC diagnostic
  push/ignored "-Wdeprecated-declarations"` block, then closes the
  pragma block, then declares a [[deprecated]] overload of
  `InitGoogleLogging` whose parameter type is `CustomPrefixCallback`.

gcc 11+ has a heuristic that suppresses deprecation warnings inside a
deprecated declaration's signature, so the overload's self-reference
stays silent. gcc 10 lacks that heuristic and fires
`-Werror=deprecated-declarations` on every TU pulling in <glog/logging.h>.

Patch (silence_self_deprecation.patch) moves the overload inside the
existing pragma block. No behavior change for callers; only the
internal self-reference stops warning. macOS clang and gcc 13 are
unaffected -- the diagnostic-suppression region simply covers slightly
more code on those toolchains too.

Verified by dry-run + real apply against a fresh extraction of
glog-0.7.1.tar.gz; the patched header preserves the original semantics.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* ci: bump oldest-supported gcc from 10 to 11

PR #168 made the matrix actually pick gcc-${{ matrix.cc }} instead of the
distro default (which was silently gcc-11 on ubuntu_22). With gcc-10 truly
exercised, two real incompatibilities surfaced:

1. flare/fiber/detail/scheduling_group.cc uses std::atomic<int>::wait,
   notify_one, notify_all (C++20 P1135). libstdc++ implements these
   starting in 11.1 only; gcc-10's <atomic> has no such members. PR #158
   introduced the dependency when it replaced the Linux-only futex(2)
   path with the portable C++20 primitives to make the macOS port work.

2. Several .cc files reference POSIX `unlink` without
   `#include <unistd.h>`. Newer libstdc++ stopped transitively pulling
   unistd through other headers.

Both are gcc-10 blockers we don't want to walk back -- atomic wait is
materially better than the futex path (portable, no syscall asymmetry).
Bump the matrix to gcc-11 and update the comment.

gcc-11 is the ubuntu-22.04 default, so the update-alternatives plumbing
becomes a no-op for this version but stays in place to keep future bumps
straightforward.

Keep the glog self-deprecation patch -- on gcc-11+ it is a no-op (the
heuristic suppresses the warning anyway), but it shields a local gcc-10
attempt from breaking on glog before the user even gets to the real
flare-side incompatibilities.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-04 00:51:16 +08:00
CHEN Feng 51cf5a5587 ci: unflake timing tests + bump deprecated actions + blade.zip (3 fixes)
Three CI hygiene fixes bundled in one PR.

* **Flaky timing assertions widened**. Two tests had ASSERT_NEAR / EXPECT_NEAR
  with budgets too tight for shared-VM CI runners:
  - flare/net/http/binlog_dry_runner_integration_test:220 -- 20ms -> 50ms
    (observed 136ms vs expected 100ms on GHA).
  - flare/io/native/stream_connection_test:411 and :491 (WriteBandwidthLimit
    / ReadBandwidthLimit) -- 1s -> 2s (observed 8.4s vs expected 7s).
  Both tests still validate order-of-magnitude correctness; just give
  shared-runner jitter the headroom it needs.

* **Deprecated GitHub Actions bumped** to silence the "Node.js 20 actions
  are deprecated" warning (forced upgrade scheduled for Sept 2026):
  - actions/checkout: @v2 / @v3 / @master -> @v6 (Node 24)
  - actions/setup-python: @v2 -> @v6

* **thirdparty/blade: bump blade.zip to master a76de22**. Picks up three
  upstream blade-build fixes that surfaced after master a8d12b2 wired in
  the new cc_check_undefined static check:
  - #1238: add __tls_get_addr / __tls_get_offset to undefined-check
    baseline (ld-linux.so injects these); unbreak stale CheckUndefinedDiff
    unit tests; defer PrebuiltCcLibrary._emit_archive_syms to generate
    phase (was tripping the __build_code-None invariant in
    Target.before_generate).
  - #1239: treat uppercase 'V' / 'W' nm symbol types as defined, not
    ambient -- they're weak DEFINED, not weak UNDEFINED.
  - #1240: treat lowercase 'u' as defined (GNU "unique global"
    extension) -- fmt's basic_data<void>::*_padding_shifts and ~40 other
    template-static-data symbols were silently dropped from libfmt.a's
    syms set, breaking any cc_library that transitively used fmt.
2026-06-03 07:19:42 +08:00
CHEN Feng 8cc6c17c63 thirdparty/blade: bump blade.zip to current master (a8d12b2) (#161)
The vendored blade in `thirdparty/blade/blade.zip` was at commit
82ba580 (the export_map → -exported_symbols_list change), which
predates the dep-check improvements merged later the same day:

  82ba580  ← bundled here previously
  9a0138e  Cache ToolChain.get_cc_target_arch (#1224)
  6db819c  incchk: cut false positives in unused-deps + docs (#1231)
  7f182fa  feat(cc): decouple undefined-symbol checking (#1225) (#1233)
  e4e0c8b  docs(cc): document static undefined-symbol check (#1234)
  a8d12b2  docs(cc): two more missing-dep cases + log demote (#1237)  ← now bundled

User-visible change: `./blade build flare/...` now reports the same
dependency notices that the upstream master blade does. With the
older bundle, a full `flare/...` build surfaced 62 Unused-dep notices
that the four auto-exemption rules introduced in #1231 already
handle (header re-export across umbrella + sub-target, export_incs-
relative paths, foreign_cc_library header-less auto-exempt, no-
scannable-source skip). Re-bumping clears them without any BUILD
edits.

Numbers on macOS arm64, -j10, full `./blade build flare/...`:

  Notice category   Before bump   After bump
  ----------------  -----------   ----------
  Missing-dep                0            0
  Unused-dep                62            0
  Build success                yes (no functional change)
2026-06-02 08:30:25 +08:00
CHEN Feng 1f5675f0df BUILD: clean up blade dep-check notices (246 -> 0) (#159)
* build_rules: let cc_flare_library accept keep_deps

`cc_flare_library` wraps a `.proto` generation step plus the resulting
`cc_library`. The wrapper's outer call doesn't expose blade's
`keep_deps` knob, so any `:protobuf` or `:flare_gen_*` dep that is
structurally required at link/runtime but not directly `#include`d
gets flagged as unused -- with no way to suppress without removing
the dep.

Forward an optional `keep_deps=` arg through to the underlying
`native.cc_library` so consumers can mark intentional link-time-only
deps. No behaviour change when `keep_deps` is not passed.

* BUILD: address blade dep-check notices

Apply the entire build64_release/build.log batch of dependency notices
(246 instances across 49 BUILD files): add deps where headers are
included but undeclared, remove deps where they're never reached by
any #include, and mark intentional-but-not-included deps as
`keep_deps` so blade stops re-flagging them.

After this change a fresh `blade build -p release flare/...` emits 0
notices (down from 246) and a `--generate-dynamic` build still links
clean across all 2376 targets.

Two visibility-related notices intentionally left in place:
  * `flare/rpc:rpc` -> `flare/rpc/protocol/http:http_{filter,handler}`
  * `flare/base:exposed_var_test` -> `//flare/base/write_mostly:metrics`
The source #includes those headers but the dep targets are restricted
to a tighter visibility set. That's a design call (open visibility vs.
hide the include) and not something to paper over here.

* BUILD: drop keep_deps obsoleted by blade dep-check improvements

After patching blade with the three dep-check fixes (blade-build#1226,
#1227, #1228), 71 keep_deps entries (across 46 targets in 19 BUILD
files) are no longer reported as false positives:

* #1226 — targets with no scannable C/C++ source (e.g. cc_flare_library
  wrappers around a .proto, foreign_cc_library, generated-only libs) no
  longer get every dep flagged as unused, since blade has no #include
  corpus to compare against.
* #1227 — headers from libraries with export_incs (notably
  thirdparty/protobuf-3.4.1) are now matched against #include directives
  using the consumer-visible relative path, so includes like
  <google/protobuf/message.h> resolve to the //thirdparty/protobuf
  target. This alone accounts for the majority of the removed keep_deps.
* #1228 — libraries that the user has placed in
  cc_library_config.hdrs_missing_suppress (gtest_main, protoc, ...) are
  now exempt from the unused-deps check by being treated as header-less,
  matching the behaviour of an explicit `hdrs = []`.

Verified with a full release build of flare/...: 0 unused-dep notices
remain. The keep_deps entries that survive are genuine link-only deps
(static-registration factories, link-only main()s, gflags providers).

* headers: add directly-used #includes that were transitively available

These three headers used identifiers from another header without a direct
#include, relying on transitive inclusion (a fragile pattern that breaks
the moment the indirect path drops the include). Make the dependencies
explicit so the blade unused-deps check matches them, and so the headers
keep compiling after upstream cleanups.

  thread_local.h        FLARE_LIKELY      -> flare/base/likely.h
  ref_counted.h         Function<>        -> flare/base/function.h
  sampler.h             FLARE_CHECK_*     -> flare/base/logging.h

* BUILD: drop deps that were never actually used

Each of these targets listed a dep that neither its hdrs nor its srcs
referenced (in some cases the original BUILD even flagged the dep with a
"???" comment). Removed:

  flare/base/internal:hash_map               //flare/base:logging
                                              (file uses internal/logging.h, not the public one)
  flare/base/thread:thread_local             keep_deps //flare/base:likely
  flare/base/thread/thread_local:ref_counted keep_deps //flare/base:function
  flare/base/thread/thread_local/detail:atomic_ptr  //flare/base:align
  flare/base/write_mostly:write_mostly       //flare/base:chrono
  flare/fiber:future                         :fiber_basic
  flare/rpc/binlog:dumper                    //flare/base/internal:index_alloc
                                              (was tagged "???" in the BUILD)
  flare/rpc/internal:sampler                 keep_deps //flare/base:logging
  flare/rpc/protocol/protobuf:rpc_controller_common  :call_context
  flare/rpc/protocol/protobuf:integration_test_*     :protobuf
                                              (transitively from //flare/rpc:rpc)

The keep_deps entries that previously masked these notices are also
gone; the three keep_deps cases above (thread_local, ref_counted,
sampler) were paired with a missing #include rather than an unused dep,
which is fixed in the previous commit.

flare/rpc:http: add a one-line comment explaining the surviving
keep_deps entry (umbrella re-export of the HTTP protocol).

* BUILD: drop keep_deps now obsoleted by foreign_cc_library auto-exempt

These keep_deps entries all listed foreign_cc_library targets (gflags,
gtest/gmock, glog, zlib, fmt, jsoncpp, ctemplate). The upcoming
blade-build patch makes foreign_cc_library targets that register only
an hdr_dir (no explicit hdrs) auto-`declare_header_less`, since the
hdr_dir path stored is the in-source build tree (e.g.
"thirdparty/gflags/gflags") which #include directives never reference,
making the unused-deps check unable to ever match them. With those
targets exempted, the keep_deps entries here become noise.

* BUILD: move keep_deps next to deps and explain every remaining entry

For every target that survives with a keep_deps, reorder the attribute
so it sits immediately after `deps` (instead of after `visibility` or
`link_all_symbols`) and add a comment block — and per-entry inline note
where the entries serve different purposes — describing WHY each entry
cannot be expressed through a normal `#include`. Two patterns recur:

  1) Umbrella facades whose hdrs are ALSO declared by the sub-targets
     they bundle. blade attributes every direct #include to the more
     specific sub-target owner, leaving the umbrella itself uncredited
     for "using" its sub-deps. (fiber, redis, http, hbase{,_client,
     _server}, tracing, rpc/protobuf)

  2) Link-time static-initializer registration with no public header.
     Each `*_protocol` and load-balancer / name-resolver sub-target
     registers itself with ServiceMethodLocator / a protocol-or-NSLB
     registry via static initializers; the consumer needs the static
     init to run at link time but has nothing to `#include`. (rpc:rpc,
     rpc:http, protobuf:{baidu_std,poppy}_protocol, the protocol
     entries of protobuf:protobuf)

No behaviour change; this is documentation + ordering.

* BUILD: drop keep_deps now handled by blade's re-export auto-exemption

With blade's new re-export auto-exemption rule (any target that shares
an `hdrs` declaration with one of its deps treats that dep as
implicitly "used"), the keep_deps entries that existed purely to silence
the umbrella -> sub-target pattern are no longer needed. blade now sees
the umbrella as legitimately depending on every sub-target whose public
header it also re-declares.

Eliminated keep_deps entries (24 across 12 targets):

  flare/fiber:fiber                 6/6   (all sub-libs re-exported)
  flare/net/redis:redis             1/1   (drops entire keep_deps)
  flare/net/hbase:hbase             2/2   (drops entire keep_deps)
  flare/net/hbase:hbase_client      2/3   (one link-time entry kept)
  flare/net/hbase:hbase_server      2/3   (one link-time entry kept)
  flare/net/http:http               3/4   (one link-time entry kept)
  flare/rpc:rpc                     3/6   (three link-time entries kept)
  flare/rpc/tracing:tracing         2/2   (drops entire keep_deps)
  protobuf:protobuf                 3/11  (eight link-time entries kept)

Remaining 17 keep_deps entries are all genuine static-initializer
registrations (NSLB / name-resolver / protocol / service registries)
that hook into a global registry with no public header for the
consumer to `#include`.

* BUILD: privatize self-registration .h files (move from hdrs to srcs)

A library whose sole purpose is to register an implementation with a
runtime registry (NSLB, name resolver, protocol, channel scheme, ...)
has no need for a public header file. Consumers reach the
implementation through the registry at link time, not by `#include`-ing
its type directly. Moving the .h into `srcs` reflects that intent and
makes the target header-less, which blade's existing
`_header_less_target_keys` mechanism automatically exempts from the
unused-deps check -- no `keep_deps` needed.

Privatized targets:

  flare/rpc/load_balancer:round_robin                  NSLB "rr"
  flare/rpc/name_resolver:list                         resolver scheme
  flare/net/http:dry_run_channel                       dry-run HTTP channel
  flare/rpc/protocol/http:http                         HTTP/1.x protocol + service
  flare/rpc/protocol/protobuf:baidu_std_protocol       protocol registration
  flare/rpc/protocol/protobuf:poppy_protocol           protocol registration
  flare/rpc/protocol/protobuf:qzone_protocol           protocol registration
  flare/rpc/protocol/protobuf:proto_over_http_protocol protocol registration
  flare/rpc/protocol/protobuf:std_protocol             protocol registration

Audit method: a target qualified iff the only out-of-target users of
its .h file are its matching `*_test.cc` -- so the public-header
contract was being used only by tests for type-level access.

Cascade effect on keep_deps blocks (12 -> 3):

  flare/rpc:rpc                       all 3 link-time entries removed
  flare/rpc:http (inner)              removed
  flare/net/http:http                 removed
  flare/rpc/protocol/protobuf:protobuf  4 of 7 entries removed
  flare/rpc/protocol/protobuf:baidu_std_protocol  removed
  flare/rpc/protocol/protobuf:poppy_protocol      removed

The three surviving keep_deps blocks still serve targets that DO have
non-test cross-target consumers (e.g. hbase_channel.cc directly
instantiating HbaseClientProtocol, server.cc reaching for
protobuf::Service), so privatizing their headers would break real
callers; keep_deps stays.

* BUILD: drop deps that flowed in transitively (removes last keep_deps)

The remaining keep_deps entries (after privatizing self-registration
headers) were all on umbrella targets that explicitly redeclared a
dep that one of their sub-deps had already pulled in directly. Once
that umbrella-level redundant dep is removed, the keep_deps becomes
unnecessary.

  flare/net/hbase:hbase_client       :hbase_client_protocol via :hbase_channel
  flare/net/hbase:hbase_server       :hbase_server_protocol via :hbase_service
  flare/rpc/protocol/protobuf:protobuf
                                     :service_method_locator + :rpc_meta_proto
                                     via every :*_protocol sub-dep
                                     :service is needed by flare/rpc:server,
                                     which declares the dep directly itself

After this commit, no target in the tree carries a `keep_deps`
annotation, and `blade build -p release flare/...` still reports zero
unused-dep notices.

* BUILD: restore link-time deps lost in the early dep-check cleanup

The first `BUILD: address blade dep-check notices` commit on this
branch took blade's then-noisy "Unused dependency" notices at face
value and dropped any dep whose .h didn't appear as an `#include` --
exactly the false-positive pattern that the later blade patches were
meant to fix. Two real link-time dependencies got swept up before
those patches existed:

  flare/base:compression   gzip / lz4 / snappy / zstd registrations
    SYMPTOM: MakeCompressor("GZIP") returns nullptr; the
    integration_test_{4K,64K,1M} suites crash on
    "Check failed: Compressor nullptr".

  flare/net/redis:nslb_registration   round_robin / name_resolver:list
    SYMPTOM: connecting via the `rr://` or `list://` scheme cannot
    find a registered NSLB / resolver; redis_test crashes inside
    redis_object.h:95 because the connection collapses before a
    typed reply ever arrives.

Re-add both sets of deps. The four compression implementations also
get the same self-registration treatment as the other targets touched
in this branch: `.h` -> `srcs`, `hdrs = []`, so blade auto-exempts
them from the unused-deps check without needing keep_deps.

`blade test -p release flare/... --full-test` -> 230/230 pass.

* BUILD: fix `',#pthread'` typo in thirdparty/protobuf-3.4.1

Leading comma made blade parse the dep as the malformed token
`",#pthread"` instead of the system library `#pthread`, surfacing as
\"Invalid dependency format error\" at parse time. The bug only
triggers on Linux (the `_is_linux` arm of the deps list), which is why
local macOS builds didn't catch it.

Introduced by the early dep-check cleanup commit b4806e4 when an
auto-edit regex inserted a stray separator.
2026-06-01 22:28:59 +08:00
CHEN FengandClaude Opus 4.7 86f175c3c4 Add macOS (darwin/arm64) build support (#158)
* feat(macos): build flare on macOS (darwin/arm64) + thirdparty alignment & bug fixes

Make flare build with both blade and bazel on macOS (Apple Silicon,
darwin/arm64); previously Linux-only. Verified: `blade build flare/...` and
`bazel build //flare/...` (653 targets) both green on macOS arm64.

Third-party / build system:
- Align bazel deps with the verified blade build: glog 0.4.0->0.7.1,
  zlib 1.2.13->1.3.2, openssl 1.0.2u->1.1.1w (1.1 required by HMAC_CTX usage).
- glog: extend the export-guard patch to every header gating <glog/export.h>
  behind GLOG_USE_GLOG_EXPORT, and update CHECK_OP to use
  google::logging::internal::{Make,}CheckOpString.
- foreign_cc macOS fixes: force a real `ar` (rules_foreign_cc defaults AR to
  Apple's libtool, incompatible with autotools' ar-style calls); gate -lrt to
  Linux; pick .dylib vs .so; build nghttp2 static-only (its sandbox dylib
  install_name breaks curl's configure run-time check).
- Register the host preinstalled make toolchain (rules_foreign_cc's bundled
  make segfaults building jemalloc on macOS; blade also uses the system make).
- Track patch files as unpack-rule inputs (foreign_build.bld).
- Silence third-party warnings (external/ and in-repo thirdparty/) via
  per_file_copt.

flare portability:
- IO: new Poller abstraction with epoll (Linux) and kqueue (macOS) backends;
  event_loop/descriptor rewired off raw epoll; eventfd -> pipe notifier.
- net/thread/cpu/rlimit platform guards; OpenSSL 1.1 HMAC_CTX API.
- Add missing `gflags/gflags.h` / `<unistd.h>` includes (were pulled in
  transitively by the old glog).
- gperftools/tcmalloc is Linux-only: excluded on darwin (mirrors blade);
  macOS uses jemalloc.

Bug fixes (also affect Linux):
- base/expected.h: Unexpected::swap referenced a nonexistent member
  (other.unex -> other.unex_); never compiled once instantiated.
- io/detail/writing_buffer_list.cc: FlushTo crashed (CHECK) on a benign drain
  race (head_ stale while tail_ == nullptr); now treats the list as empty.
- base/chrono.{h,cc}: clocks delegated to a hand-rolled clock_gettime that
  mixed clock epochs (broke TimerWorker::wait_until); now use
  std::chrono::*::now(); ReadCoarseSystemClock duration_casts to the clock's
  duration.
- fiber/detail/scheduling_group.cc: spin-wait bound was a hardcoded TSC-tick
  count assuming a GHz-scale TSC; now derived from the measured TSC frequency.
- base/internal/dpc.cc: "Run N DPCs" logged cbs.size() (always 0 at loop exit)
  instead of the accumulated dpcs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fiber: defeat Clang's TLS-base CSE across returns_twice on AArch64

On AArch64, Clang caches the resolved thread_local slot address in a
callee-saved register and reuses it across `[[gnu::returns_twice]]`
calls. `jump_context` may resume the same C++ frame on a different OS
thread, so the cached slot points to the previous worker's TLS region
on resume, and accesses go to the wrong memory.

GCC handles `returns_twice` more conservatively (it re-issues
`mrs tpidr_el0` after the call), which is why Linux flare worked
inlined for years -- Linux + GCC, not "Linux".

Centralize the canonical `jump_context` declaration in a new
`context.h` (so every TU sees the `returns_twice` attribute) and
force the three TLS accessors out-of-line: `[[gnu::noinline]]` makes
each access an ABI call, and ABI rules force the caller to redo the
TLS resolution -- Clang can't CSE across a real function boundary.

Discovered while porting flare to macOS arm64 (Apple Clang), but the
underlying hazard exists on any Clang aarch64 build; GCC users were
just lucky.

* io/kqueue: fix Modify to disable removed filters; stop fanning EV_EOF to opposite direction

Two macOS-port correctness fixes in the kqueue poller, both surfaced
by a flare RPC client that died with STATUS_IO_ERROR on the first
write to a freshly-opened connection.

1. `Modify` now explicitly EV_DISABLEs filters that aren't in the
   new event mask. Unlike Linux epoll (EPOLL_CTL_MOD replaces the
   whole event bitmask in one shot), kqueue registers EVFILT_READ
   and EVFILT_WRITE independently -- a bare EV_ADD on one filter
   does NOT affect the other. Without explicit disable, the kernel
   keeps firing the "removed" filter under level-triggered mode,
   and `OnWritable()` runs on an empty writing buffer, which the
   connection layer mistakes for "remote closed" and kills the
   connection. EV_DISABLE (not EV_DELETE) is what we want -- it
   pauses delivery while preserving the filter's internal readiness
   state, mirroring epoll's behaviour. (EV_DELETE + later EV_ADD on
   a socket that is already readable produces no edge with EV_CLEAR,
   and the reader stalls forever.)

2. `Wait` no longer fans an EV_EOF flag out into both kPollerRead
   and kPollerWrite. EV_EOF on EVFILT_READ just means the peer
   half-closed for reading; the write direction is still usable
   until the next write returns EPIPE. The old fan-out manufactured
   a fake write event whenever the read side EOF'd, kicking
   `OnWritable()` on an empty writing buffer -- same false-disconnect
   chain as #1.

* io/util/socket: SetCloseOnExec must use F_SETFD; rename helper to SetStatusFlags

FD_CLOEXEC is a *file-descriptor* flag (F_GETFD / F_SETFD), not a
file-status flag (F_GETFL / F_SETFL). The existing `SetCloseOnExec`
routed through the generic `SetFlags` helper, which goes through
F_SETFL, and so passed FD_CLOEXEC = 0x01 into the status-flag space.

On Linux glibc, the unsupported bit is silently discarded by F_SETFL,
so this was invisible. On Darwin the kernel actually interprets the
0x01 bit inside the F_SETFL flag space: O_NONBLOCK gets wiped off the
listening socket and O_APPEND gets set. The downstream effect is that
`accept(2)` on the listening socket reverts to blocking and the
server's accept loop hangs forever after the first connection.

Fix `SetCloseOnExec` to use F_GETFD / F_SETFD directly, and rename
the generic helper from `SetFlags` to `SetStatusFlags` so the
descriptor-flag-vs-status-flag distinction is hard to miss next time.
The only remaining caller of the helper is `SetNonBlocking`, which
is correct (O_NONBLOCK *is* a status flag).

* io/native: treat ENOTCONN as transient in FlushWritingBuffer

When a non-blocking TCP socket is in the middle of its `connect(2)`,
Linux returns `EAGAIN` on `write(2)`/`sendmsg(2)`, which flare maps
to `FlushStatus::SystemBufferSaturated` and retries via the write
event. Darwin instead returns `ENOTCONN` ("Socket is not connected")
in the same situation -- the kernel distinguishes "would block on a
connected socket" (EAGAIN) from "not yet connected" (ENOTCONN).

The existing code treated ENOTCONN as a fatal write error, returned
`NothingWritten`, and `Kill(CleanupReason::Disconnect)` immediately
fired. The first RPC on every channel died with STATUS_IO_ERROR.

Fold ENOTCONN into the EAGAIN / EWOULDBLOCK branch so the write is
deferred until the kernel signals writability (which happens when
the connect completes), matching Linux semantics.

* base/write_mostly: order members so mutex outlives TLS wrappers

`WriteMostly` had `tls_buffer_` declared before `mutex`, which means
`mutex` was destroyed *first* (members are destroyed in reverse
declaration order). When `tls_buffer_` was then torn down, each
per-thread `WriteBufferWrapper` ran its destructor and tried to
`std::unique_lock(parent_->mutex)` -- locking an already-destroyed
mutex.

libstdc++ on Linux silently allowed this (the underlying pthread
mutex didn't actually reject), so the bug was invisible.

libc++ on Darwin returns EINVAL from `pthread_mutex_lock`, std::mutex
throws `system_error("mutex lock failed: Invalid argument")`, and
since destructors are noexcept by default the unhandled exception
aborts via std::terminate.

Reorder the members so `tls_buffer_` is the last declared field
(thus the first destroyed): both `mutex` and `exited_thread_combined_`
are still alive while the wrappers merge into them.

* base/deferred_test: initialise bool to avoid UB read

`Deferred.All` declared `bool f4;` and then `ASSERT_FALSE(f4)`
before any store. Reading an uninitialised bool is undefined
behaviour: the value is "indeterminate" and a load of an
indeterminate value is itself UB regardless of which bit pattern
happens to be in the stack slot.

Linux happened to observe zero on the stack and slipped through.
macOS Clang traps on the indeterminate read (SIGTRAP, exit 133),
exposing the bug.

Initialise `bool f4 = false`.

* macOS port: platform-specific test adjustments

A bag of test-only changes that fall out of the macOS port.

  * attribute_test.cc -- SetCurrentAffinity skipped on Darwin.
    Darwin has no pthread_setaffinity_np equivalent and the legacy
    thread_policy_set THREAD_AFFINITY_POLICY is hint-only; the
    `expected == GetCurrentProcessorId()` assertion cannot hold.

  * descriptor_test.cc -- ConcurrentRestartRead skipped on Darwin.
    The test attaches a PipeDesc with Event::Write to the read end
    of a closed-write pipe. Linux epoll never fires EPOLLOUT on
    that fd; macOS kqueue fires EVFILT_WRITE (no write buffer ==
    "has space"). The fire trips a pre-existing race in
    `Descriptor::QueueCleanupCallbackCheck`: FireXxxEvent does not
    consult `cleanup_pending_` before fetch_add, so an event between
    cleanup-task queueing and execution makes the strict CHECK at
    descriptor.cc abort. Fixing that race needs Dekker-style
    ordering between FireXxxEvent and Kill -- bigger scope than
    this batch.

  * writing_datagram_list_test.cc -- shrink the test datagram from
    16384 to 4096 bytes. Darwin's `net.inet.udp.maxdgram` defaults
    to 9216, and sendmsg() rejects larger UDP payloads with
    EMSGSIZE; Linux is happy up to ~64KB.

  * datagram_transceiver_test.cc -- cap the fragment count from
    60'000 to 8192 on Darwin. Still well above IOV_MAX (1024 on
    both libc's) so the "flatten on iovec overflow" path is still
    exercised; total payload now fits under net.inet.udp.maxdgram.

  * uri_matcher_test.cc -- regex pattern `"\\abc.*efg"` used the
    `\a` escape, which is not a valid ECMAScript escape. libstdc++
    accepted it silently (treating it as literal `a`); libc++ on
    Darwin throws regex_error("invalid escaped character") and the
    test aborts. The intended pattern was `abc.*efg`.

  * dirty_hook_test.cc, hooking_mock_test.cc -- skipped on Darwin.
    Both rely on `mprotect`-ing the text segment to writable to
    overwrite a function prologue. macOS arm64 enforces W^X on
    signed code pages: mprotect returns EPERM, the CHECK aborts.
    Toggling JIT-style write-execute would require
    `pthread_jit_write_protect_np`, the
    `com.apple.security.cs.allow-jit` entitlement, and code placed
    in a JIT region -- none of which apply to the regular text
    segment that DirtyHook patches. (The single non-hook subtest
    in hooking_mock_test, `NotEnabled`, still runs.)

* fixup: satisfy clang-format-15 (LLVM style) on the macOS port commits

CI's clang-format-15 (LLVM style) flagged two spots from the macOS
port batch:

  * flare/fiber/detail/context.h: `} // extern "C"` -> `}  // extern "C"`
    (LLVM trailing-comment style wants two spaces before //).

  * flare/io/detail/kqueue_poller.cc: the `read_flags`/`write_flags`
    ternaries were hand-aligned to a column width that clang-format
    didn't pick. Drop the explicit alignment and pull the disabled
    case into a named `disable_flags` local so each assignment fits
    on a single line that clang-format leaves alone.

No behaviour change.

* thirdparty/blade: bump blade.zip for target_arch cache fix

Picks up the toolchain.target_arch caching from
https://github.com/blade-build/blade-build/pull/1224.
BUILD-file load on this workspace drops from 13.2s to 0.25s.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 17:36:21 +08:00
CHEN Feng b2c5e41851 Fix blade error when using python 3.10 (#148)
Fix #111
2024-04-18 19:42:23 +08:00
kang jinci 1d60bd710b feat: support bazel build (#121)
* feat: suppport bazel build

* feat(bazel): add rpc plugin

* code change

* fix comment
2023-07-26 01:34:04 +08:00
kang jinci 3899fef103 fix blade build (#119)
* fix: add object_array target

* fix(blade): fix thirdparty/xxhash and thirdparty/rapidxml

* remove reduce deps
2023-07-15 01:44:17 +08:00
kang jinci 430f7e0c06 Fix compile fail (#81)
* fix: gcc12 compile failed

* Update .gitignore
2022-12-13 22:00:25 +08:00
kang jinci 078ace2278 Fix compile bug and fiber calling with args (#66)
* Fix compile bug

* Fix fiber calling with args and add Fiber CallWithArgs TEST

* Use std::apply and CamelCase

Update fiber_test.cc
2022-05-29 15:05:15 +08:00
Luo Bo 7a69d23947 Disabled libidn when configuring libcurl. (#58) 2021-11-25 12:40:05 +08:00
Luo Bo bad9f62be0 Upgrading blade to #ea03d43. (#34)
Closing #18, #22.
2021-06-18 15:21:53 +08:00
果冻虾仁 fe30705561 Remove dependency to brotlidec when building libcurl. (#33) 2021-06-18 11:13:58 +08:00
Luo Bo e2697cbd2b Using dedicated folder for building script (as far as we can). Stripped all thirdparty/ prefix in #includes. This permits (possible) integration with other building systems. (#29)
* Stripped thirdparty/ prefix when including external headers.

* Introduced dedicated folder for different building systems.;

* Using canonical path for include protobuf's headers.

* Using canonical path for googletest.
2021-06-15 23:07:46 +08:00
Luo Bo f49062154f Getting rid of cmake's package registry. Suppressing gflags from installing to cmake's registry. (#31) 2021-06-14 21:12:44 +08:00
CHEN Feng 1b562391f2 Upgrade blade to fix build errors under WSL2 (#21) 2021-06-03 12:18:01 +08:00
CHEN Feng afc3c72ef8 Do not install python for blade (#20)
Fix #12
Build under WSL2
2021-06-01 00:31:41 +08:00
Luo Bo 99542dc124 Fix build (#15)
* Fixing deps to zlib.

* Forcibly disables libunwind when configuring glog.
2021-05-31 13:44:15 +08:00
Luo Bo f92cb6132e Always use 'lib' as libdir for cmake targets. The default one is not consistent across Linux distros. (#7) 2021-05-29 03:56:21 +08:00
Luo Bo 9cc00d3105 chore: Importing from internal repository. 2021-05-26 14:11:38 +08:00