• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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