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

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"),
},
)