xref: /aosp_15_r20/external/pigweed/pw_malloc/BUILD.gn (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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