1# Copyright 2020 The Pigweed Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4# use this file except in compliance with the License. You may obtain a copy of 5# the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations under 13# the License. 14 15load("@rules_cc//cc:cc_library.bzl", "cc_library") 16load("@rules_python//sphinxdocs:sphinx_docs_library.bzl", "sphinx_docs_library") 17load("//pw_build:compatibility.bzl", "incompatible_with_mcu") 18load("//pw_build:pw_facade.bzl", "pw_facade") 19load("//pw_unit_test:pw_cc_test.bzl", "pw_cc_test") 20 21package( 22 default_visibility = ["//visibility:public"], 23 features = ["-layering_check"], 24) 25 26licenses(["notice"]) 27 28constraint_setting( 29 name = "backend_constraint_setting", 30) 31 32# TODO: pwbug.dev/328679085 - Remove this alias once no-one uses it. 33alias( 34 name = "facade", 35 actual = "pw_malloc.facade", 36) 37 38cc_library( 39 name = "common", 40 linkopts = [ 41 # Link options that replace dynamic memory operations in standard 42 # library with the pigweed malloc. 43 "-Wl,--wrap=malloc", 44 "-Wl,--wrap=free", 45 "-Wl,--wrap=realloc", 46 "-Wl,--wrap=calloc", 47 "-Wl,--wrap=_malloc_r", 48 "-Wl,--wrap=_realloc_r", 49 "-Wl,--wrap=_free_r", 50 "-Wl,--wrap=_calloc_r", 51 ], 52 visibility = ["//visibility:private"], 53 deps = [ 54 "//pw_allocator:allocator", 55 "//pw_allocator:synchronized_allocator", 56 "//pw_allocator:tracking_allocator", 57 "//pw_bytes", 58 "//pw_preprocessor", 59 ], 60) 61 62pw_facade( 63 name = "pw_malloc", 64 srcs = ["malloc.cc"], 65 hdrs = [ 66 "public/pw_malloc/config.h", 67 "public/pw_malloc/malloc.h", 68 ], 69 backend = ":backend", 70 strip_include_prefix = "public", 71 deps = [ 72 ":common", 73 ":config_override", 74 "//pw_assert:check", 75 ], 76 alwayslink = 1, 77) 78 79label_flag( 80 name = "config_override", 81 build_setting_default = "//pw_build:default_module_config", 82) 83 84label_flag( 85 name = "backend", 86 build_setting_default = ":backend_multiplexer", 87) 88 89constraint_value( 90 name = "best_fit_backend", 91 constraint_setting = "//pw_malloc:backend_constraint_setting", 92) 93 94# TODO(b/376730645): Remove deprecated backends. 95constraint_value( 96 name = "best_fit_block_allocator_backend", 97 constraint_setting = "//pw_malloc:backend_constraint_setting", 98) 99 100constraint_value( 101 name = "bucket_allocator_backend", 102 constraint_setting = "//pw_malloc:backend_constraint_setting", 103) 104 105# TODO(b/376730645): Remove deprecated backends. 106constraint_value( 107 name = "bucket_block_allocator_backend", 108 constraint_setting = "//pw_malloc:backend_constraint_setting", 109) 110 111constraint_value( 112 name = "first_fit_backend", 113 constraint_setting = "//pw_malloc:backend_constraint_setting", 114) 115 116# TODO(b/376730645): Remove deprecated backends. 117constraint_value( 118 name = "dual_first_fit_block_allocator_backend", 119 constraint_setting = "//pw_malloc:backend_constraint_setting", 120) 121 122# TODO(b/376730645): Remove deprecated backends. 123constraint_value( 124 name = "first_fit_block_allocator_backend", 125 constraint_setting = "//pw_malloc:backend_constraint_setting", 126) 127 128# TODO(b/376730645): Remove deprecated backends. 129constraint_value( 130 name = "last_fit_block_allocator_backend", 131 constraint_setting = "//pw_malloc:backend_constraint_setting", 132) 133 134constraint_value( 135 name = "freelist_backend", 136 constraint_setting = "//pw_malloc:backend_constraint_setting", 137) 138 139constraint_value( 140 name = "worst_fit_backend", 141 constraint_setting = "//pw_malloc:backend_constraint_setting", 142) 143 144# TODO(b/376730645): Remove deprecated backends. 145constraint_value( 146 name = "worst_fit_block_allocator_backend", 147 constraint_setting = "//pw_malloc:backend_constraint_setting", 148) 149 150# TODO(b/376730645): Remove deprecated backends. 151alias( 152 name = "backend_multiplexer", 153 actual = select({ 154 "//pw_malloc:best_fit_block_allocator_backend": "//pw_malloc:best_fit", 155 "//pw_malloc:bucket_allocator_backend": "//pw_malloc:bucket_allocator", 156 "//pw_malloc:bucket_block_allocator_backend": "//pw_malloc:bucket_allocator", 157 "//pw_malloc:dual_first_fit_block_allocator_backend": "//pw_malloc:first_fit", 158 "//pw_malloc:first_fit_block_allocator_backend": "//pw_malloc:first_fit", 159 "//pw_malloc:last_fit_block_allocator_backend": "//pw_malloc:first_fit", 160 "//pw_malloc:worst_fit_block_allocator_backend": "//pw_malloc:worst_fit", 161 "//pw_malloc_freelist:backend": "//pw_malloc:bucket_allocator", 162 "//pw_malloc_freertos:backend": "//pw_malloc_freertos", 163 "//conditions:default": "//pw_build:unspecified_backend", 164 }), 165 visibility = ["//targets:__pkg__"], 166) 167 168cc_library( 169 name = "best_fit", 170 srcs = ["best_fit.cc"], 171 deps = [ 172 ":pw_malloc.facade", 173 "//pw_allocator:best_fit", 174 ], 175) 176 177# TODO(b/376730645): Remove deprecated backends. 178cc_library( 179 name = "best_fit_block_allocator", 180 deps = [":best_fit"], 181) 182 183cc_library( 184 name = "bucket_allocator", 185 srcs = ["bucket_allocator.cc"], 186 deps = [ 187 "//pw_allocator:bucket_allocator", 188 "//pw_malloc:facade", 189 ], 190) 191 192# TODO(b/376730645): Remove deprecated backends. 193cc_library( 194 name = "bucket_block_allocator", 195 deps = [":bucket_allocator"], 196) 197 198cc_library( 199 name = "first_fit", 200 srcs = ["first_fit.cc"], 201 deps = [ 202 "//pw_allocator:first_fit", 203 "//pw_malloc:facade", 204 ], 205) 206 207# TODO(b/376730645): Remove deprecated backends. 208cc_library( 209 name = "dual_first_fit_block_allocator", 210 deps = [":first_fit"], 211) 212 213# TODO(b/376730645): Remove deprecated backends. 214cc_library( 215 name = "first_fit_block_allocator", 216 deps = [":first_fit"], 217) 218 219# TODO(b/376730645): Remove deprecated backends. 220cc_library( 221 name = "last_fit_block_allocator", 222 deps = [":first_fit"], 223) 224 225cc_library( 226 name = "worst_fit", 227 srcs = ["worst_fit.cc"], 228 deps = [ 229 "//pw_allocator:worst_fit", 230 "//pw_malloc:facade", 231 ], 232) 233 234cc_library( 235 name = "testing", 236 testonly = True, 237 srcs = ["malloc.cc"], 238 hdrs = [ 239 "public/pw_malloc/config.h", 240 "public/pw_malloc/internal/testing.h", 241 "public/pw_malloc/malloc.h", 242 ], 243 defines = [ 244 "PW_MALLOC_METRICS_INCLUDE=\\\"pw_malloc/internal/testing.h\\\"", 245 "PW_MALLOC_METRICS_TYPE=::pw::malloc::internal::TestMetrics", 246 "PW_MALLOC_BLOCK_OFFSET_TYPE=uint16_t", 247 "PW_MALLOC_MIN_BUCKET_SIZE=64", 248 "PW_MALLOC_NUM_BUCKETS=4", 249 ], 250 implementation_deps = [ 251 "//pw_assert:check", 252 "//pw_tokenizer:decoder", 253 ], 254 strip_include_prefix = "public", 255 256 # Only run the test if no backend is set to ensure there is no system 257 # allocator. 258 target_compatible_with = select({ 259 "//pw_malloc:best_fit_block_allocator_backend": ["@platforms//:incompatible"], 260 "//pw_malloc:bucket_allocator_backend": ["@platforms//:incompatible"], 261 "//pw_malloc:bucket_block_allocator_backend": ["@platforms//:incompatible"], 262 "//pw_malloc:dual_first_fit_block_allocator_backend": ["@platforms//:incompatible"], 263 "//pw_malloc:first_fit_block_allocator_backend": ["@platforms//:incompatible"], 264 "//pw_malloc:last_fit_block_allocator_backend": ["@platforms//:incompatible"], 265 "//pw_malloc:worst_fit_block_allocator_backend": ["@platforms//:incompatible"], 266 "//pw_malloc_freelist:backend": ["@platforms//:incompatible"], 267 "//pw_malloc_freertos:backend": ["@platforms//:incompatible"], 268 "//conditions:default": [], 269 }) + 270 271 # Currently only supported for host unit tests on Linux. 272 select({ 273 "@platforms//os:linux": [], 274 "//conditions:default": ["@platforms//:incompatible"], 275 }) + 276 277 # Only run using the light framework, since gtest allocates objects before 278 # the test fixture initializes the heap. 279 select({ 280 "//pw_unit_test:light_setting": [], 281 "//conditions:default": ["@platforms//:incompatible"], 282 }) + 283 284 # Don't run with ASAN or TSAN, since they wrap malloc. 285 select({ 286 "//pw_toolchain/host_clang:asan_enabled": ["@platforms//:incompatible"], 287 "//pw_toolchain/host_clang:tsan_enabled": ["@platforms//:incompatible"], 288 "//conditions:default": [], 289 }), 290 visibility = ["//visibility:private"], 291 deps = [ 292 ":common", 293 "//pw_tokenizer:decoder", 294 "//pw_unit_test:light", 295 ], 296) 297 298pw_cc_test( 299 name = "best_fit_test", 300 srcs = [ 301 "best_fit.cc", 302 "malloc_test.cc", 303 ], 304 # TODO: b/379937425 - Enable when internal toolchains are sorted out. 305 tags = ["manual"], 306 deps = [ 307 ":testing", 308 "//pw_allocator:best_fit", 309 ], 310) 311 312pw_cc_test( 313 name = "bucket_allocator_test", 314 srcs = [ 315 "bucket_allocator.cc", 316 "malloc_test.cc", 317 ], 318 # TODO: b/379937425 - Enable when internal toolchains are sorted out. 319 tags = ["manual"], 320 deps = [ 321 ":testing", 322 "//pw_allocator:bucket_allocator", 323 ], 324) 325 326pw_cc_test( 327 name = "first_fit_test", 328 srcs = [ 329 "first_fit.cc", 330 "malloc_test.cc", 331 ], 332 # TODO: b/379937425 - Enable when internal toolchains are sorted out. 333 tags = ["manual"], 334 deps = [ 335 ":testing", 336 "//pw_allocator:first_fit", 337 ], 338) 339 340pw_cc_test( 341 name = "worst_fit_test", 342 srcs = [ 343 "malloc_test.cc", 344 "worst_fit.cc", 345 ], 346 # TODO: b/379937425 - Enable when internal toolchains are sorted out. 347 tags = ["manual"], 348 deps = [ 349 ":testing", 350 "//pw_allocator:worst_fit", 351 ], 352) 353 354filegroup( 355 name = "doxygen", 356 srcs = [ 357 "public/pw_malloc/config.h", 358 "public/pw_malloc/malloc.h", 359 ], 360) 361 362sphinx_docs_library( 363 name = "docs", 364 srcs = [ 365 "backends.rst", 366 "docs.rst", 367 ], 368 prefix = "pw_malloc/", 369 target_compatible_with = incompatible_with_mcu(), 370) 371