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 15import("//build_overrides/pigweed.gni") 16 17import("$dir_pw_build/facade.gni") 18import("$dir_pw_build/module_config.gni") 19import("$dir_pw_docgen/docs.gni") 20import("$dir_pw_malloc/backend.gni") 21import("$dir_pw_unit_test/test.gni") 22 23declare_args() { 24 # The build target that overrides the default configuration options for this 25 # module. This should point to a source set that provides defines through a 26 # public config (which may -include a file or add defines directly). 27 pw_malloc_CONFIG = pw_build_DEFAULT_MODULE_CONFIG 28} 29 30pw_source_set("config") { 31 public_configs = [ ":public_include_path" ] 32 public = [ "public/pw_malloc/config.h" ] 33 public_deps = [ 34 "$dir_pw_allocator:synchronized_allocator", 35 "$dir_pw_allocator:tracking_allocator", 36 pw_malloc_CONFIG, 37 ] 38} 39 40config("public_include_path") { 41 include_dirs = [ "public" ] 42} 43 44config("private_include_path") { 45 include_dirs = [ "." ] 46} 47 48config("wrap_functions") { 49 # Link options that provides replace dynamic memory operations in standard 50 # library with the pigweed malloc. 51 ldflags = [ 52 # memory allocation -- these must be re-entrant and do locking 53 "-Wl,--wrap=malloc", 54 "-Wl,--wrap=free", 55 "-Wl,--wrap=realloc", 56 "-Wl,--wrap=calloc", 57 58 # Wrap these in case internal newlib call them (e.g. strdup will) 59 # directly call _malloc_r) 60 "-Wl,--wrap=_malloc_r", 61 "-Wl,--wrap=_realloc_r", 62 "-Wl,--wrap=_free_r", 63 "-Wl,--wrap=_calloc_r", 64 ] 65} 66 67# Alias for `:wrap_functions`. 68config("pw_malloc_wrapper_config") { 69 configs = [ ":wrap_functions" ] 70} 71 72_COMMON_SRCS = [ "malloc.cc" ] 73 74_COMMON_HDRS = [ "public/pw_malloc/malloc.h" ] 75 76group("common") { 77 visibility = [ ":*" ] 78 public_configs = [ 79 ":public_include_path", 80 ":wrap_functions", 81 ] 82 public_deps = [ 83 ":config", 84 "$dir_pw_allocator:allocator", 85 dir_pw_assert, 86 dir_pw_bytes, 87 dir_pw_preprocessor, 88 ] 89} 90 91pw_facade("pw_malloc") { 92 backend = pw_malloc_BACKEND 93 public = _COMMON_HDRS 94 sources = _COMMON_SRCS 95 public_deps = [ ":common" ] 96} 97 98# Allocator-based backends. 99 100pw_source_set("best_fit") { 101 public_deps = [ ":pw_malloc.facade" ] 102 deps = [ "$dir_pw_allocator:best_fit" ] 103 sources = [ "best_fit.cc" ] 104} 105 106# TODO(b/376730645): Remove deprecated backends. 107pw_source_set("best_fit_block_allocator") { 108 public_deps = [ ":best_fit" ] 109} 110 111pw_source_set("bucket_allocator") { 112 public_deps = [ ":pw_malloc.facade" ] 113 deps = [ "$dir_pw_allocator:bucket_allocator" ] 114 sources = [ "bucket_allocator.cc" ] 115} 116 117# TODO(b/376730645): Remove deprecated backends. 118pw_source_set("bucket_block_allocator") { 119 public_deps = [ ":bucket_allocator" ] 120} 121 122# TODO(b/376730645): Remove deprecated backends. 123pw_source_set("dual_first_fit_block_allocator") { 124 public_deps = [ ":first_fit" ] 125} 126 127pw_source_set("first_fit") { 128 public_deps = [ ":pw_malloc.facade" ] 129 deps = [ "$dir_pw_allocator:first_fit" ] 130 sources = [ "first_fit.cc" ] 131} 132 133# TODO(b/376730645): Remove deprecated backends. 134pw_source_set("first_fit_block_allocator") { 135 public_deps = [ ":first_fit" ] 136} 137 138# TODO(b/376730645): Remove deprecated backends. 139pw_source_set("last_fit_block_allocator") { 140 public_deps = [ ":first_fit" ] 141} 142 143pw_source_set("worst_fit") { 144 public_deps = [ ":pw_malloc.facade" ] 145 deps = [ "$dir_pw_allocator:worst_fit" ] 146 sources = [ "worst_fit.cc" ] 147} 148 149# TODO(b/376730645): Remove deprecated backends. 150pw_source_set("worst_fit_block_allocator") { 151 public_deps = [ ":worst_fit" ] 152} 153 154# Backend unit tests. 155 156pw_source_set("testing") { 157 configs = [ ":private_include_path" ] 158 defines = [ 159 "PW_MALLOC_METRICS_INCLUDE=\"pw_malloc/internal/testing.h\"", 160 "PW_MALLOC_METRICS_TYPE=::pw::malloc::internal::TestMetrics", 161 "PW_MALLOC_BLOCK_OFFSET_TYPE=uint16_t", 162 "PW_MALLOC_MIN_BUCKET_SIZE=64", 163 "PW_MALLOC_NUM_BUCKETS=4", 164 ] 165 public = _COMMON_HDRS + [ "public/pw_malloc/internal/testing.h" ] 166 sources = _COMMON_SRCS + [ "malloc_test.cc" ] 167 public_deps = [ ":common" ] 168 deps = [ 169 "$dir_pw_tokenizer:decoder", 170 "$dir_pw_unit_test:light", 171 ] 172} 173 174pw_test("best_fit_test") { 175 deps = [ 176 ":testing", 177 "$dir_pw_allocator:best_fit", 178 ] 179 sources = [ "best_fit.cc" ] 180} 181 182pw_test("bucket_allocator_test") { 183 deps = [ 184 ":testing", 185 "$dir_pw_allocator:bucket_allocator", 186 ] 187 sources = [ "bucket_allocator.cc" ] 188} 189 190pw_test("first_fit_test") { 191 deps = [ 192 ":testing", 193 "$dir_pw_allocator:first_fit", 194 ] 195 sources = [ "first_fit.cc" ] 196} 197 198pw_test("worst_fit_test") { 199 deps = [ 200 ":testing", 201 "$dir_pw_allocator:worst_fit", 202 ] 203 sources = [ "worst_fit.cc" ] 204} 205 206# Docs 207 208pw_doc_group("docs") { 209 sources = [ 210 "backends.rst", 211 "docs.rst", 212 ] 213} 214 215pw_test_group("tests") { 216 # Only run the test if no backend is set to ensure there is no system 217 # allocator. 218 enable_if = pw_malloc_BACKEND == "" 219 220 # Currently only supported for host unit tests on Linux. 221 enable_if = enable_if && defined(pw_toolchain_SCOPE.is_host_toolchain) && 222 pw_toolchain_SCOPE.is_host_toolchain && host_os == "linux" 223 224 # Only run using the light framework, since gtest allocates objects before the 225 # test fixture initializes the heap. 226 enable_if = enable_if && pw_unit_test_BACKEND == "$dir_pw_unit_test:light" 227 228 # Don't run with ASAN and TSAN since they wrap malloc. 229 default_configs = [] 230 if (defined(pw_toolchain_SCOPE.defaults)) { 231 defaults = pw_toolchain_SCOPE.defaults 232 if (defined(defaults.default_configs)) { 233 default_configs = defaults.default_configs 234 } 235 } 236 conflicting = [ 237 "$dir_pw_toolchain/host_clang:sanitize_address", 238 "$dir_pw_toolchain/host_clang:sanitize_thread", 239 ] 240 enable_if = enable_if && 241 default_configs + conflicting - conflicting == default_configs 242 243 tests = [ 244 ":best_fit_test", 245 ":bucket_allocator_test", 246 ":first_fit_test", 247 ":worst_fit_test", 248 ] 249} 250