xref: /llvm-project/utils/bazel/llvm-project-overlay/libc/libc_build_rules.bzl (revision c388da6ed38ba8892edb90803b76bcfe759fe3cf)
1# This file is licensed under the Apache License v2.0 with LLVM Exceptions.
2# See https://llvm.org/LICENSE.txt for license information.
3# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5"""LLVM libc starlark rules for building individual functions."""
6
7load("@bazel_skylib//lib:paths.bzl", "paths")
8load("@bazel_skylib//lib:selects.bzl", "selects")
9load(":libc_configure_options.bzl", "LIBC_CONFIGURE_OPTIONS")
10load(":libc_namespace.bzl", "LIBC_NAMESPACE")
11load(":platforms.bzl", "PLATFORM_CPU_X86_64")
12
13def libc_internal_target(name):
14    return name + ".__internal__"
15
16def libc_common_copts():
17    root_label = Label(":libc")
18    libc_include_path = paths.join(root_label.workspace_root, root_label.package)
19    return [
20        "-I" + libc_include_path,
21        "-I" + paths.join(libc_include_path, "include"),
22        "-DLIBC_NAMESPACE=" + LIBC_NAMESPACE,
23    ]
24
25def libc_release_copts():
26    copts = [
27        "-DLIBC_COPT_PUBLIC_PACKAGING",
28        # This is used to explicitly give public symbols "default" visibility.
29        # See src/__support/common.h for more information.
30        "-DLLVM_LIBC_FUNCTION_ATTR='[[gnu::visibility(\"default\")]]'",
31        # All other libc sources need to be compiled with "hidden" visibility.
32        "-fvisibility=hidden",
33        "-O3",
34        "-fno-builtin",
35        "-fno-lax-vector-conversions",
36        "-ftrivial-auto-var-init=pattern",
37        "-fno-omit-frame-pointer",
38        "-fstack-protector-strong",
39    ]
40
41    platform_copts = selects.with_or({
42        PLATFORM_CPU_X86_64: ["-mno-omit-leaf-frame-pointer"],
43        "//conditions:default": [],
44    })
45    return copts + platform_copts
46
47def _libc_library(name, copts = [], deps = [], local_defines = [], **kwargs):
48    """Internal macro to serve as a base for all other libc library rules.
49
50    Args:
51      name: Target name.
52      copts: The special compiler options for the target.
53      deps: The list of target dependencies if any.
54      local_defines: The list of target local_defines if any.
55      **kwargs: All other attributes relevant for the cc_library rule.
56    """
57
58    native.cc_library(
59        name = name,
60        copts = copts + libc_common_copts(),
61        local_defines = local_defines + LIBC_CONFIGURE_OPTIONS,
62        deps = deps,
63        linkstatic = 1,
64        **kwargs
65    )
66
67# A convenience function which should be used to list all libc support libraries.
68# Any library which does not define a public function should be listed with
69# libc_support_library.
70def libc_support_library(name, **kwargs):
71    _libc_library(name = name, **kwargs)
72
73def libc_function(
74        name,
75        srcs,
76        weak = False,
77        copts = [],
78        local_defines = [],
79        **kwargs):
80    """Add target for a libc function.
81
82    The libc function is eventually available as a cc_library target by name
83    "name". LLVM libc implementations of libc functions are in C++. So, this
84    rule internally generates a C wrapper for the C++ implementation and adds
85    it to the source list of the cc_library. This way, the C++ implementation
86    and the C wrapper are both available in the cc_library.
87
88    Args:
89      name: Target name. It is normally the name of the function this target is
90            for.
91      srcs: The .cpp files which contain the function implementation.
92      weak: Make the symbol corresponding to the libc function "weak".
93      copts: The list of options to add to the C++ compilation command.
94      local_defines: The preprocessor defines which will be prepended with -D
95                     and passed to the compile command of this target but not
96                     its deps.
97      **kwargs: Other attributes relevant for a cc_library. For example, deps.
98    """
99
100    # We compile the code twice, the first target is suffixed with ".__internal__" and contains the
101    # C++ functions in the "LIBC_NAMESPACE" namespace. This allows us to test the function in the
102    # presence of another libc.
103    libc_support_library(
104        name = libc_internal_target(name),
105        srcs = srcs,
106        copts = copts,
107        local_defines = local_defines,
108        **kwargs
109    )
110
111    # This second target is the llvm libc C function with default visibility.
112    func_attrs = [
113        "LLVM_LIBC_FUNCTION_ATTR_" + name + "='LLVM_LIBC_EMPTY, [[gnu::weak]]'",
114    ] if weak else []
115
116    _libc_library(
117        name = name,
118        srcs = srcs,
119        copts = copts + libc_release_copts(),
120        local_defines = local_defines + func_attrs,
121        **kwargs
122    )
123
124def libc_math_function(
125        name,
126        additional_deps = None):
127    """Add a target for a math function.
128
129    Args:
130      name: The name of the function.
131      additional_deps: Other deps like helper cc_library targes used by the
132                       math function.
133    """
134    additional_deps = additional_deps or []
135
136    #TODO(michaelrj): Fix the floating point dependencies
137    OLD_FPUTIL_DEPS = [
138        ":__support_fputil_basic_operations",
139        ":__support_fputil_division_and_remainder_operations",
140        ":__support_fputil_fenv_impl",
141        ":__support_fputil_fp_bits",
142        ":__support_fputil_hypot",
143        ":__support_fputil_manipulation_functions",
144        ":__support_fputil_nearest_integer_operations",
145        ":__support_fputil_normal_float",
146        ":__support_math_extras",
147        ":__support_fputil_except_value_utils",
148    ]
149    libc_function(
150        name = name,
151        srcs = ["src/math/generic/" + name + ".cpp"],
152        hdrs = ["src/math/" + name + ".h"],
153        deps = [":__support_common"] + OLD_FPUTIL_DEPS + additional_deps,
154    )
155