feat: Introduce stable Bazel build

The initial migration to a Bazel based build. All attempts have been made
to maintain configuration parity with the upstream build.
This commit is contained in:
Connor McEntee 2025-02-22 11:27:13 -07:00
parent 54eaed1d8b
commit 7f192e9919
29 changed files with 6564 additions and 1 deletions

1
.bazelignore Normal file
View file

@ -0,0 +1 @@
examples/

2
.gitignore vendored
View file

@ -98,3 +98,5 @@ test/include/test/jemalloc_test_defs.h
/msvc/projects/*/*/Release*/
/msvc/projects/*/*/Win32/
/msvc/projects/*/*/x64/
bazel-*

165
BUILD.bazel Normal file
View file

@ -0,0 +1,165 @@
load("@rules_cc//cc:defs.bzl", "cc_library")
load("@rules_license//rules:license.bzl", "license")
load("//tools:cc.bzl", "COPTS")
load("//tools:transition.bzl", "PLATFORM", "transition_default_constraints")
####
# Due to the complexity of the build, the overlay is maintained independently.
# See https://github.com/sallustfire/jemalloc/tree/bcr-5.3.0?tab=readme-ov-file#bazel-build-of-jemalloc
####
package(default_applicable_licenses = [":license"])
license(
name = "license",
license_kinds = ["@rules_license//licenses/spdx:BSD-2-Clause"],
license_text = "COPYING",
)
alias(
name = "jemalloc",
actual = ":jemalloc_with_defaults",
visibility = ["//visibility:public"],
)
cc_library(
name = "jemalloc_core",
srcs = [
"src/arena.c",
"src/background_thread.c",
"src/base.c",
"src/bin.c",
"src/bin_info.c",
"src/bitmap.c",
"src/buf_writer.c",
"src/cache_bin.c",
"src/ckh.c",
"src/counter.c",
"src/ctl.c",
"src/decay.c",
"src/div.c",
"src/ecache.c",
"src/edata.c",
"src/edata_cache.c",
"src/ehooks.c",
"src/emap.c",
"src/eset.c",
"src/exp_grow.c",
"src/extent.c",
"src/extent_dss.c",
"src/extent_mmap.c",
"src/fxp.c",
"src/hook.c",
"src/hpa.c",
"src/hpa_hooks.c",
"src/hpdata.c",
"src/inspect.c",
"src/jemalloc.c",
"src/large.c",
"src/log.c",
"src/malloc_io.c",
"src/mutex.c",
"src/nstime.c",
"src/pa.c",
"src/pa_extra.c",
"src/pac.c",
"src/pages.c",
"src/pai.c",
"src/peak_event.c",
"src/prof.c",
"src/prof_data.c",
"src/prof_log.c",
"src/prof_recent.c",
"src/prof_stats.c",
"src/prof_sys.c",
"src/psset.c",
"src/rtree.c",
"src/safety_check.c",
"src/san.c",
"src/san_bump.c",
"src/sc.c",
"src/sec.c",
"src/stats.c",
"src/sz.c",
"src/tcache.c",
"src/test_hooks.c",
"src/thread_event.c",
"src/ticker.c",
"src/tsd.c",
"src/witness.c",
] + select({
"//settings/flags:zone_allocator": ["src/zone.c"],
"//conditions:default": [],
}) +
select({
"//settings/compiler:msvc_compatible": [
"include/msvc_compat/C99/stdbool.h",
"include/msvc_compat/C99/stdint.h",
"include/msvc_compat/strings.h",
"include/msvc_compat/windows_extra.h",
],
"//conditions:default": [],
}) + select({
"//settings/flags:cxx": ["src/jemalloc_cpp.cpp"],
"//conditions:default": [],
}),
hdrs = ["//include/jemalloc"],
copts = ["-Iinclude/jemalloc/internal"] + select({
"//settings/compiler:msvc_compatible": [
"-Iinclude/msvc_compat",
"-Iinclude/msvc_compat/C99",
],
"//conditions:default": [],
}) + COPTS,
includes = ["include"],
linkopts = select({
"@platforms//os:android": ["-ldl"],
"@platforms//os:linux": [
"-ldl",
"-lpthread",
"-lrt",
],
"//conditions:default": [],
}),
local_defines = select({
"//settings:jet": ["JEMALLOC_JET"],
"//conditions:default": [],
}) + select({
"//settings:no_private_namespace": ["JEMALLOC_NO_PRIVATE_NAMESPACE"],
"//conditions:default": [],
}),
tags = ["manual"],
visibility = ["//:__subpackages__"],
deps = ["//include/jemalloc/internal"],
)
transition_default_constraints(
name = "jemalloc_with_defaults",
src = ":jemalloc_core",
platform = PLATFORM,
settings = {},
)
# C_UTIL_INTEGRATION_SRCS from the Makefile which are shared with the integration testlib
cc_library(
name = "utils",
srcs = [
"src/malloc_io.c",
"src/nstime.c",
"src/ticker.c",
],
hdrs = ["//include/jemalloc"],
copts = ["-Iinclude/jemalloc/internal"] + COPTS,
includes = ["include"],
linkopts = select({
"@platforms//os:linux": [
"-lpthread",
"-lrt",
],
"//conditions:default": [],
}),
linkstatic = True,
tags = ["manual"],
visibility = ["//:__subpackages__"],
deps = ["//include/jemalloc/internal"],
)

12
MODULE.bazel Normal file
View file

@ -0,0 +1,12 @@
module(
name = "jemalloc",
version = "5.3.0-bcr.alpha.1",
bazel_compatibility = [">=7.2.1"],
compatibility_level = 5,
)
bazel_dep(name = "aspect_bazel_lib", version = "2.0.0")
bazel_dep(name = "bazel_skylib", version = "1.7.1")
bazel_dep(name = "platforms", version = "0.0.10")
bazel_dep(name = "rules_cc", version = "0.0.17")
bazel_dep(name = "rules_license", version = "1.0.0")

3184
MODULE.bazel.lock generated Normal file

File diff suppressed because it is too large Load diff

62
README.md Normal file
View file

@ -0,0 +1,62 @@
# Bazel build of jemalloc
This is a minimal fork of [jemalloc](https://github.com/jemalloc/jemalloc) to maintain a set of overlay files for
building jemalloc with [Bazel](https://bazel.build/).
The upstream jemalloc build performs a number of feature detection steps in the configure script. All of which need to be
statically declared via platform and compiler constraints. Some of these have been made configurable under
//settings, but the list is not exhaustive. An attempt has been made to default to logical values assuming the most
common configurations. But these assumptions cannot satisfy all cases in the wild and may break on some systems.
Contributors are encouraged to open MRs to add more configuration options to //settings/platform.
## Usage
See the [examples/BUILD.bazel](examples/BUILD.bazel) file for examples of how to consume `@jemalloc`.
## Notes
- **//settings/flags:jemalloc_prefix (--with-jemalloc-prefix):** In contrast to the make build, this defaults to having
no prefix. The original reasoning was that jemalloc was likely to replace malloc on linux but not MacOS or Windows.
In practice in Bazel, this forcibly bifurcates the API based on target platform making the cc_library more difficult
to consume by cross-platform downstream targets. Anyone wanting to eject jemalloc as an .so will likely want to
reintroduce this behavior.
- **//settings/platform:lg_vaddr:** Defaults to the hard-coded cross compilation value of 57 from the configure script.
If targeting a 32-bit platform, this should be explicitly set.
- **glibc:** Assumes a modern version. If jemalloc is compiled to be the default allocator on linux, it assumes glibc
and some publicly exposed symbols can be wrapped: __malloc_hook, __realloc_hook, __free_hook, __memalign_hook.
However, they are deprecated since glibc 2.34. The jemalloc source likely needs to be updated to reflect this.
Platform configurations that have defaults that are applied via transition.
- //settings/flags:enable_zone_allocator
- //settings/platform:glibc_overrides_support
- //settings/platform:lg_page
- //settings/platform:memalign_support
- //settings/platform:malloc_size_support
- //settings/platform:usable_size_const
- //settings/platform:valloc_support
## Validated Platforms
- Ubuntu 20.04 & 22.04
- Debian 10
- MacOS 15 (M3)
## Known Issues
- **Windows:** An effort to was made to translate upstream MSVC configuration, but it has not been validated and will
likely fail.
- **FreeBSD:** An effort was made to translate existing autoconf feature detection to Bazel config settings, but no
attempt has been made to build on FreeBSD.
- **Centos 7:** Fails due to the lack of defining `JEMALLOC_MADV_FREE`. Though, the original build does not set it when
`MADV_FREE` is present. Supporting both and being faithful to the configure script would require an additional
platform setting.
- C++ compilation might be broken for LLVM around detecting libstdc++.
## Contributing
Before contributing new versions or updates to the Bazel Central Registry, these contributions should be made as Merge
Requests here:
- Fork the repository targeting the existing BCR release branch (e.g `bcr-5.3.0`) for the jemalloc version or create
a new one
- Verify the that all tests pass on the supported platforms e.g. `bazel test //...`
- Open a Merge Request

44
examples/BUILD.bazel Normal file
View file

@ -0,0 +1,44 @@
load("@rules_cc//cc:defs.bzl", "cc_test")
load("@jemalloc//settings:config.bzl", "jemalloc")
# Case 1: Test libc malloc can be replaced
cc_test(
name = "test_1_basic",
size = "small",
srcs = ["test_basic.c"],
malloc = "@jemalloc",
)
# Case 2: Test that the jemalloc API can be used
cc_test(
name = "test_2_api",
size = "small",
srcs = ["test_api.c"],
malloc = "@jemalloc",
)
# Case 3: Test convenience rule can modify the library build settings
jemalloc(
name = "jemalloc_custom",
cache_oblivious = "False",
cxx = "False",
log = "True",
stats = "False",
without_export = "False",
)
cc_test(
name = "test_3_config",
size = "small",
srcs = ["test_basic.c"],
malloc = ":jemalloc_custom",
)
# Case 4: Optional features are gated by config settings
cc_test(
name = "test_4_requires_stats",
size = "small",
srcs = ["test_api.c"],
args = ["--expect-stats-unavailable"],
malloc = ":jemalloc_custom",
)

12
examples/MODULE.bazel Normal file
View file

@ -0,0 +1,12 @@
module(
name = "jemalloc_examples",
)
bazel_dep(name = "jemalloc")
local_path_override(
module_name = "jemalloc",
path = "..",
)
bazel_dep(name = "platforms", version = "0.0.10", dev_dependency = True)
bazel_dep(name = "rules_cc", version = "0.0.17", dev_dependency = True)

573
examples/MODULE.bazel.lock generated Normal file
View file

@ -0,0 +1,573 @@
{
"lockFileVersion": 18,
"registryFileHashes": {
"https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
"https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
"https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
"https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915",
"https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
"https://bcr.bazel.build/modules/abseil-cpp/20240116.1/source.json": "9be551b8d4e3ef76875c0d744b5d6a504a27e3ae67bc6b28f46415fd2d2957da",
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.0.0/MODULE.bazel": "e118477db5c49419a88d78ebc7a2c2cea9d49600fe0f490c1903324a2c16ecd9",
"https://bcr.bazel.build/modules/aspect_bazel_lib/2.0.0/source.json": "ccfe2217c5218a1652c2f740eeaacb14e0632923f797b7c14d403018e2984deb",
"https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd",
"https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
"https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d",
"https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d",
"https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a",
"https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58",
"https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b",
"https://bcr.bazel.build/modules/bazel_features/1.21.0/source.json": "3e8379efaaef53ce35b7b8ba419df829315a880cb0a030e5bb45c96d6d5ecb5f",
"https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
"https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a",
"https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
"https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
"https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686",
"https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a",
"https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5",
"https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d",
"https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651",
"https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138",
"https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953",
"https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
"https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
"https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
"https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
"https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
"https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/source.json": "41e9e129f80d8c8bf103a7acc337b76e54fad1214ac0a7084bf24f4cd924b8b4",
"https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
"https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
"https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d",
"https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
"https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
"https://bcr.bazel.build/modules/platforms/0.0.10/source.json": "f22828ff4cf021a6b577f1bf6341cb9dcd7965092a439f64fc1bb3b7a5ae4bd5",
"https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
"https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
"https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
"https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814",
"https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d",
"https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
"https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c",
"https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d",
"https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df",
"https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e",
"https://bcr.bazel.build/modules/protobuf/29.0/source.json": "b857f93c796750eef95f0d61ee378f3420d00ee1dd38627b27193aa482f4f981",
"https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
"https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
"https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/source.json": "be4789e951dd5301282729fe3d4938995dc4c1a81c2ff150afc9f1b0504c6022",
"https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206",
"https://bcr.bazel.build/modules/re2/2023-09-01/source.json": "e044ce89c2883cd957a2969a43e79f7752f9656f6b20050b62f90ede21ec6eb4",
"https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8",
"https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e",
"https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
"https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002",
"https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191",
"https://bcr.bazel.build/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac",
"https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
"https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
"https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a",
"https://bcr.bazel.build/modules/rules_cc/0.0.17/source.json": "4db99b3f55c90ab28d14552aa0632533e3e8e5e9aea0f5c24ac0014282c2a7c5",
"https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
"https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
"https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
"https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
"https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e",
"https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
"https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86",
"https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39",
"https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6",
"https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31",
"https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a",
"https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6",
"https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
"https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2",
"https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
"https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2",
"https://bcr.bazel.build/modules/rules_java/8.6.1/source.json": "f18d9ad3c4c54945bf422ad584fa6c5ca5b3116ff55a5b1bc77e5c1210be5960",
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
"https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
"https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
"https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d",
"https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4",
"https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0",
"https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197",
"https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59",
"https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3",
"https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5",
"https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0",
"https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
"https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c",
"https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb",
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a",
"https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
"https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
"https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73",
"https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2",
"https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1",
"https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
"https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
"https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
"https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
"https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
"https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
"https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7",
"https://bcr.bazel.build/modules/rules_python/0.40.0/source.json": "939d4bd2e3110f27bfb360292986bb79fd8dcefb874358ccd6cdaa7bda029320",
"https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
"https://bcr.bazel.build/modules/rules_shell/0.2.0/source.json": "7f27af3c28037d9701487c4744b5448d26537cc66cdef0d8df7ae85411f8de95",
"https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
"https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c",
"https://bcr.bazel.build/modules/stardoc/0.5.4/MODULE.bazel": "6569966df04610b8520957cb8e97cf2e9faac2c0309657c537ab51c16c18a2a4",
"https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef",
"https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c",
"https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7",
"https://bcr.bazel.build/modules/stardoc/0.7.1/source.json": "b6500ffcd7b48cd72c29bb67bcac781e12701cc0d6d55d266a652583cfcdab01",
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
"https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d",
"https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198"
},
"selectedYankedVersions": {},
"moduleExtensions": {
"@@aspect_bazel_lib+//lib:extensions.bzl%toolchains": {
"general": {
"bzlTransitiveDigest": "ASDZiXdUwWSg7jAktdoeBNRnm4A0VU1Dj+00qlwez/8=",
"usagesDigest": "QUEoJGaYUpyluk+Ep1sVxUKepcyatzY1uMyc8HHodRI=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {
"copy_directory_darwin_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
"attributes": {
"platform": "darwin_amd64"
}
},
"copy_directory_darwin_arm64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
"attributes": {
"platform": "darwin_arm64"
}
},
"copy_directory_freebsd_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
"attributes": {
"platform": "freebsd_amd64"
}
},
"copy_directory_linux_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
"attributes": {
"platform": "linux_amd64"
}
},
"copy_directory_linux_arm64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
"attributes": {
"platform": "linux_arm64"
}
},
"copy_directory_windows_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo",
"attributes": {
"platform": "windows_amd64"
}
},
"copy_directory_toolchains": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_toolchains_repo",
"attributes": {
"user_repository_name": "copy_directory"
}
},
"copy_to_directory_darwin_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
"attributes": {
"platform": "darwin_amd64"
}
},
"copy_to_directory_darwin_arm64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
"attributes": {
"platform": "darwin_arm64"
}
},
"copy_to_directory_freebsd_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
"attributes": {
"platform": "freebsd_amd64"
}
},
"copy_to_directory_linux_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
"attributes": {
"platform": "linux_amd64"
}
},
"copy_to_directory_linux_arm64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
"attributes": {
"platform": "linux_arm64"
}
},
"copy_to_directory_windows_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo",
"attributes": {
"platform": "windows_amd64"
}
},
"copy_to_directory_toolchains": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_toolchains_repo",
"attributes": {
"user_repository_name": "copy_to_directory"
}
},
"jq_darwin_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
"attributes": {
"platform": "darwin_amd64",
"version": "1.7"
}
},
"jq_darwin_arm64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
"attributes": {
"platform": "darwin_arm64",
"version": "1.7"
}
},
"jq_linux_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
"attributes": {
"platform": "linux_amd64",
"version": "1.7"
}
},
"jq_linux_arm64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
"attributes": {
"platform": "linux_arm64",
"version": "1.7"
}
},
"jq_windows_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo",
"attributes": {
"platform": "windows_amd64",
"version": "1.7"
}
},
"jq": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_host_alias_repo",
"attributes": {}
},
"jq_toolchains": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_toolchains_repo",
"attributes": {
"user_repository_name": "jq"
}
},
"yq_darwin_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
"attributes": {
"platform": "darwin_amd64",
"version": "4.25.2"
}
},
"yq_darwin_arm64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
"attributes": {
"platform": "darwin_arm64",
"version": "4.25.2"
}
},
"yq_linux_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
"attributes": {
"platform": "linux_amd64",
"version": "4.25.2"
}
},
"yq_linux_arm64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
"attributes": {
"platform": "linux_arm64",
"version": "4.25.2"
}
},
"yq_linux_s390x": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
"attributes": {
"platform": "linux_s390x",
"version": "4.25.2"
}
},
"yq_linux_ppc64le": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
"attributes": {
"platform": "linux_ppc64le",
"version": "4.25.2"
}
},
"yq_windows_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo",
"attributes": {
"platform": "windows_amd64",
"version": "4.25.2"
}
},
"yq": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_host_alias_repo",
"attributes": {}
},
"yq_toolchains": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_toolchains_repo",
"attributes": {
"user_repository_name": "yq"
}
},
"coreutils_darwin_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
"attributes": {
"platform": "darwin_amd64",
"version": "0.0.23"
}
},
"coreutils_darwin_arm64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
"attributes": {
"platform": "darwin_arm64",
"version": "0.0.23"
}
},
"coreutils_linux_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
"attributes": {
"platform": "linux_amd64",
"version": "0.0.23"
}
},
"coreutils_linux_arm64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
"attributes": {
"platform": "linux_arm64",
"version": "0.0.23"
}
},
"coreutils_windows_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo",
"attributes": {
"platform": "windows_amd64",
"version": "0.0.23"
}
},
"coreutils_toolchains": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_toolchains_repo",
"attributes": {
"user_repository_name": "coreutils"
}
},
"bsd_tar_linux_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
"attributes": {
"platform": "linux_amd64"
}
},
"bsd_tar_linux_arm64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
"attributes": {
"platform": "linux_arm64"
}
},
"bsd_tar_windows_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
"attributes": {
"platform": "windows_amd64"
}
},
"bsd_tar_host": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%bsdtar_binary_repo",
"attributes": {
"platform": "host"
}
},
"bsd_tar_toolchains": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:tar_toolchain.bzl%tar_toolchains_repo",
"attributes": {
"user_repository_name": "bsd_tar"
}
},
"expand_template_darwin_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
"attributes": {
"platform": "darwin_amd64"
}
},
"expand_template_darwin_arm64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
"attributes": {
"platform": "darwin_arm64"
}
},
"expand_template_freebsd_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
"attributes": {
"platform": "freebsd_amd64"
}
},
"expand_template_linux_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
"attributes": {
"platform": "linux_amd64"
}
},
"expand_template_linux_arm64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
"attributes": {
"platform": "linux_arm64"
}
},
"expand_template_windows_amd64": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo",
"attributes": {
"platform": "windows_amd64"
}
},
"expand_template_toolchains": {
"repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_toolchains_repo",
"attributes": {
"user_repository_name": "expand_template"
}
}
},
"recordedRepoMappingEntries": [
[
"aspect_bazel_lib+",
"aspect_bazel_lib",
"aspect_bazel_lib+"
],
[
"aspect_bazel_lib+",
"bazel_skylib",
"bazel_skylib+"
],
[
"aspect_bazel_lib+",
"bazel_tools",
"bazel_tools"
]
]
}
},
"@@platforms//host:extension.bzl%host_platform": {
"general": {
"bzlTransitiveDigest": "xelQcPZH8+tmuOHVjL9vDxMnnQNMlwj0SlvgoqBkm4U=",
"usagesDigest": "SeQiIN/f8/Qt9vYQk7qcXp4I4wJeEC0RnQDiaaJ4tb8=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {
"host_platform": {
"repoRuleId": "@@platforms//host:extension.bzl%host_platform_repo",
"attributes": {}
}
},
"recordedRepoMappingEntries": []
}
},
"@@rules_java+//java:rules_java_deps.bzl%compatibility_proxy": {
"general": {
"bzlTransitiveDigest": "84xJEZ1jnXXwo8BXMprvBm++rRt4jsTu9liBxz0ivps=",
"usagesDigest": "jTQDdLDxsS43zuRmg1faAjIEPWdLAbDAowI1pInQSoo=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {
"compatibility_proxy": {
"repoRuleId": "@@rules_java+//java:rules_java_deps.bzl%_compatibility_proxy_repo_rule",
"attributes": {}
}
},
"recordedRepoMappingEntries": [
[
"rules_java+",
"bazel_tools",
"bazel_tools"
]
]
}
},
"@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
"general": {
"bzlTransitiveDigest": "sFhcgPbDQehmbD1EOXzX4H1q/CD5df8zwG4kp4jbvr8=",
"usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {
"com_github_jetbrains_kotlin_git": {
"repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository",
"attributes": {
"urls": [
"https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip"
],
"sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88"
}
},
"com_github_jetbrains_kotlin": {
"repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository",
"attributes": {
"git_repository_name": "com_github_jetbrains_kotlin_git",
"compiler_version": "1.9.23"
}
},
"com_github_google_ksp": {
"repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository",
"attributes": {
"urls": [
"https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip"
],
"sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d",
"strip_version": "1.9.23-1.0.20"
}
},
"com_github_pinterest_ktlint": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
"attributes": {
"sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985",
"urls": [
"https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint"
],
"executable": true
}
},
"rules_android": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806",
"strip_prefix": "rules_android-0.1.1",
"urls": [
"https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip"
]
}
}
},
"recordedRepoMappingEntries": [
[
"rules_kotlin+",
"bazel_tools",
"bazel_tools"
]
]
}
}
}
}

156
examples/test_api.c Normal file
View file

@ -0,0 +1,156 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jemalloc/jemalloc.h>
#include <errno.h>
#include <getopt.h>
void print_usage(const char* prog_name) {
printf("Usage: %s [options]\n", prog_name);
printf("Options:\n");
printf(" -h, --help Show this help message\n");
printf(" -v, --verbose Enable verbose output\n");
printf(" --expect-stats-unavailable Expect stats to be unavailable (exit 0 if unavailable, 1 if not)\n");
printf(" By default, test expects stats to be available\n");
}
/*
* This function explicitly tests stats functionality and optionally prints available stats
* which can be disabled with --disable-stats
* Returns 0 if stats are available, 1 if stats are disabled
*/
int test_stats_functionality(int verbose) {
size_t allocated, active, resident, metadata, mapped, retained;
size_t sz = sizeof(size_t);
int ret;
// Try to access stats.allocated - will fail if stats are disabled
ret = mallctl("stats.allocated", &allocated, &sz, NULL, 0);
if (ret != 0) {
fprintf(stderr, "Stats error: Failed to get stats.allocated: %s (error code: %d)\n",
strerror(ret), ret);
if (ret == ENOENT) {
fprintf(stderr, "This indicates jemalloc was compiled with --disable-stats\n");
}
return 1; // Stats are unavailable
}
// Stats are available, print them if verbose mode
if (verbose) {
printf("\nJemalloc Memory Stats:\n");
printf(" Allocated: %zu bytes (%.2f MB)\n", allocated, (double)allocated / (1024 * 1024));
// Get additional stats and print them when available
if (mallctl("stats.active", &active, &sz, NULL, 0) == 0) {
printf(" Active: %zu bytes (%.2f MB)\n", active, (double)active / (1024 * 1024));
}
if (mallctl("stats.resident", &resident, &sz, NULL, 0) == 0) {
printf(" Resident: %zu bytes (%.2f MB)\n", resident, (double)resident / (1024 * 1024));
}
if (mallctl("stats.metadata", &metadata, &sz, NULL, 0) == 0) {
printf(" Metadata: %zu bytes (%.2f MB)\n", metadata, (double)metadata / (1024 * 1024));
}
if (mallctl("stats.mapped", &mapped, &sz, NULL, 0) == 0) {
printf(" Mapped: %zu bytes (%.2f MB)\n", mapped, (double)mapped / (1024 * 1024));
}
if (mallctl("stats.retained", &retained, &sz, NULL, 0) == 0) {
printf(" Retained: %zu bytes (%.2f MB)\n", retained, (double)retained / (1024 * 1024));
}
}
return 0; // Stats are available
}
int main(int argc, char** argv) {
int expect_stats_available = 1; // Default: expect stats to be available
int verbose = 0; // Default: non-verbose output
// Define long options
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"verbose", no_argument, 0, 'v'},
{"expect-stats-unavailable", no_argument, 0, 'u'},
{0, 0, 0, 0}
};
// Parse command line options
int opt;
int option_index = 0;
while ((opt = getopt_long(argc, argv, "hv", long_options, &option_index)) != -1) {
switch (opt) {
case 'h':
print_usage(argv[0]);
return 0;
case 'v':
verbose = 1;
break;
case 'u':
expect_stats_available = 0; // Expect stats to be unavailable
break;
default:
print_usage(argv[0]);
return 2;
}
}
// Basic check to ensure jemalloc is loaded
const char *version;
size_t version_size = sizeof(version);
if (mallctl("version", (void*)&version, &version_size, NULL, 0) != 0) {
fprintf(stderr, "Error: mallctl 'version' failed. Jemalloc not loaded?\n");
return 1; // Always fail if jemalloc isn't loaded
}
if (verbose) {
printf("Using jemalloc version: %s\n", version);
}
// Perform some allocations to have something to measure
const int num_allocs = 10;
void* ptrs[num_allocs];
for (int i = 0; i < num_allocs; i++) {
// Allocate blocks of increasing size
size_t size = 1024 * (i + 1);
ptrs[i] = malloc(size);
if (!ptrs[i]) {
fprintf(stderr, "malloc failed for size %zu\n", size);
return 1;
}
// Write some data to ensure pages are committed
memset(ptrs[i], i, size);
}
// Test stats functionality
int stats_unavailable = test_stats_functionality(verbose);
// Clean up allocations
for (int i = 0; i < num_allocs; i++) {
free(ptrs[i]);
}
// Determine exit code based on stats availability and expectation
int exit_code;
if (expect_stats_available) {
// Expecting stats to be available
exit_code = stats_unavailable ? 1 : 0;
} else {
// Expecting stats to be unavailable
exit_code = stats_unavailable ? 0 : 1;
}
// Only print this if verbose mode is enabled
if (verbose) {
printf("\nStats %s - Test %s\n",
stats_unavailable ? "UNAVAILABLE" : "AVAILABLE",
exit_code == 0 ? "PASSED" : "FAILED");
}
return exit_code;
}

50
examples/test_basic.c Normal file
View file

@ -0,0 +1,50 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv) {
// Concatenate all arguments into a single string
size_t len = 0;
for (int i = 1; i < argc; i++) {
len += strlen(argv[i]);
}
char* str = malloc(len + 1);
if (!str) {
fprintf(stderr, "malloc failed\n");
return 1;
}
str[0] = '\0';
for (int i = 1; i < argc; i++) {
strcat(str, argv[i]);
}
printf("Concatenated string: %s\n", str);
// Additional allocations to exercise the allocator
size_t n_allocs = 1000;
void** allocs = malloc(n_allocs * sizeof(void*));
if (!allocs) {
fprintf(stderr, "malloc for allocs array failed\n");
free(str);
return 1;
}
for (size_t i = 0; i < n_allocs; i++) {
allocs[i] = malloc(i + 1); // Varying sizes
if (!allocs[i]) {
fprintf(stderr, "malloc failed at iteration %zu\n", i);
break;
}
memset(allocs[i], 'A', i + 1); // Fill to ensure allocation is usable
}
// Clean up
for (size_t i = 0; i < n_allocs; i++) {
free(allocs[i]);
}
free(allocs);
free(str);
printf("All allocations and frees completed successfully.\n");
return 0;
}

View file

@ -0,0 +1,60 @@
def _settings_transition_impl(settings, attr):
return {
"@jemalloc//settings/flags:jemalloc_prefix": "je_",
"@jemalloc//settings/flags:jemalloc_cprefix": "JE_",
}
_settings_transition = transition(
implementation = _settings_transition_impl,
inputs = [
"@jemalloc//settings/flags:jemalloc_prefix",
"@jemalloc//settings/flags:jemalloc_cprefix",
],
outputs = [
"@jemalloc//settings/flags:jemalloc_prefix",
"@jemalloc//settings/flags:jemalloc_cprefix",
# "//settings/platform:lg_page",
],
)
def _transition_settings_impl(ctx):
return [ctx.attr.src[0][DefaultInfo]]
# target = ctx.attr.src
# possible_providers = [
# DefaultInfo,
# CcInfo,
# InstrumentedFilesInfo,
# OutputGroupInfo,
# ]
#
# print(target[0])
#
# return [target[0][provider] for provider in possible_providers if provider in target[0]]
transition_settings = rule(
implementation = _transition_settings_impl,
attrs = {
"target": attr.label(cfg = _settings_transition),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
)
platform_transition_binary = rule(
implementation = _platform_transition_binary_impl,
attrs = {
"basename": attr.string(),
"binary": attr.label(allow_files = True, cfg = binary_cfg),
"target_platform": attr.label(
doc = "The target platform to transition the binary.",
mandatory = True,
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
executable = True,
doc = "Transitions the binary to use the provided platform. Will forward RunEnvironmentInfo",
)

View file

@ -0,0 +1,145 @@
load("@bazel_skylib//lib:selects.bzl", "selects")
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
load("//:tools/autoconf.bzl", "configure_header", "define_macro_if", "define_macro_with")
load("//:tools/version.bzl", "parse_version")
version = parse_version(module_version())
configure_header(
name = "jemalloc_defs",
out = "jemalloc_defs.h",
substitutions =
define_macro_if("JEMALLOC_HAVE_ATTR_ALLOC_SIZE", "//settings/compiler:gcc_compatible") |
define_macro_if("JEMALLOC_HAVE_ATTR_FORMAT_ARG", "//settings/compiler:gcc_compatible") |
define_macro_if("JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF", "//settings/compiler:gcc_core") |
define_macro_if("JEMALLOC_HAVE_ATTR_FORMAT_PRINTF", "//settings/compiler:gcc_compatible") |
define_macro_if("JEMALLOC_HAVE_ATTR_FALLTHROUGH", "//settings/compiler:gcc_compatible") |
define_macro_if("JEMALLOC_HAVE_ATTR_COLD", "//settings/compiler:gcc_compatible") |
define_macro_if("JEMALLOC_HAVE_ATTR", "//settings/compiler:gcc_compatible") |
define_macro_if("JEMALLOC_OVERRIDE_MEMALIGN", "//settings/platform:has_memalign") |
define_macro_if("JEMALLOC_OVERRIDE_VALLOC", "//settings/platform:has_valloc") |
define_macro_with("JEMALLOC_USABLE_SIZE_CONST", "$(JEMALLOC_USABLE_SIZE_CONST)") |
define_macro_if("JEMALLOC_USE_CXX_THROW", "@platforms//os:linux") |
selects.with_or(
{
"//settings/compiler:msvc_compatible": define_macro_with("LG_SIZEOF_PTR", "LG_SIZEOF_PTR_WIN"),
("@platforms//cpu:aarch32", "@platforms//cpu:x86_32"): define_macro_with("LG_SIZEOF_PTR", "2"),
("@platforms//cpu:aarch64", "@platforms//cpu:x86_64"): define_macro_with("LG_SIZEOF_PTR", "3"),
},
no_match_error = "Cannot determine LG_SIZEOF_PTR value, missing support for platform.",
),
tags = ["manual"],
template = "jemalloc_defs.h.in",
toolchains = ["//settings/platform:usable_size_const"],
)
expand_template(
name = "jemalloc_macros",
out = "jemalloc_macros.h",
substitutions = {
"@jemalloc_version@": version.full,
"@jemalloc_version_major@": version.major,
"@jemalloc_version_minor@": version.minor,
"@jemalloc_version_bugfix@": version.bugfix,
"@jemalloc_version_nrev@": version.nrev,
"@jemalloc_version_gid@": version.gid,
},
template = "jemalloc_macros.h.in",
)
genrule(
name = "jemalloc_mangle",
srcs = [
"jemalloc_mangle.sh",
"//include/jemalloc/internal:public_symbols",
],
outs = ["jemalloc_mangle.h"],
cmd = "$(location jemalloc_mangle.sh) $(location //include/jemalloc/internal:public_symbols) je_ > $@",
tags = ["manual"],
visibility = ["//visibility:public"],
)
genrule(
name = "jemalloc_mangle_jet",
srcs = [
"jemalloc_mangle.sh",
"//include/jemalloc/internal:public_symbols",
],
outs = ["jemalloc_mangle_jet.h"],
cmd = "$(location jemalloc_mangle.sh) $(location //include/jemalloc/internal:public_symbols) jet_ > $@",
tags = ["manual"],
visibility = ["//visibility:public"],
)
expand_template(
name = "jemalloc_protos",
out = "jemalloc_protos.h",
substitutions = {
"@je_@": "je_",
"@install_suffix@": "",
},
template = "jemalloc_protos.h.in",
)
expand_template(
name = "jemalloc_protos_jet",
out = "jemalloc_protos_jet.h",
substitutions = {
"@je_@": "jet_",
"@install_suffix@": "",
},
template = "jemalloc_protos.h.in",
)
# Invoke jemalloc_rename.sh to generate jemalloc_rename.h
genrule(
name = "jemalloc_rename",
srcs = [
"jemalloc_rename.sh",
"//include/jemalloc/internal:public_symbols",
],
outs = ["jemalloc_rename.h"],
cmd = "$(location jemalloc_rename.sh) $(location //include/jemalloc/internal:public_symbols) > $@",
tags = ["manual"],
visibility = ["//visibility:public"],
)
expand_template(
name = "jemalloc_typedefs",
out = "jemalloc_typedefs.h",
substitutions = {},
template = "jemalloc_typedefs.h.in",
)
# jemalloc.sh generates the public jemalloc.h header file. Equivalent logic is replicated to handle pathing.
# Not fully hermetic but assumes no more about the host system than the Makefile does.
genrule(
name = "jemalloc",
srcs = [
":jemalloc_defs",
":jemalloc_rename",
":jemalloc_macros",
":jemalloc_protos",
":jemalloc_typedefs",
":jemalloc_mangle",
],
outs = ["jemalloc.h"],
cmd = """
echo '#ifndef JEMALLOC_H_' > $@
echo '#define JEMALLOC_H_' >> $@
echo '#ifdef __cplusplus' >> $@
echo 'extern "C" {' >> $@
echo '#endif' >> $@
echo '' >> $@
for f in $(SRCS); do
grep -v 'Generated from .* by configure' $$f | sed 's/ $$//g' >> $@
echo '' >> $@
done
echo '#ifdef __cplusplus' >> $@
echo '}' >> $@
echo '#endif' >> $@
echo '#endif /* JEMALLOC_H_ */' >> $@
""",
tags = ["manual"],
visibility = ["//:__subpackages__"],
)

View file

@ -0,0 +1,638 @@
load("@aspect_bazel_lib//lib:expand_template.bzl", "expand_template")
load("@bazel_skylib//lib:selects.bzl", "selects")
load("@rules_cc//cc:defs.bzl", "cc_library")
load("//:tools/autoconf.bzl", "configure_header", "define_macro_if", "define_macro_if_any", "define_macro_if_with", "define_macro", "define_macro_with", "undefine_macro")
load("//:tools/version.bzl", "parse_version")
load(":private_namespace.bzl", "private_namespace")
load(":public_symbols.bzl", "public_symbols")
version = parse_version(module_version())
cc_library(
name = "internal",
hdrs = [
"activity_callback.h",
"arena_externs.h",
"arena_inlines_a.h",
"arena_inlines_b.h",
"arena_stats.h",
"arena_structs.h",
"arena_types.h",
"assert.h",
"atomic.h",
"atomic_c11.h",
"atomic_gcc_atomic.h",
"atomic_gcc_sync.h",
"atomic_msvc.h",
"background_thread_externs.h",
"background_thread_inlines.h",
"background_thread_structs.h",
"base.h",
"bin.h",
"bin_info.h",
"bin_stats.h",
"bin_types.h",
"bit_util.h",
"bitmap.h",
"buf_writer.h",
"cache_bin.h",
"ckh.h",
"counter.h",
"ctl.h",
"decay.h",
"div.h",
"ecache.h",
"edata.h",
"edata_cache.h",
"ehooks.h",
"emap.h",
"emitter.h",
"eset.h",
"exp_grow.h",
"extent.h",
"extent_dss.h",
"extent_mmap.h",
"fb.h",
"fxp.h",
"hash.h",
"hook.h",
"hpa.h",
"hpa_hooks.h",
"hpa_opts.h",
"hpdata.h",
"inspect.h",
"jemalloc_internal_decls.h",
"jemalloc_internal_externs.h",
"jemalloc_internal_includes.h",
"jemalloc_internal_inlines_a.h",
"jemalloc_internal_inlines_b.h",
"jemalloc_internal_inlines_c.h",
"jemalloc_internal_macros.h",
"jemalloc_internal_types.h",
"large_externs.h",
"lockedint.h",
"log.h",
"malloc_io.h",
"mpsc_queue.h",
"mutex.h",
"mutex_prof.h",
"nstime.h",
"pa.h",
"pac.h",
"pages.h",
"pai.h",
"peak.h",
"peak_event.h",
"ph.h",
"prng.h",
"prof_data.h",
"prof_externs.h",
"prof_hook.h",
"prof_inlines.h",
"prof_log.h",
"prof_recent.h",
"prof_stats.h",
"prof_structs.h",
"prof_sys.h",
"prof_types.h",
"psset.h",
"ql.h",
"qr.h",
"quantum.h",
"rb.h",
"rtree.h",
"rtree_tsd.h",
"safety_check.h",
"san.h",
"san_bump.h",
"sc.h",
"sec.h",
"sec_opts.h",
"seq.h",
"slab_data.h",
"smoothstep.h",
"spin.h",
"stats.h",
"sz.h",
"tcache_externs.h",
"tcache_inlines.h",
"tcache_structs.h",
"tcache_types.h",
"test_hooks.h",
"thread_event.h",
"ticker.h",
"tsd.h",
"tsd_generic.h",
"tsd_malloc_thread_cleanup.h",
"tsd_tls.h",
"tsd_types.h",
"tsd_win.h",
"typed_list.h",
"util.h",
"witness.h",
] + [
":jemalloc_internal_defs",
":jemalloc_preamble",
":public_namespace",
] + select({
"//settings:no_private_namespace": [],
"//conditions:default": [
":private_namespace",
":private_namespace_jet",
],
}),
tags = ["manual"],
visibility = ["//:__subpackages__"],
)
expand_template(
name = "jemalloc_preamble",
out = "jemalloc_preamble.h",
substitutions = {
"@install_suffix@": "",
"@private_namespace@": "je_",
},
template = "jemalloc_preamble.h.in",
)
# jemalloc is built to be the default allocator
selects.config_setting_group(
name = "override_glibc_allocator",
match_all = [
"//settings/platform:has_glibc_overrides",
"//settings/flags:no_jemalloc_prefix",
],
)
selects.config_setting_group(
name = "aarch_clang-cl",
match_all = [
"//settings/platform:aarch",
"@rules_cc//cc/compiler:clang-cl",
],
)
selects.config_setting_group(
name = "aarch_gcc",
match_all = [
"//settings/platform:aarch",
"//settings/compiler:gcc_native",
],
)
selects.config_setting_group(
name = "x86_gcc",
match_all = [
"//settings/platform:x86",
"//settings/compiler:gcc_native",
],
)
selects.config_setting_group(
name = "x86_msvc",
match_all = [
"//settings/platform:x86",
"//settings/compiler:msvc_compatible",
],
)
selects.config_setting_group(
name = "jemalloc_retain_cpu",
match_any = [
"@platforms//cpu:aarch64",
"@platforms//cpu:x86_64",
],
)
selects.config_setting_group(
name = "jemalloc_retain_os",
match_any = [
"@platforms//os:android",
"@platforms//os:linux",
"@platforms//os:windows",
],
)
selects.config_setting_group(
name = "jemalloc_retain",
match_all = [
":jemalloc_retain_cpu",
":jemalloc_retain_os",
],
)
configure_header(
name = "jemalloc_internal_defs",
out = "jemalloc_internal_defs.h",
substitutions =
select({
"//settings/flags:no_jemalloc_prefix": undefine_macro("JEMALLOC_PREFIX") |
undefine_macro("JEMALLOC_CPREFIX"),
"//conditions:default": define_macro_with("JEMALLOC_PREFIX", "\"$(JEMALLOC_PREFIX)\"") |
define_macro_with("JEMALLOC_CPREFIX", "\"$(JEMALLOC_CPREFIX)\""),
}) |
# JEMALLOC_OVERRIDE___LIBC_*: Only relevant when JEMALLOC_PREFIX is empty and overriding libc
define_macro_if("JEMALLOC_OVERRIDE___LIBC_CALLOC", ":override_glibc_allocator") |
define_macro_if("JEMALLOC_OVERRIDE___LIBC_FREE", ":override_glibc_allocator") |
define_macro_if("JEMALLOC_OVERRIDE___LIBC_MALLOC", ":override_glibc_allocator") |
define_macro_if("JEMALLOC_OVERRIDE___LIBC_MEMALIGN", ":override_glibc_allocator") |
define_macro_if("JEMALLOC_OVERRIDE___LIBC_REALLOC", ":override_glibc_allocator") |
define_macro_if("JEMALLOC_OVERRIDE___LIBC_VALLOC", ":override_glibc_allocator") |
# Internal symbol that no longer appears to exist or be public on modern linux + glibc
undefine_macro("JEMALLOC_OVERRIDE___POSIX_MEMALIGN") |
# JEMALLOC_PRIVATE_NAMESPACE: Default to "je_" as in autoconf
define_macro_with("JEMALLOC_PRIVATE_NAMESPACE", "je_") |
# CPU_SPINWAIT and HAVE_CPU_SPINWAIT: Platform-specific spin wait instructions, depends on compiler
select({
"@platforms//cpu:x86_32": define_macro_with("HAVE_CPU_SPINWAIT", "1"),
"@platforms//cpu:x86_64": define_macro_with("HAVE_CPU_SPINWAIT", "1"),
"@platforms//cpu:aarch32": define_macro_with("HAVE_CPU_SPINWAIT", "1"),
"@platforms//cpu:aarch64": define_macro_with("HAVE_CPU_SPINWAIT", "1"),
"//conditions:default": define_macro_with("HAVE_CPU_SPINWAIT", "0"),
}) |
select({
# configure.ac doesn't test aarch for msvc mm_pause
":aarch_clang-cl": define_macro_with("CPU_SPINWAIT", "__asm__ volatile(\"isb\")"),
":aarch_gcc": define_macro_with("CPU_SPINWAIT", "__asm__ volatile(\"isb\")"),
":x86_gcc": define_macro_with("CPU_SPINWAIT", "__asm__ volatile(\"pause\")"),
":x86_msvc": define_macro_with("CPU_SPINWAIT", "_mm_pause()"),
"//conditions:default": define_macro_with("CPU_SPINWAIT", ""),
}) |
# LG_VADDR: Virtual address bits
define_macro_with("LG_VADDR", "$(LG_VADDR)") |
# JEMALLOC_C11_ATOMICS: Assume available on modern compilers (C11 standard)
define_macro("JEMALLOC_C11_ATOMICS") |
# JEMALLOC_GCC_ATOMIC_ATOMICS and U8 variant: Assume GCC-style atomics on non-MSVC
define_macro_if("JEMALLOC_GCC_ATOMIC_ATOMICS", "//settings/compiler:gcc_compatible") |
define_macro_if("JEMALLOC_GCC_U8_ATOMIC_ATOMICS", "//settings/compiler:gcc_compatible") |
# JEMALLOC_GCC_SYNC_ATOMICS and U8 variant: Older GCC atomics, assume supported
define_macro_if("JEMALLOC_GCC_SYNC_ATOMICS", "//settings/compiler:gcc_compatible") |
define_macro_if("JEMALLOC_GCC_U8_SYNC_ATOMICS", "//settings/compiler:gcc_compatible") |
# JEMALLOC_HAVE_BUILTIN_CLZ: Assume available on modern GCC/Clang
define_macro_if("JEMALLOC_HAVE_BUILTIN_CLZ", "//settings/compiler:gcc_compatible") |
# JEMALLOC_OS_UNFAIR_LOCK: Darwin-specific
define_macro_if("JEMALLOC_OS_UNFAIR_LOCK", "//settings/platform:darwin") |
# JEMALLOC_USE_SYSCALL: Assume syscall(2) is usable on POSIX systems except for modern MacOS
define_macro_if_any(
"JEMALLOC_USE_SYSCALL",
[
"@platforms//os:android",
"@platforms//os:freebsd",
"@platforms//os:linux",
"@platforms//os:openbsd",
],
) |
# JEMALLOC_HAVE_SECURE_GETENV: GNU-specific, available on Linux/Android
define_macro_if("JEMALLOC_HAVE_SECURE_GETENV", "//settings/platform:gnu") |
# JEMALLOC_HAVE_ISSETUGID: BSD-specific, assume on macOS
define_macro_if("JEMALLOC_HAVE_ISSETUGID", "//settings/platform:bsd") |
# Pthread features: POSIX systems
define_macro_if("JEMALLOC_HAVE_PTHREAD_ATFORK", "//settings/platform:posix") |
# MacOS takes a different setname signature
define_macro_if("JEMALLOC_HAVE_PTHREAD_SETNAME_NP", "//settings/platform:gnu") |
define_macro_if("JEMALLOC_HAVE_PTHREAD_GETNAME_NP", "//settings/platform:gnu") |
define_macro_if("JEMALLOC_HAVE_PTHREAD_GET_NAME_NP", "@platforms//os:freebsd") |
# Clock features: POSIX systems
define_macro_if("JEMALLOC_HAVE_CLOCK_MONOTONIC_COARSE", "//settings/platform:gnu") |
# Despite POSIX compliance modern macs appear to not support this
define_macro_if_any(
"JEMALLOC_HAVE_CLOCK_MONOTONIC",
[
"@platforms//os:android",
"@platforms//os:freebsd",
"@platforms//os:linux",
"@platforms//os:openbsd",
],
) |
define_macro_if("JEMALLOC_HAVE_MACH_ABSOLUTE_TIME", "//settings/platform:darwin") |
define_macro_if("JEMALLOC_HAVE_CLOCK_REALTIME", "//settings/platform:posix") |
# JEMALLOC_MUTEX_INIT_CB: FreeBSD-specific
define_macro_if("JEMALLOC_MUTEX_INIT_CB", "@platforms//os:freebsd") |
# JEMALLOC_MALLOC_THREAD_CLEANUP: BSD specific
define_macro_if("JEMALLOC_MALLOC_THREAD_CLEANUP", "@platforms//os:freebsd") |
# JEMALLOC_THREADED_INIT: GNU systems
define_macro_if("JEMALLOC_THREADED_INIT", "//settings/platform:gnu") |
# JEMALLOC_TLS_MODEL: Assume initial-exec TLS on modern systems
define_macro_if_with("JEMALLOC_TLS_MODEL", "//settings/platform:posix", "__attribute__((tls_model(\"initial-exec\")))") |
# JEMALLOC_DEBUG: Configurable flag
define_macro_if("JEMALLOC_DEBUG", "//settings/flags:debug") |
# JEMALLOC_STATS: Configurable flag
define_macro_if("JEMALLOC_STATS", "//settings/flags:stats") |
# JEMALLOC_EXPERIMENTAL_SMALLOCX_API: Configurable flag
define_macro_if("JEMALLOC_EXPERIMENTAL_SMALLOCX_API", "//settings/flags:experimental_smallocx_api") |
# JEMALLOC_PROF and related: Assume off by default, not critical for core functionality
undefine_macro("JEMALLOC_PROF_LIBUNWIND") |
undefine_macro("JEMALLOC_PROF_LIBGCC") |
undefine_macro("JEMALLOC_PROF_GCC") |
undefine_macro("JEMALLOC_PROF") |
# JEMALLOC_DSS: sbrk(2) deprecated on macOS, disable
define_macro_if_any(
"JEMALLOC_DSS",
[
"@platforms//os:android",
"@platforms//os:freebsd",
"@platforms//os:linux",
],
) |
# JEMALLOC_FILL: Configurable flag
define_macro_if("JEMALLOC_FILL", "//settings/flags:fill") |
# JEMALLOC_UTRACE and LABEL: Disabled by default
undefine_macro("JEMALLOC_UTRACE_LABEL") |
undefine_macro("JEMALLOC_UTRACE") |
# JEMALLOC_XMALLOC: Configurable flag
define_macro_if("JEMALLOC_XMALLOC", "//settings/flags:xmalloc") |
# JEMALLOC_LAZY_LOCK: Configurable flag
# TODO: This is forced for freeBSD
define_macro_if("JEMALLOC_LAZY_LOCK", "//settings/flags:lazy_lock") |
# LG_QUANTUM: Only set with configure flag, disabled by default
select({
"//settings/flags:no_lg_quantum": undefine_macro("LG_QUANTUM"),
"//conditions:default": define_macro_with("LG_QUANTUM", "$(LG_QUANTUM)"),
}) |
# LG_PAGE: Configured explicitly
define_macro_with("LG_PAGE", "$(LG_PAGE)") |
# CONFIG_LG_SLAB_MAXREGS: Optional tuning, leave undefined unless specified
undefine_macro("CONFIG_LG_SLAB_MAXREGS") |
# LG_HUGEPAGE: Configured explicitly
define_macro_with("LG_HUGEPAGE", "$(LG_HUGEPAGE)") |
# JEMALLOC_MAPS_COALESCE: Hardcoded via configure.ac host check
select({
"@platforms//os:windows": undefine_macro("JEMALLOC_MAPS_COALESCE"),
"//conditions:default": define_macro("JEMALLOC_MAPS_COALESCE"),
}) |
# JEMALLOC_RETAIN: Specific 64-bit systems
define_macro_if("JEMALLOC_RETAIN", ":jemalloc_retain") |
# JEMALLOC_TLS: One of the more complicated settings, explicitly disabled on darwin and windows,
# forced on FreeBSD, detected on the others
define_macro_if_any(
"JEMALLOC_TLS",
[
"@platforms//os:android",
"@platforms//os:freebsd",
"@platforms//os:linux",
],
) |
# JEMALLOC_INTERNAL_UNREACHABLE: Assume __builtin_unreachable on modern compilers, autoconf doesn't handle MSVC failure
define_macro_if_with("JEMALLOC_INTERNAL_UNREACHABLE", "//settings/compiler:gcc_compatible", "__builtin_unreachable") |
# JEMALLOC_INTERNAL_FFS*: Assume builtins on modern compilers
define_macro_if_with("JEMALLOC_INTERNAL_FFSLL", "//settings/compiler:gcc_compatible", "__builtin_ffsll") |
define_macro_if_with("JEMALLOC_INTERNAL_FFSL", "//settings/compiler:gcc_compatible", "__builtin_ffsl") |
define_macro_if_with("JEMALLOC_INTERNAL_FFS", "//settings/compiler:gcc_compatible", "__builtin_ffs") |
# JEMALLOC_INTERNAL_POPCOUNT*: Assume builtins on modern compilers
define_macro_if_with("JEMALLOC_INTERNAL_POPCOUNTL", "//settings/compiler:gcc_compatible", "__builtin_popcountl") |
define_macro_if_with("JEMALLOC_INTERNAL_POPCOUNT", "//settings/compiler:gcc_compatible", "__builtin_popcount") |
# JEMALLOC_CACHE_OBLIVIOUS: Configurable flag
define_macro_if("JEMALLOC_CACHE_OBLIVIOUS", "//settings/flags:cache_oblivious") |
# JEMALLOC_LOG: Configurable flag
define_macro_if("JEMALLOC_LOG", "//settings/flags:log") |
# JEMALLOC_READLINKAT: Assume off by default
undefine_macro("JEMALLOC_READLINKAT") |
# JEMALLOC_ZONE: Darwin-specific, configurable
define_macro_if("JEMALLOC_ZONE", "//settings/flags:zone_allocator") |
# Overcommit methods: Platform-specific
define_macro_if("JEMALLOC_SYSCTL_VM_OVERCOMMIT", "@platforms//os:freebsd") |
define_macro_if("JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY", "//settings/platform:gnu") |
# JEMALLOC_HAVE_MADVISE_HUGE: Assume THP support on modern Linux
define_macro_if("JEMALLOC_HAVE_MADVISE_HUGE", "@platforms//os:linux") |
# JEMALLOC_HAVE_MADVISE: Assume available on modern POSIX systems
define_macro_if("JEMALLOC_HAVE_MADVISE", "//settings/platform:posix") |
# Purge methods: Platform-specific
define_macro_if_any(
"JEMALLOC_PURGE_MADVISE_FREE",
[
"@platforms//os:android",
"@platforms//os:freebsd",
"@platforms//os:linux",
"@platforms//os:macos",
"@platforms//os:openbsd",
],
) |
define_macro_if("JEMALLOC_PURGE_MADVISE_DONTNEED_ZEROS", "//settings/platform:gnu") |
define_macro_if_any(
"JEMALLOC_PURGE_MADVISE_DONTNEED",
[
"@platforms//os:android",
"@platforms//os:freebsd",
"@platforms//os:linux",
"@platforms//os:macos",
],
) |
# JEMALLOC_DEFINE_MADVISE_FREE: Only for older x86 Linux without MADV_FREE, assume not needed
undefine_macro("JEMALLOC_DEFINE_MADVISE_FREE") |
# JEMALLOC_MADVISE_DONTDUMP: Assume on Linux
define_macro_if("JEMALLOC_MADVISE_DONTDUMP", "//settings/platform:gnu") |
# JEMALLOC_MADVISE_NOCORE
define_macro_if("JEMALLOC_MADVISE_NOCORE", "@platforms//os:freebsd") |
# JEMALLOC_HAVE_MPROTECT: Assume on modern POSIX systems
define_macro_if("JEMALLOC_HAVE_MPROTECT", "//settings/platform:posix") |
# JEMALLOC_THP: Missing from configure detection
undefine_macro("JEMALLOC_THP") |
# JEMALLOC_HAVE_POSIX_MADVISE: Undefined in configure.ac if madvise is available, only possible on some BSD
# variants or embedded systems
undefine_macro("JEMALLOC_HAVE_POSIX_MADVISE") |
# JEMALLOC_PURGE_POSIX_MADVISE_DONTNEED_ZEROS: Unconfigurable but present in template
undefine_macro("JEMALLOC_PURGE_POSIX_MADVISE_DONTNEED_ZEROS") |
# JEMALLOC_PURGE_POSIX_MADVISE_DONTNEED: Obscure fallback, assume unneeded
undefine_macro("JEMALLOC_PURGE_POSIX_MADVISE_DONTNEED") |
# JEMALLOC_HAVE_MEMCNTL: Solaris-specific, assume off
undefine_macro("JEMALLOC_HAVE_MEMCNTL") |
# JEMALLOC_HAVE_MALLOC_SIZE: Darwin-specific
define_macro_if("JEMALLOC_HAVE_MALLOC_SIZE", "//settings/platform:darwin") |
# JEMALLOC_HAS_ALLOCA_H: Hardcoded via configure.ac host check
define_macro_if("JEMALLOC_HAS_ALLOCA_H", "//settings/platform:gnu") |
# JEMALLOC_HAS_RESTRICT: Assume C99-compliant compilers
define_macro_if("JEMALLOC_HAS_RESTRICT", "//settings/compiler:gcc_compatible") |
# JEMALLOC_BIG_ENDIAN: Assume little-endian for modern systems
undefine_macro("JEMALLOC_BIG_ENDIAN") |
# Size definitions: Function of ABI but can assume defaults
define_macro_with("LG_SIZEOF_INTMAX_T", "3") |
define_macro_with("LG_SIZEOF_INT", "2") |
define_macro_with("LG_SIZEOF_LONG_LONG", "3") |
select(
{
"@platforms//os:windows": define_macro_with("LG_SIZEOF_LONG", "2"),
"@platforms//cpu:aarch32": define_macro_with("LG_SIZEOF_LONG", "2"),
"@platforms//cpu:aarch64": define_macro_with("LG_SIZEOF_LONG", "3"),
"@platforms//cpu:x86_32": define_macro_with("LG_SIZEOF_LONG", "2"),
"@platforms//cpu:x86_64": define_macro_with("LG_SIZEOF_LONG", "3"),
},
no_match_error = "Determined by ABI, support for less common target cpus not yet implemented",
) |
# GLIBC hooks: Assume glibc > 2.34 after which these were deprecated
undefine_macro("JEMALLOC_GLIBC_MALLOC_HOOK") |
undefine_macro("JEMALLOC_GLIBC_MEMALIGN_HOOK") |
# JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP: Linux-specific
define_macro_if("JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP", "@platforms//os:linux") |
# JEMALLOC_HAVE_PTHREAD: Assume on POSIX systems
define_macro_if("JEMALLOC_HAVE_PTHREAD", "//settings/platform:posix") |
# JEMALLOC_HAVE_DLSYM: Assume on POSIX systems
define_macro_if("JEMALLOC_HAVE_DLSYM", "//settings/platform:posix") |
# JEMALLOC_HAVE_SCHED_GETCPU: GNU-specific
define_macro_if("JEMALLOC_HAVE_SCHED_GETCPU", "//settings/platform:gnu") |
# JEMALLOC_HAVE_SCHED_SETAFFINITY: GNU-specific
define_macro_if("JEMALLOC_HAVE_SCHED_SETAFFINITY", "//settings/platform:gnu") |
# JEMALLOC_BACKGROUND_THREAD: Assume on POSIX systems without os_unfair_lock
define_macro_if_any(
"JEMALLOC_BACKGROUND_THREAD",
[
"@platforms//os:android",
"@platforms//os:freebsd",
"@platforms//os:linux",
"@platforms//os:openbsd",
],
) |
# JEMALLOC_EXPORT: Controlled via flag to disable exporting public API
define_macro_if("JEMALLOC_EXPORT", "//settings/flags:export") |
# JEMALLOC_CONFIG_MALLOC_CONF: Leave empty
define_macro_with("JEMALLOC_CONFIG_MALLOC_CONF", "\"\"") |
# JEMALLOC_IS_MALLOC: Defined if no prefix
define_macro_if("JEMALLOC_IS_MALLOC", "//settings/flags:no_jemalloc_prefix") |
# JEMALLOC_STRERROR_R_RETURNS_CHAR_WITH_GNU_SOURCE: Linux/Android
define_macro_if("JEMALLOC_STRERROR_R_RETURNS_CHAR_WITH_GNU_SOURCE", "//settings/platform:gnu") |
# JEMALLOC_OPT_SAFETY_CHECKS: Configurable, off by default
undefine_macro("JEMALLOC_OPT_SAFETY_CHECKS") |
# JEMALLOC_ENABLE_CXX: Configurable flag
define_macro_if("JEMALLOC_ENABLE_CXX", "//settings/flags:cxx") |
# JEMALLOC_OPT_SIZE_CHECKS: Configurable, off by default
undefine_macro("JEMALLOC_OPT_SIZE_CHECKS") |
# JEMALLOC_UAF_DETECTION: Configurable flag
define_macro_if("JEMALLOC_UAF_DETECTION", "//settings/flags:uaf_detection") |
# JEMALLOC_HAVE_VM_MAKE_TAG: Darwin-specific
define_macro_if("JEMALLOC_HAVE_VM_MAKE_TAG", "//settings/platform:darwin") |
# JEMALLOC_ZERO_REALLOC_DEFAULT_FREE: Hardcoded in configure.ac
define_macro_if_any(
"JEMALLOC_ZERO_REALLOC_DEFAULT_FREE",
[
"@platforms//os:android",
"@platforms//os:linux",
"@platforms//os:windows",
],
),
tags = ["manual"],
template = "jemalloc_internal_defs.h.in",
toolchains = [
"//settings/flags:jemalloc_prefix",
"//settings/flags:jemalloc_cprefix",
"//settings/flags:lg_quantum",
"//settings/platform:lg_hugepage",
"//settings/platform:lg_page",
"//settings/platform:lg_vaddr",
],
)
PUBLIC_SYMBOLS = [
"aligned_alloc",
"calloc",
"dallocx",
"free",
"mallctl",
"mallctlbymib",
"mallctlnametomib",
"malloc",
"malloc_conf",
"malloc_conf_2_conf_harder",
"malloc_message",
"malloc_stats_print",
"malloc_usable_size",
"mallocx",
"smallocx_%s" % version.gid,
"nallocx",
"posix_memalign",
"rallocx",
"realloc",
"sallocx",
"sdallocx",
"xallocx",
] + select(
{
"//settings/platform:has_memalign": ["memalign"],
"//settings/platform:no_memalign": [],
},
no_match_error = "Availability of memalign must explicitly be declared via //settings/platform:memalign_support",
) + select(
{
"//settings/platform:has_valloc": ["valloc"],
"//settings/platform:no_valloc": [],
},
no_match_error = "Availability of valloc must explicitly be declared via //settings/platform:valloc_support",
) + select(
{
"//settings/platform:has_malloc_size": ["malloc_size"],
"//settings/platform:no_malloc_size": [],
},
no_match_error = "Availability of malloc_size must explicitly be declared via //settings/platform:malloc_size_support",
)
public_symbols(
name = "public_symbols",
out = "public_symbols.txt",
symbols = PUBLIC_SYMBOLS,
tags = ["manual"],
visibility = ["//:__subpackages__"],
)
WRAP_SYMBOLS = select({
"@platforms//os:windows": ["tls_callback"],
"@platforms//os:freebsd": [
"pthread_create",
"_malloc_thread_cleanup",
"_malloc_tsd_cleanup_register",
"_malloc_prefork",
"_malloc_postfork",
],
"//conditions:default": ["pthread_create"],
}) + select({
":override_glibc_allocator": [
"__libc_calloc",
"__libc_free",
"__libc_malloc",
"__libc_memalign",
"__libc_realloc",
"__libc_valloc",
],
"//conditions:default": [],
})
private_namespace(
name = "private_namespace",
out = "private_namespace.h",
input = "//:jemalloc_core",
public_symbols = PUBLIC_SYMBOLS,
tags = ["manual"],
wrap_symbols = WRAP_SYMBOLS,
)
private_namespace(
name = "private_namespace_jet",
out = "private_namespace_jet.h",
enable_jet = True,
input = "//:jemalloc_core",
prefix = "jet_",
public_symbols = PUBLIC_SYMBOLS,
tags = ["manual"],
wrap_symbols = WRAP_SYMBOLS,
)
genrule(
name = "public_namespace",
srcs = [
"public_namespace.sh",
":public_symbols",
],
outs = ["public_namespace.h"],
cmd = "$(location public_namespace.sh) $(location :public_symbols) > $@",
tags = ["manual"],
visibility = ["//visibility:public"],
)
genrule(
name = "public_unnamespace",
srcs = [
"public_unnamespace.sh",
":public_symbols",
],
outs = ["public_unnamespace.h"],
cmd = "$(location public_unnamespace.sh) $(location :public_symbols) > $@",
tags = ["manual"],
visibility = ["//visibility:public"],
)

View file

@ -0,0 +1,118 @@
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("@rules_cc//cc:defs.bzl", "CcToolchainConfigInfo")
load("@rules_cc//cc:find_cc_toolchain.bzl", "CC_TOOLCHAIN_TYPE", "find_cc_toolchain", "use_cc_toolchain")
def _private_namespace_impl(ctx):
cc_toolchain = find_cc_toolchain(ctx)
output = ctx.actions.declare_file(ctx.attr.out)
# Extract private symbols
args = ctx.actions.args()
prefix = ctx.attr.prefix if ctx.attr.prefix else ctx.attr._prefix[BuildSettingInfo].value
for sym in ctx.attr.public_symbols:
args.add(prefix + sym)
# Wrap symbols without prefix
args.add_all(ctx.attr.wrap_symbols)
# Write out awk script
constraint = ctx.attr._constraint_macos[platform_common.ConstraintValueInfo]
sym_prefix = "_" if ctx.target_platform_has_constraint(constraint) else ""
output_awk = ctx.actions.declare_file("{name}.awk".format(name = ctx.attr.name))
ctx.actions.run_shell(
inputs = [],
outputs = [output_awk],
arguments = [args],
command = "{script} \"{sym_prefix}\" $@ > {output}".format(
script = ctx.file._private_symbols_sh.path,
output = output_awk.path,
sym_prefix = sym_prefix,
),
mnemonic = "PrivateSymbols",
tools = [ctx.file._private_symbols_sh],
)
inputs = [src for src in ctx.files.input if src.path.endswith(".a")]
output_symbols = ctx.actions.declare_file("symbols{jet}.sym".format(jet = "_jet" if ctx.attr.enable_jet else ""))
ctx.actions.run_shell(
inputs = depset(inputs, transitive = [cc_toolchain.all_files]),
outputs = [output_symbols],
command = "{nm} -a {inputs} | awk -f {script} > {output}".format(
nm = cc_toolchain.nm_executable,
inputs = " ".join([input.path for input in inputs]),
script = output_awk.path,
output = output_symbols.path,
),
tools = [output_awk],
mnemonic = "PrivateNamespaceNM",
)
ctx.actions.run_shell(
inputs = [output_symbols],
outputs = [output],
command = "{script} {symbols} > {output}".format(
script = ctx.file._private_namespace_sh.path,
symbols = output_symbols.path,
output = output.path,
),
mnemonic = "PrivateNamespace",
tools = [ctx.file._private_namespace_sh],
)
return [DefaultInfo(files = depset([output]))]
def _transition_impl(settings, attr):
return {
# Only C sources are used for symbol extraction
"//settings/flags:enable_cxx": False,
"//settings:enable_no_private_namespace": True,
"//settings:enable_jet": attr.enable_jet,
}
transition_config_settings = transition(
implementation = _transition_impl,
inputs = [],
outputs = ["//settings/flags:enable_cxx", "//settings:enable_no_private_namespace", "//settings:enable_jet"],
)
private_namespace = rule(
doc = "Generate the private namespace header from compiled object files. This combines the private_symbols.awk " +
"generation with the header generation to bridge the requriements between the exec and target platforms.",
implementation = _private_namespace_impl,
attrs = {
"prefix": attr.string(doc = "Explicit prefix for public symbols, overrides value selected by build setting."),
"public_symbols": attr.string_list(
doc = "List of public API symbols",
mandatory = True,
),
"input": attr.label(
doc = "Compiled object achive from which to extract the symbols. A transition is forced to compile with JEMALLOC_NO_PRIVATE_NAMESPACE",
cfg = transition_config_settings,
),
"enable_jet": attr.bool(default = False),
"out": attr.string(
doc = "Name of the generated file",
mandatory = True,
),
"wrap_symbols": attr.string_list(
doc = "List of symbols to wrap without prefix",
default = [],
),
"_prefix": attr.label(default = "//settings/flags:jemalloc_prefix"),
"_cc_toolchain": attr.label(default = Label("@rules_cc//cc:current_cc_toolchain")),
"_constraint_macos": attr.label(default = "@platforms//os:macos", cfg = "target"),
"_private_namespace_sh": attr.label(
default = "//include/jemalloc/internal:private_namespace.sh",
allow_single_file = True,
cfg = "exec",
),
"_private_symbols_sh": attr.label(
default = "//include/jemalloc/internal:private_symbols.sh",
allow_single_file = True,
cfg = "exec",
),
},
toolchains = use_cc_toolchain(True),
)

View file

@ -0,0 +1,50 @@
"Reproduce the public_symbols.txt generation from configure.ac"
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
def _public_symbols_impl(ctx):
output = ctx.actions.declare_file(ctx.attr.out)
prefix = ctx.attr._prefix[BuildSettingInfo].value
# List of key:value pairs for custom mangling
mangling_map = {}
if ctx.attr.mangling_map:
# Parse "orig:mangled,orig2:mangled2" format
pairs = ctx.attr.mangling_map.split(",")
for pair in pairs:
orig, mangled = pair.split(":")
mangling_map[orig] = mangled
# Generate mappings, with mangling_map taking precedence
content = ""
for sym in ctx.attr.symbols:
if sym in mangling_map:
content += "{sym}:{mangling_map[sym]}\n".format(sym = sym, mangling_map = mangling_map)
else:
content += "{sym}:{prefix}{sym}\n".format(sym = sym, prefix = prefix, mangling_map = mangling_map)
ctx.actions.write(
output = output,
content = content,
)
return DefaultInfo(files = depset([output]))
public_symbols = rule(
implementation = _public_symbols_impl,
attrs = {
"symbols": attr.string_list(
doc = "List of all public symbols",
allow_empty = False,
mandatory = True,
),
"mangling_map": attr.string(
doc = "Untested feature to support the equivalent of --with-mangling=<key_1>:<value_1>,<key_2>:<value_2>,...",
),
"out": attr.string(
doc = "Name of the generated file",
mandatory = True,
),
"_prefix": attr.label(default = "//settings/flags:jemalloc_prefix"),
},
)

57
settings/BUILD.bazel Normal file
View file

@ -0,0 +1,57 @@
load("@bazel_skylib//rules:common_settings.bzl", "bool_setting", "string_setting")
# JEMALLOC_JET - Explicitly used for testing
bool_setting(
name = "enable_jet",
build_setting_default = False,
visibility = ["//:__subpackages__"],
)
config_setting(
name = "jet",
flag_values = {":enable_jet": "True"},
)
# JEMALLOC_NO_PRIVATE_NAMESPACE - To create a private namespace, jemalloc first has to compile without one and
# identify all of the exported symbols.
bool_setting(
name = "enable_no_private_namespace",
build_setting_default = False,
visibility = ["//:__subpackages__"],
)
config_setting(
name = "no_private_namespace",
flag_values = {":enable_no_private_namespace": "True"},
)
# Control defines for compilation under different testing scenarios
string_setting(
name = "with_test",
build_setting_default = "False",
values = [
"False",
"unit",
"integration",
"integration_cpp",
],
visibility = ["//:__subpackages__"],
)
# JEMALLOC_UNIT_TEST
config_setting(
name = "unit_test",
flag_values = {":with_test": "unit"},
)
# JEMALLOC_INTEGRATION_TEST
config_setting(
name = "integration_test",
flag_values = {":with_test": "integration"},
)
# JEMALLOC_INTEGRATION_CPP_TEST
config_setting(
name = "integration_cpp_test",
flag_values = {":with_test": "integration_cpp"},
)

View file

@ -0,0 +1,44 @@
load("@bazel_skylib//lib:selects.bzl", "selects")
selects.config_setting_group(
name = "gcc_compatible",
match_any = [
"@rules_cc//cc/compiler:clang",
"@rules_cc//cc/compiler:clang-cl",
"@rules_cc//cc/compiler:gcc",
"@rules_cc//cc/compiler:mingw-gcc",
"@rules_cc//cc/compiler:emscripten",
],
visibility = ["//:__subpackages__"],
)
selects.config_setting_group(
name = "gcc_core",
match_any = [
"@rules_cc//cc/compiler:gcc",
"@rules_cc//cc/compiler:mingw-gcc",
],
visibility = ["//:__subpackages__"],
)
# GCC-like and target native CPU architectures
# Equivalent of configure.ac "x$GCC" != "xyes"
selects.config_setting_group(
name = "gcc_native",
match_any = [
"@rules_cc//cc/compiler:clang",
"@rules_cc//cc/compiler:gcc",
"@rules_cc//cc/compiler:mingw-gcc",
],
visibility = ["//:__subpackages__"],
)
# Compatibility with MSVCs conventions (intrinsics, frontend).
selects.config_setting_group(
name = "msvc_compatible",
match_any = [
"@rules_cc//cc/compiler:clang-cl",
"@rules_cc//cc/compiler:msvc-cl",
],
visibility = ["//:__subpackages__"],
)

109
settings/config.bzl Normal file
View file

@ -0,0 +1,109 @@
"""Public API for configuring jemalloc build settings."""
load("@rules_cc//cc:defs.bzl", "CcInfo")
def _jemalloc_config_impl(ctx):
target = ctx.attr._target[0]
providers = [DefaultInfo, CcInfo, InstrumentedFilesInfo, OutputGroupInfo]
return [target[provider] for provider in providers if provider in target]
def _jemalloc_transition_impl(settings, attr):
"""Transition implementation that applies user-provided settings."""
result = settings | {}
# Boolean flags
bool_flags = {
"//settings/flags:enable_cache_oblivious": attr.cache_oblivious,
"//settings/flags:enable_cxx": attr.cxx,
"//settings/flags:enable_experimental_smallocx": attr.experimental_smallocx,
"//settings/flags:enable_fill": attr.fill,
"//settings/flags:enable_lazy_lock": attr.lazy_lock,
"//settings/flags:enable_log": attr.log,
"//settings/flags:enable_stats": attr.stats,
"//settings/flags:enable_uaf_detection": attr.uaf_detection,
"//settings/flags:enable_xmalloc": attr.xmalloc,
"//settings/flags:without_export": attr.without_export,
}
for flag, value in bool_flags.items():
if value == "True":
result[flag] = True
elif value == "False":
result[flag] = False
# String flags
result["//settings/flags:jemalloc_prefix"] = attr.jemalloc_prefix
if attr.zone_allocator != "":
result["//settings/flags:enable_zone_allocator"] = attr.zone_allocator
# Integer flags
if attr.lg_quantum != -1:
result["//settings/flags:lg_quantum"] = attr.lg_quantum
return result
_jemalloc_transition = transition(
implementation = _jemalloc_transition_impl,
inputs = [
"//settings/flags:enable_cache_oblivious",
"//settings/flags:enable_cxx",
"//settings/flags:enable_experimental_smallocx",
"//settings/flags:enable_fill",
"//settings/flags:enable_lazy_lock",
"//settings/flags:enable_log",
"//settings/flags:enable_stats",
"//settings/flags:enable_uaf_detection",
"//settings/flags:enable_xmalloc",
"//settings/flags:without_export",
"//settings/flags:jemalloc_prefix",
"//settings/flags:enable_zone_allocator",
"//settings/flags:lg_quantum",
],
outputs = [
"//settings/flags:enable_cache_oblivious",
"//settings/flags:enable_cxx",
"//settings/flags:enable_experimental_smallocx",
"//settings/flags:enable_fill",
"//settings/flags:enable_lazy_lock",
"//settings/flags:enable_log",
"//settings/flags:enable_stats",
"//settings/flags:enable_uaf_detection",
"//settings/flags:enable_xmalloc",
"//settings/flags:without_export",
"//settings/flags:jemalloc_prefix",
"//settings/flags:enable_zone_allocator",
"//settings/flags:lg_quantum",
],
)
jemalloc = rule(
doc = "Convenience rule that returns the jemalloc cc_library transitioned the optional build settings based on user-provided constraints.",
implementation = _jemalloc_config_impl,
attrs = {
"cache_oblivious": attr.string(values = ["True", "False", ""]),
"cxx": attr.string(values = ["True", "False", ""]),
"experimental_smallocx": attr.string(values = ["True", "False", ""]),
"fill": attr.string(values = ["True", "False", ""]),
"jemalloc_prefix": attr.string(),
"lazy_lock": attr.string(values = ["True", "False", ""]),
"lg_quantum": attr.int(default = -1),
"log": attr.string(values = ["True", "False", ""]),
"stats": attr.string(values = ["True", "False", ""]),
"uaf_detection": attr.string(values = ["True", "False", ""]),
"without_export": attr.string(values = ["True", "False", ""]),
"xmalloc": attr.string(values = ["True", "False", ""]),
"zone_allocator": attr.string(values = ["yes", "no", "__auto__"]),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
"_target": attr.label(
doc = "The jemalloc cc_library target to configure.",
default = "//:jemalloc",
providers = [CcInfo],
cfg = _jemalloc_transition,
),
},
provides = [CcInfo],
)

182
settings/flags/BUILD.bazel Normal file
View file

@ -0,0 +1,182 @@
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "int_flag", "string_flag", "string_setting")
### Bazel-ification of optional flags accepted by ./configure ###
# JEMALLOC_CACHE_OBLIVIOUS
bool_flag(
name = "enable_cache_oblivious",
build_setting_default = True,
visibility = ["//visibility:public"],
)
config_setting(
name = "cache_oblivious",
flag_values = {":enable_cache_oblivious": "True"},
)
# JEMALLOC_ENABLE_CXX
bool_flag(
name = "enable_cxx",
build_setting_default = True,
visibility = ["//visibility:public"],
)
config_setting(
name = "cxx",
flag_values = {":enable_cxx": "True"},
)
# JEMALLOC_DEBUG
config_setting(
name = "debug",
values = {"compilation_mode": "dbg"},
)
# JEMALLOC_EXPERIMENTAL_SMALLOCX_API
bool_flag(
name = "enable_experimental_smallocx",
build_setting_default = False,
visibility = ["//visibility:public"],
)
config_setting(
name = "experimental_smallocx_api",
flag_values = {":enable_experimental_smallocx": "True"},
)
# JEMALLOC_FILL (support for junk/zero filling)
bool_flag(
name = "enable_fill",
build_setting_default = True,
visibility = ["//visibility:public"],
)
config_setting(
name = "fill",
flag_values = {":enable_fill": "True"},
)
# JEMALLOC_LAZY_LOCK
bool_flag(
name = "enable_lazy_lock",
build_setting_default = False,
visibility = ["//visibility:public"],
)
config_setting(
name = "lazy_lock",
flag_values = {":enable_lazy_lock": "True"},
)
# JEMALLOC_LOG
bool_flag(
name = "enable_log",
build_setting_default = False,
visibility = ["//visibility:public"],
)
config_setting(
name = "log",
flag_values = {":enable_log": "True"},
)
# JEMALLOC_STATS
bool_flag(
name = "enable_stats",
build_setting_default = True,
visibility = ["//visibility:public"],
)
config_setting(
name = "stats",
flag_values = {":enable_stats": "True"},
)
# JEMALLOC_UAF_DETECTION
bool_flag(
name = "enable_uaf_detection",
build_setting_default = False,
visibility = ["//visibility:public"],
)
config_setting(
name = "uaf_detection",
flag_values = {":enable_uaf_detection": "True"},
)
# JEMALLOC_XMALLOC
bool_flag(
name = "enable_xmalloc",
build_setting_default = False,
visibility = ["//visibility:public"],
)
config_setting(
name = "xmalloc",
flag_values = {":enable_xmalloc": "True"},
)
# JEMALLOC_PREFIX optionally set via --with-jemalloc-prefix
string_flag(
name = "jemalloc_prefix",
build_setting_default = "",
make_variable = "JEMALLOC_PREFIX",
visibility = ["//visibility:public"],
)
config_setting(
name = "no_jemalloc_prefix",
flag_values = {":jemalloc_prefix": ""},
)
# JEMALLOC_CPREFIX Uppercase version of JEMALLOC_PREFIX but can't easily be set during templating so uses a separate
# setting to handle it so string manipulation can be stored when the configurable prefix is processed.
string_setting(
name = "jemalloc_cprefix",
build_setting_default = "",
make_variable = "JEMALLOC_CPREFIX",
visibility = ["//:__subpackages__"],
)
# LG_QUANTUM Base 2 log of minimum allocation alignment (--with-lg-quantum), -1 is undefined for resolution internal
# to the headers
int_flag(
name = "lg_quantum",
build_setting_default = -1,
make_variable = "LG_QUANTUM",
visibility = ["//visibility:public"],
)
config_setting(
name = "no_lg_quantum",
flag_values = {":lg_quantum": "-1"},
)
# JEMALLOC_EXPORT via --without-export which disables the export of the jemalloc API
bool_flag(
name = "without_export",
build_setting_default = False,
visibility = ["//visibility:public"],
)
config_setting(
name = "export",
flag_values = {":without_export": "True"},
)
# JEMALLOC_ZONE Enable/Disable zone allocator for Darwin
string_flag(
name = "enable_zone_allocator",
build_setting_default = "__auto__",
values = [
"yes",
"no",
"__auto__",
],
visibility = ["//visibility:public"],
)
config_setting(
name = "zone_allocator",
flag_values = {":enable_zone_allocator": "yes"},
)

View file

@ -0,0 +1,214 @@
load("@bazel_skylib//lib:selects.bzl", "selects")
load("@bazel_skylib//rules:common_settings.bzl", "int_flag", "string_flag")
### Bazel-ification of platform feature detection performed by ./configure ###
# If "yes", the glibc hooks __libc_calloc, __libc_free, __libc_malloc, etc are available for override
string_flag(
name = "glibc_overrides_support",
build_setting_default = "__auto__",
values = [
"yes",
"no",
"__auto__",
],
visibility = ["//visibility:public"],
)
config_setting(
name = "has_glibc_overrides",
flag_values = {":glibc_overrides_support": "yes"},
visibility = ["//visibility:public"],
)
config_setting(
name = "no_glibc_overrides",
flag_values = {":glibc_overrides_support": "no"},
visibility = ["//visibility:public"],
)
# Whether the target libc has `malloc_size` available for linking
string_flag(
name = "malloc_size_support",
build_setting_default = "__auto__",
values = [
"yes",
"no",
"__auto__",
],
visibility = ["//visibility:public"],
)
config_setting(
name = "has_malloc_size",
flag_values = {":malloc_size_support": "yes"},
visibility = ["//visibility:public"],
)
config_setting(
name = "no_malloc_size",
flag_values = {":malloc_size_support": "no"},
visibility = ["//visibility:public"],
)
# JEMALLOC_USABLE_SIZE_CONST: Whether malloc_usable_size can accepts const, glibc on linux apparently omits it
string_flag(
name = "usable_size_const",
build_setting_default = "__auto__",
make_variable = "JEMALLOC_USABLE_SIZE_CONST",
values = [
"",
"const",
"__auto__",
],
visibility = ["//visibility:public"],
)
string_flag(
name = "memalign_support",
build_setting_default = "__auto__",
values = [
"yes",
"no",
"__auto__",
],
visibility = ["//visibility:public"],
)
config_setting(
name = "has_memalign",
flag_values = {":memalign_support": "yes"},
visibility = ["//visibility:public"],
)
config_setting(
name = "no_memalign",
flag_values = {":memalign_support": "no"},
visibility = ["//visibility:public"],
)
# LG_HUGEPAGE Base 2 log of system huge page size, can be explicitly set --with-lg-hugepage
# The correct setting depends on the kernel. configure defaults to 21 (2 MiB) when detection fails and
# there is runtime detection to gracefully handle a misconfigure value
int_flag(
name = "lg_hugepage",
build_setting_default = 21,
make_variable = "LG_HUGEPAGE",
visibility = ["//visibility:public"],
)
# LG_PAGE Base 2 log of system page size, can be explicitly set --with-lg-page
string_flag(
name = "lg_page",
build_setting_default = "__auto__",
make_variable = "LG_PAGE",
visibility = ["//visibility:public"],
)
# LLG_VADDR Number of significant virtual address bits, can be explicitly set --with-lg-vaddr
# The configure cross compilation fallback is the default. This should be safe for any 64-bit target even if the OS
# doesn't allow it because of runtime checks. However, 32-bit architectures should explicitly declare this
# need to declare
int_flag(
name = "lg_vaddr",
build_setting_default = 57,
make_variable = "LG_VADDR",
visibility = ["//visibility:public"],
)
string_flag(
name = "valloc_support",
build_setting_default = "__auto__",
values = [
"yes",
"no",
"__auto__",
],
visibility = ["//visibility:public"],
)
config_setting(
name = "has_valloc",
flag_values = {":valloc_support": "yes"},
visibility = ["//visibility:public"],
)
config_setting(
name = "no_valloc",
flag_values = {":valloc_support": "no"},
visibility = ["//visibility:public"],
)
### Convenience settings groups ###
# ARM
selects.config_setting_group(
name = "aarch",
match_any = [
"@platforms//cpu:aarch32",
"@platforms//cpu:aarch64",
],
visibility = ["//:__subpackages__"],
)
# X86
selects.config_setting_group(
name = "x86",
match_any = [
"@platforms//cpu:x86_32",
"@platforms//cpu:x86_64",
],
visibility = ["//:__subpackages__"],
)
# BSD systems
selects.config_setting_group(
name = "bsd",
match_any = [
"@platforms//os:freebsd",
"@platforms//os:ios",
"@platforms//os:macos",
"@platforms//os:openbsd",
"@platforms//os:tvos",
"@platforms//os:watchos",
],
visibility = ["//:__subpackages__"],
)
# Darwin systems
selects.config_setting_group(
name = "darwin",
match_any = [
"@platforms//os:ios",
"@platforms//os:macos",
"@platforms//os:tvos",
"@platforms//os:watchos",
],
visibility = ["//:__subpackages__"],
)
# GNU systems
selects.config_setting_group(
name = "gnu",
match_any = [
"@platforms//os:android",
"@platforms//os:linux",
],
visibility = ["//:__subpackages__"],
)
# POSIX systems
selects.config_setting_group(
name = "posix",
match_any = [
"@platforms//os:android",
"@platforms//os:freebsd",
"@platforms//os:ios",
"@platforms//os:linux",
"@platforms//os:macos",
"@platforms//os:openbsd",
"@platforms//os:tvos",
"@platforms//os:watchos",
],
visibility = ["//:__subpackages__"],
)

95
test/BUILD.bazel Normal file
View file

@ -0,0 +1,95 @@
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
load("@rules_cc//cc:defs.bzl", "cc_library")
load("//:tools/cc.bzl", "COPTS")
expand_template(
name = "jemalloc_test",
testonly = True,
out = "include/test/jemalloc_test.h",
substitutions = {
"@install_suffix@": "",
"@je_@": "je_",
"@private_namespace@": "je_",
},
template = "include/test/jemalloc_test.h.in",
)
expand_template(
name = "jemalloc_test_defs",
testonly = True,
out = "include/test/jemalloc_test_defs.h",
substitutions = {
"#undef HAVE_SSE2": "/* #undef HAVE_SSE2 */",
"#undef HAVE_ALTIVEC": "/* #undef HAVE_ALTIVEC */",
},
template = "include/test/jemalloc_test_defs.h.in",
)
cc_library(
name = "testlib",
testonly = True,
srcs = [
"src/SFMT.c",
"src/btalloc.c",
"src/btalloc_0.c",
"src/btalloc_1.c",
"src/math.c",
"src/mtx.c",
"src/sleep.c",
"src/test.c",
"src/thd.c",
"src/timer.c",
],
hdrs = [
"include/test/SFMT.h",
"include/test/SFMT-alti.h",
"include/test/SFMT-params.h",
"include/test/SFMT-params11213.h",
"include/test/SFMT-params1279.h",
"include/test/SFMT-params132049.h",
"include/test/SFMT-params19937.h",
"include/test/SFMT-params216091.h",
"include/test/SFMT-params2281.h",
"include/test/SFMT-params4253.h",
"include/test/SFMT-params44497.h",
"include/test/SFMT-params607.h",
"include/test/SFMT-params86243.h",
"include/test/SFMT-sse2.h",
"include/test/arena_util.h",
"include/test/bench.h",
"include/test/bgthd.h",
"include/test/btalloc.h",
"include/test/extent_hooks.h",
"include/test/jemalloc_test.h",
"include/test/jemalloc_test_defs.h",
"include/test/math.h",
"include/test/mq.h",
"include/test/mtx.h",
"include/test/nbits.h",
"include/test/san.h",
"include/test/sleep.h",
"include/test/test.h",
"include/test/thd.h",
"include/test/timer.h",
],
copts = COPTS,
includes = ["include"],
linkstatic = True,
local_defines = select(
{
"//settings:unit_test": ["JEMALLOC_UNIT_TEST"],
"//settings:integration_test": ["JEMALLOC_INTEGRATION_TEST"],
"//settings:integration_cpp_test": ["JEMALLOC_INTEGRATION_CPP_TEST"],
},
no_match_error = "Explicit test setting must be configured //settings:with_test",
),
tags = ["manual"],
visibility = ["//test:__subpackages__"],
deps = ["//:jemalloc_core"] + select(
{
"//settings:integration_test": ["//:utils"],
"//settings:integration_cpp_test": ["//:utils"],
"//conditions:default": [],
},
),
)

View file

@ -0,0 +1,118 @@
load("@rules_cc//cc:defs.bzl", "cc_test")
load("//:tools/cc.bzl", "COPTS")
load("//:tools/transition.bzl", "PLATFORM", "transition_default_constraints")
INTEGRATION_TESTS = [
{"src": "allocated.c"},
{
"src": "extent.c",
"conf": "junk:false",
},
{"src": "malloc.c"},
{
"src": "mallocx.c",
"conf": "junk:false",
},
{"src": "MALLOCX_ARENA.c"},
{"src": "overflow.c"},
{"src": "posix_memalign.c"},
{"src": "rallocx.c"},
{"src": "sdallocx.c"},
{
"src": "slab_sizes.c",
"conf": "slab_sizes:1-4096:17|100-200:1|128-128:2",
},
{"src": "thread_arena.c"},
{"src": "thread_tcache_enabled.c"},
{
"src": "xallocx.c",
"conf": "junk:false",
},
]
INTEGRATION_DECAY_TESTS = [
{
"name": "%s_%s" % (
test["name"] if "name" in test else test["src"].removesuffix(".c").replace("/", "_"),
config["suffix"],
),
"src": test["src"],
"conf": "%s,%s" % (
test["conf"],
config["conf"],
) if "conf" in test else config["conf"],
}
for config in [
{
"suffix": "decay_minus_one",
"conf": "dirty_decay_ms:-1,muzzy_decay_ms:-1",
},
{
"suffix": "decay_zero",
"conf": "dirty_decay_ms:0,muzzy_decay_ms:0",
},
]
for test in INTEGRATION_TESTS
]
transition_default_constraints(
name = "testlib",
testonly = True,
src = "//test:testlib",
platform = PLATFORM,
settings = {
"//settings:with_test": "integration",
"//settings/flags:enable_fill": "True",
# This needs to be pinned for testing. The MALLOC_CONF ENV depends on it. The make build allows for it to be
# set dynamically via templating and generates a test harness around it. By requiring a value that cannot be
# set internally by accident, this exercises the same functionality.
"//settings/flags:jemalloc_prefix": "je_test_",
},
visibility = ["//:__subpackages__"],
)
[cc_test(
name = test["name"] if "name" in test else test["src"].removesuffix(".c").replace("/", "_"),
srcs = [test["src"]],
copts = COPTS,
env = {"JE_TEST_MALLOC_CONF": test.get("conf", "")},
local_defines = ["JEMALLOC_INTEGRATION_TEST"],
deps = [":testlib"],
) for test in INTEGRATION_TESTS + INTEGRATION_DECAY_TESTS]
INTEGRATION_CPP_TESTS = [
{"src": "cpp/basic.cpp"},
{
"src": "cpp/infallible_new_true.cpp",
"conf": "experimental_infallible_new:true",
},
{
"src": "cpp/infallible_new_false.cpp",
"conf": "experimental_infallible_new:false",
},
]
transition_default_constraints(
name = "testlib_cpp",
testonly = True,
src = "//test:testlib",
platform = PLATFORM,
settings = {
"//settings:with_test": "integration_cpp",
"//settings/flags:enable_fill": "True",
# This needs to be pinned for testing. The MALLOC_CONF ENV depends on it. The make build allows for it to be
# set dynamically via templating and generates a test harness around it. By requiring a value that cannot be
# set internally by accident, this exercises the same functionality.
"//settings/flags:jemalloc_prefix": "je_test_",
},
visibility = ["//:__subpackages__"],
)
[cc_test(
name = test["name"] if "name" in test else test["src"].removesuffix(".cpp").replace("/", "_"),
srcs = [test["src"]],
copts = COPTS,
env = {"JE_TEST_MALLOC_CONF": test.get("conf", "")},
local_defines = ["JEMALLOC_INTEGRATION_CPP_TEST"],
deps = [":testlib_cpp"],
) for test in INTEGRATION_CPP_TESTS]

View file

@ -181,7 +181,7 @@ p_test_impl(bool do_malloc_init, bool do_reentrant, test_t *t, va_list ap) {
test_status_string(test_status_fail),
test_counts[test_status_fail], test_count);
return ret;
return (ret == test_status_skip) ? test_status_pass : ret;
}
test_status_t

173
test/unit/BUILD.bazel Normal file
View file

@ -0,0 +1,173 @@
load("@rules_cc//cc:defs.bzl", "cc_test")
load("//:tools/cc.bzl", "COPTS")
load("//:tools/transition.bzl", "PLATFORM", "transition_default_constraints")
# TODO: Handle conf when enable_prof = True
#{ "src": "batch_alloc_prof.c" },
#{ "src": "arena_reset_prof.c" },
UNIT_TESTS = [
{"src": "a0.c"},
{
"src": "arena_decay.c",
"conf": "dirty_decay_ms:1000,muzzy_decay_ms:1000,tcache_max:1024",
},
{"src": "arena_reset.c"},
{"src": "atomic.c"},
{"src": "background_thread.c"},
{"src": "background_thread_enable.c"},
{"src": "base.c"},
{"src": "batch_alloc.c"},
{
"src": "binshard.c",
"conf": "narenas:1,bin_shards:1-160:16|129-512:4|256-256:8",
},
{"src": "bitmap.c"},
{"src": "bit_util.c"},
{"src": "buf_writer.c"},
{"src": "cache_bin.c"},
{"src": "ckh.c"},
{"src": "counter.c"},
{"src": "decay.c"},
{"src": "div.c"},
{"src": "double_free.c"},
{"src": "edata_cache.c"},
{"src": "emitter.c"},
{"src": "extent_quantize.c"},
{"src": "fb.c"},
{"src": "fork.c"},
{"src": "fxp.c"},
{
"src": "san.c",
"conf": "san_guard_large:1,san_guard_small:1",
},
{"src": "san_bump.c"},
{"src": "hash.c"},
{"src": "hook.c"},
{"src": "hpa.c"},
{
"src": "hpa_background_thread.c",
"conf": "hpa_dirty_mult:0,hpa_min_purge_interval_ms:50,hpa_sec_nshards:0",
},
{"src": "hpdata.c"},
{"src": "huge.c"},
{"src": "inspect.c"},
{
"src": "junk.c",
"conf": "abort:false,zero:false,junk:true",
},
{
"name": "unit_junk_alloc",
"src": "junk.c",
"conf": "abort:false,zero:false,junk:alloc",
},
{
"name": "unit_junk_free",
"src": "junk.c",
"conf": "abort:false,zero:false,junk:free",
},
{"src": "log.c"},
{"src": "mallctl.c"},
{"src": "malloc_conf_2.c"},
{"src": "malloc_io.c"},
{"src": "math.c"},
{"src": "mpsc_queue.c"},
{"src": "mq.c"},
{"src": "mtx.c"},
{"src": "nstime.c"},
{"src": "oversize_threshold.c"},
{"src": "pa.c"},
{"src": "pack.c"},
{"src": "pages.c"},
{"src": "peak.c"},
{"src": "ph.c"},
{"src": "prng.c"},
{"src": "prof_accum.c"},
{"src": "prof_active.c"},
{"src": "prof_gdump.c"},
{"src": "prof_hook.c"},
{"src": "prof_idump.c"},
{"src": "prof_log.c"},
{"src": "prof_mdump.c"},
{"src": "prof_recent.c"},
{"src": "prof_reset.c"},
{"src": "prof_stats.c"},
{"src": "prof_tctx.c"},
{"src": "prof_thread_name.c"},
{"src": "prof_sys_thread_name.c"},
{"src": "psset.c"},
{"src": "ql.c"},
{"src": "qr.c"},
{"src": "rb.c"},
{"src": "retained.c"},
{"src": "rtree.c"},
{"src": "safety_check.c"},
{"src": "sc.c"},
{"src": "sec.c"},
{"src": "seq.c"},
{"src": "SFMT.c"},
{"src": "size_check.c"},
{"src": "size_classes.c"},
{"src": "slab.c"},
{"src": "smoothstep.c"},
{"src": "spin.c"},
{"src": "stats.c"},
{"src": "stats_print.c"},
{"src": "sz.c"},
{
"src": "tcache_max.c",
"conf": "tcache_max:1024",
},
{"src": "test_hooks.c"},
{"src": "thread_event.c"},
{"src": "ticker.c"},
{"src": "tsd.c"},
{"src": "uaf.c"},
{"src": "witness.c"},
{
"src": "zero.c",
"conf": "abort:false,junk:false,zero:true",
},
{
"src": "zero_realloc_abort.c",
"conf": "zero_realloc:abort",
},
{
"src": "zero_realloc_free.c",
"conf": "zero_realloc:free",
},
{
"src": "zero_realloc_alloc.c",
"conf": "zero_realloc:alloc",
},
{
"src": "zero_reallocs.c",
"conf": "zero_realloc:free",
},
]
transition_default_constraints(
name = "testlib",
testonly = True,
src = "//test:testlib",
platform = PLATFORM,
settings = {
"//settings:enable_jet": "True",
"//settings:with_test": "unit",
"//settings/flags:enable_fill": "True",
# This needs to be pinned for testing. The MALLOC_CONF ENV depends on it. The make build allows for it to be
# set dynamically via templating and generates a test harness around it. By requiring a value that cannot be
# set internally by accident, this exercises the same functionality.
"//settings/flags:jemalloc_prefix": "je_test_",
},
visibility = ["//:__subpackages__"],
)
[cc_test(
name = test["name"] if "name" in test else test["src"].removesuffix(".c").replace("/", "_"),
srcs = [test["src"]],
copts = COPTS,
env = {"JE_TEST_MALLOC_CONF": test.get("conf", "")},
linkstatic = True,
local_defines = ["JEMALLOC_UNIT_TEST"],
deps = [":testlib"],
) for test in UNIT_TESTS]

113
tools/autoconf.bzl Normal file
View file

@ -0,0 +1,113 @@
"Utilities for replicating autoconf behavior"
load("@aspect_bazel_lib//lib:expand_template.bzl", "expand_template")
def define_macro_if(macro, condition):
"""Controls conditional macro definition based on a build condition.
Args:
macro: String macro name to define
condition: Build condition that should enable the macro
Returns:
A select dictionary mapping conditions to substitution dictionaries
"""
return select({
condition: define_macro(macro),
"//conditions:default": undefine_macro(macro),
})
def define_macro_if_with(macro, condition, value):
"""Conditionally defines a macro with a specific value based on a build condition.
Args:
macro: String macro name to define
condition: Build condition that should enable the macro
value: Value to assign to the macro when defined
Returns:
A select dictionary mapping conditions to substitution dictionaries
"""
return select({
condition: define_macro_with(macro, value),
"//conditions:default": undefine_macro(macro),
})
def define_macro(macro):
"""Unconditionally defines a macro.
Args:
macro: String macro name to define
Returns:
A substitution dictionary for the macro
"""
return {"#undef {}".format(macro): "#define {}".format(macro)}
def define_macro_if_any(macro, conditions):
"""Defines a macro if any of the specified conditions are met.
Args:
macro: String macro name to define
conditions: List of build conditions that should individually enable the macro
Returns:
A select dictionary mapping conditions to substitution dictionaries
"""
substitutions = {}
defined = define_macro(macro)
for condition in conditions:
substitutions[condition] = defined
substitutions["//conditions:default"] = undefine_macro(macro)
return select(substitutions)
def define_macro_with(macro, value):
"""Unconditionally defines a macro with a specific value.
Args:
macro: String macro name to define
value: Value to assign to the macro
Returns:
A substitution dictionary for the macro with value
"""
return {"#undef {}".format(macro): "#define {} {}".format(macro, value)}
def undefine_macro(macro):
"""Explicitly undefines a macro with a commented annotation.
Args:
macro: String macro name to undefine
Returns:
A substitution dictionary that replaces the undef with a comment
"""
return {"#undef {}".format(macro): "/* #UNDEF {} */".format(macro)}
def configure_header(name, substitutions, **kwargs):
"""Generates a header file with autoconf-style macro substitutions.
Args:
name: Target name
substitutions: Dictionary of substitutions to apply
**kwargs: Additional arguments passed to expand_template
Returns:
The processed header file with all substitutions applied
"""
return expand_template(
name = name,
# The expand_template substitutions are applied serially and overlapping macro names can interfere with each other.
# Explicitly marking that a macro has been processed such that the template string no longer matches prevents this.
substitutions = substitutions | {"#UNDEF": "#undef"},
**kwargs
)

50
tools/cc.bzl Normal file
View file

@ -0,0 +1,50 @@
"Project specific configuration of rules_cc"
load("@bazel_skylib//lib:selects.bzl", "selects")
_COPTS_GCC_COMPATIBLE = [
"-Wall",
"-Wextra",
"-Wsign-compare",
"-Wundef",
"-Wno-format-zero-length",
"-Wpointer-arith",
"-Wno-missing-braces",
"-Wno-missing-field-initializers",
"-Wimplicit-fallthrough",
"-pipe",
]
_COPTS_GCC = _COPTS_GCC_COMPATIBLE + ["-Wno-missing-attributes"]
_COPTS_MSVC_COMPATIBLE = [
"/Zi",
"/MT",
"/W3",
"/FS",
]
# Platform and compiler COPTS consistent with configure/make
COPTS = ["-D_REENTRANT"] + select({
"@rules_cc//cc/compiler:clang": _COPTS_GCC_COMPATIBLE + ["-Wshorten-64-to-32"],
"@rules_cc//cc/compiler:gcc": _COPTS_GCC,
"@rules_cc//cc/compiler:mingw-gcc": _COPTS_GCC,
"@rules_cc//cc/compiler:msvc-cl": _COPTS_MSVC_COMPATIBLE,
"@rules_cc//cc/compiler:clang-cl": _COPTS_MSVC_COMPATIBLE,
"//conditions:default": [],
}) + selects.with_or({
("@platforms//os:windows", "//settings/platform:darwin"): [],
"//settings/compiler:gcc_compatible": ["-fvisibility=hidden"],
"//conditions:default": [],
}) + selects.with_or({
("@platforms//os:android", "@platforms//os:linux"): [
"-DPIC",
"-D_GNU_SOURCE",
],
"@platforms//os:freebsd": [
"-DPIC",
"-D_BSD_SOURCE",
],
"@platforms//os:macos": ["-DPIC"],
"//conditions:default": [],
})

109
tools/transition.bzl Normal file
View file

@ -0,0 +1,109 @@
"Transition build and platform settings"
load("@rules_cc//cc:defs.bzl", "CcInfo")
PLATFORM = select({
"@platforms//os:freebsd": "freebsd",
"@platforms//os:linux": "linux",
"@platforms//os:windows": "windows",
"//settings/platform:darwin": "darwin",
"//conditions:default": "unknown",
})
def _platform_constraints_transition_impl(settings, attr):
# Assume typical defaults for target platforms
default_settings = {
"//settings/flags:enable_zone_allocator": {"darwin": "yes", "default": "no"},
"//settings/platform:glibc_overrides_support": {"linux": "yes", "default": "no"},
"//settings/platform:lg_page": {"darwin": "14", "default": "12"},
"//settings/platform:memalign_support": {"linux": "yes", "default": "no"},
"//settings/platform:malloc_size_support": {"darwin": "yes", "default": "no"},
"//settings/platform:usable_size_const": {"linux": "", "default": "const"},
"//settings/platform:valloc_support": {"darwin": "yes", "linux": "yes", "default": "no"},
}
result = {}
for label, platform_defaults in default_settings.items():
configured_value = settings[label]
# If unset, use platform-specific default or universal fallback
result[label] = (platform_defaults.get(attr.platform, platform_defaults["default"]) if configured_value == "__auto__" else configured_value)
# Apply explicitly passed settings
boolean_settings = ["//settings:enable_jet", "//settings/flags:enable_fill"]
for setting in boolean_settings:
result[setting] = attr.settings[Label(setting)] == "True" if Label(setting) in attr.settings else settings[setting]
string_settings = ["//settings:with_test", "//settings/flags:jemalloc_prefix"]
for setting in string_settings:
result[setting] = attr.settings[Label(setting)] if Label(setting) in attr.settings else settings[setting]
# Equivalent of JEMALLOC_CPREFIX=`echo ${JEMALLOC_PREFIX} | tr "a-z" "A-Z"`
result["//settings/flags:jemalloc_cprefix"] = result["//settings/flags:jemalloc_prefix"].upper()
return result
_platform_constraints_transition = transition(
implementation = _platform_constraints_transition_impl,
inputs = [
"//settings:enable_jet",
"//settings:with_test",
"//settings/flags:jemalloc_prefix",
"//settings/flags:jemalloc_cprefix",
"//settings/flags:enable_fill",
"//settings/flags:enable_zone_allocator",
"//settings/platform:glibc_overrides_support",
"//settings/platform:lg_page",
"//settings/platform:malloc_size_support",
"//settings/platform:memalign_support",
"//settings/platform:usable_size_const",
"//settings/platform:valloc_support",
],
outputs = [
"//settings:enable_jet",
"//settings:with_test",
"//settings/flags:jemalloc_prefix",
"//settings/flags:jemalloc_cprefix",
"//settings/flags:enable_fill",
"//settings/flags:enable_zone_allocator",
"//settings/platform:glibc_overrides_support",
"//settings/platform:lg_page",
"//settings/platform:malloc_size_support",
"//settings/platform:memalign_support",
"//settings/platform:usable_size_const",
"//settings/platform:valloc_support",
],
)
def _transition_default_constraints_impl(ctx):
target = ctx.attr.src[0]
providers = [DefaultInfo, CcInfo, InstrumentedFilesInfo, OutputGroupInfo]
return [target[provider] for provider in providers if provider in target]
transition_default_constraints = rule(
doc = "Configure detects target platform constraints. The target platform should declare these, but " +
"intelligent defaults can be set for the majority of cases.",
implementation = _transition_default_constraints_impl,
attrs = {
"src": attr.label(cfg = _platform_constraints_transition),
"platform": attr.string(
doc = "Hack to inject platform constraints into the transition to apply unset defaults",
mandatory = True,
values = [
"freebsd",
"linux",
"darwin",
"windows",
"unknown",
],
),
"settings": attr.label_keyed_string_dict(
doc = "Settings to explicitly transition",
default = {},
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
},
)

27
tools/version.bzl Normal file
View file

@ -0,0 +1,27 @@
"Version string utilities."
def parse_version(version):
"""Parses raw version string into a structured version object.
Returns:
struct: Contains version components:
- full: Full version
- gid: Version git id
- major: Major version number
- minor: Minor version number
- patch: Patch version number
- bugfix: Bugfix version
- nrev: Revision number
"""
prefix, gid = version.split("-bcr", 2)
major, minor, patch = prefix.split(".", 3)
return struct(
full = prefix,
gid = "0",
major = major,
minor = minor,
patch = patch,
bugfix = "0",
nrev = "0",
)