311 lines · plain
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-exception4 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("@rules_cc//cc:defs.bzl", "cc_library")10load(":libc_configure_options.bzl", "LIBC_CONFIGURE_OPTIONS")11load(":libc_namespace.bzl", "LIBC_NAMESPACE")12load(":platforms.bzl", "PLATFORM_CPU_X86_64")13 14def libc_common_copts():15 root_label = Label(":libc")16 libc_include_path = paths.join(root_label.workspace_root, root_label.package)17 return [18 "-I" + libc_include_path,19 "-I" + paths.join(libc_include_path, "include"),20 "-DLIBC_NAMESPACE=" + LIBC_NAMESPACE,21 ]22 23def libc_release_copts():24 copts = [25 "-DLIBC_COPT_PUBLIC_PACKAGING",26 # This is used to explicitly give public symbols "default" visibility.27 # See src/__support/common.h for more information.28 "-DLLVM_LIBC_FUNCTION_ATTR='[[gnu::visibility(\"default\")]]'",29 # All other libc sources need to be compiled with "hidden" visibility.30 "-fvisibility=hidden",31 "-O3",32 "-fno-builtin",33 "-fno-lax-vector-conversions",34 "-ftrivial-auto-var-init=pattern",35 "-fno-omit-frame-pointer",36 "-fstack-protector-strong",37 ]38 39 platform_copts = selects.with_or({40 PLATFORM_CPU_X86_64: ["-mno-omit-leaf-frame-pointer"],41 "//conditions:default": [],42 })43 return copts + platform_copts44 45def _libc_library(name, **kwargs):46 """Internal macro to serve as a base for all other libc library rules.47 48 Args:49 name: Target name.50 **kwargs: All other attributes relevant for the cc_library rule.51 """52 53 for attr in ["copts", "local_defines"]:54 if attr in kwargs:55 fail("disallowed attribute: '{}' in rule: '{}'".format(attr, name))56 cc_library(57 name = name,58 copts = libc_common_copts(),59 local_defines = LIBC_CONFIGURE_OPTIONS,60 linkstatic = 1,61 **kwargs62 )63 64# A convenience function which should be used to list all libc support libraries.65# Any library which does not define a public function should be listed with66# libc_support_library.67def libc_support_library(name, **kwargs):68 _libc_library(name = name, **kwargs)69 70def libc_function(name, **kwargs):71 """Add target for a libc function.72 73 This macro creates an internal cc_library that can be used to test this74 function.75 76 Args:77 name: Target name. Typically the name of the function this target is for.78 **kwargs: Other attributes relevant for a cc_library. For example, deps.79 """80 81 # Builds "internal" library with a function, exposed as a C++ function in82 # the "LIBC_NAMESPACE" namespace. This allows us to test the function in the83 # presence of another libc.84 _libc_library(name = name, **kwargs)85 86LibcLibraryInfo = provider(87 "All source files and textual headers for building a particular library.",88 fields = ["srcs", "textual_hdrs"],89)90 91def _get_libc_info_aspect_impl(92 target, # @unused93 ctx):94 maybe_srcs = getattr(ctx.rule.attr, "srcs", [])95 maybe_hdrs = getattr(ctx.rule.attr, "hdrs", [])96 maybe_textual_hdrs = getattr(ctx.rule.attr, "textual_hdrs", [])97 maybe_deps = getattr(ctx.rule.attr, "deps", [])98 return LibcLibraryInfo(99 srcs = depset(100 transitive = [101 dep[LibcLibraryInfo].srcs102 for dep in maybe_deps103 if LibcLibraryInfo in dep104 ] + [105 src.files106 for src in maybe_srcs + maybe_hdrs107 ],108 ),109 textual_hdrs = depset(110 transitive = [111 dep[LibcLibraryInfo].textual_hdrs112 for dep in maybe_deps113 if LibcLibraryInfo in dep114 ] + [115 hdr.files116 for hdr in maybe_textual_hdrs117 ],118 ),119 )120 121_get_libc_info_aspect = aspect(122 implementation = _get_libc_info_aspect_impl,123 attr_aspects = ["deps"],124)125 126def _libc_srcs_filegroup_impl(ctx):127 srcs = depset(transitive = [128 fn[LibcLibraryInfo].srcs129 for fn in ctx.attr.libs130 ])131 if ctx.attr.enforce_headers_only:132 paths = [f.short_path for f in srcs.to_list() if f.extension != "h"]133 if paths:134 fail("Unexpected non-header files: {}".format(paths))135 return DefaultInfo(files = srcs)136 137_libc_srcs_filegroup = rule(138 doc = "Returns all sources for building the specified libraries.",139 implementation = _libc_srcs_filegroup_impl,140 attrs = {141 "libs": attr.label_list(142 mandatory = True,143 aspects = [_get_libc_info_aspect],144 ),145 "enforce_headers_only": attr.bool(default = False),146 },147)148 149def _libc_textual_hdrs_filegroup_impl(ctx):150 return DefaultInfo(151 files = depset(transitive = [152 fn[LibcLibraryInfo].textual_hdrs153 for fn in ctx.attr.libs154 ]),155 )156 157_libc_textual_hdrs_filegroup = rule(158 doc = "Returns all textual headers for compiling the specified libraries.",159 implementation = _libc_textual_hdrs_filegroup_impl,160 attrs = {161 "libs": attr.label_list(162 mandatory = True,163 aspects = [_get_libc_info_aspect],164 ),165 },166)167 168def libc_release_library(169 name,170 libc_functions,171 weak_symbols = [],172 **kwargs):173 """Create the release version of a libc library.174 175 Args:176 name: Name of the cc_library target.177 libc_functions: List of functions to include in the library. They should be178 created by libc_function macro.179 weak_symbols: List of function names that should be marked as weak symbols.180 **kwargs: Other arguments relevant to cc_library.181 """182 183 _libc_srcs_filegroup(184 name = name + "_srcs",185 libs = libc_functions,186 )187 188 _libc_textual_hdrs_filegroup(189 name = name + "_textual_hdrs",190 libs = libc_functions,191 )192 cc_library(193 name = name + "_textual_hdr_library",194 textual_hdrs = [":" + name + "_textual_hdrs"],195 )196 197 weak_attributes = [198 "LLVM_LIBC_FUNCTION_ATTR_" + name + "='LLVM_LIBC_EMPTY, [[gnu::weak]]'"199 for name in weak_symbols200 ]201 cc_library(202 name = name,203 srcs = [":" + name + "_srcs"],204 copts = libc_common_copts() + libc_release_copts(),205 local_defines = weak_attributes + LIBC_CONFIGURE_OPTIONS,206 deps = [207 ":" + name + "_textual_hdr_library",208 ],209 **kwargs210 )211 212def libc_header_library(name, hdrs, deps = [], **kwargs):213 """Creates a header-only library to share libc functionality.214 215 Args:216 name: Name of the cc_library target.217 hdrs: List of headers to be shared.218 deps: The list of libc_support_library dependencies if any.219 **kwargs: All other attributes relevant for the cc_library rule.220 """221 222 _libc_srcs_filegroup(223 name = name + "_hdr_deps",224 libs = deps,225 enforce_headers_only = True,226 )227 228 _libc_textual_hdrs_filegroup(229 name = name + "_textual_hdrs",230 libs = deps,231 )232 cc_library(233 name = name + "_textual_hdr_library",234 textual_hdrs = [":" + name + "_textual_hdrs"],235 )236 cc_library(237 name = name,238 hdrs = hdrs,239 # We put _hdr_deps in srcs, as they are not a part of this cc_library240 # interface, but instead are used to implement shared headers.241 srcs = [":" + name + "_hdr_deps"],242 deps = [":" + name + "_textual_hdr_library"],243 # copts don't really matter, since it's a header-only library, but we244 # need proper -I flags for header validation, which are specified in245 # libc_common_copts().246 copts = libc_common_copts(),247 **kwargs248 )249 250def libc_generated_header(name, hdr, yaml_template, other_srcs = []):251 """Generates a libc header file from YAML template.252 253 Args:254 name: Name of the genrule target.255 hdr: Path of the header file to generate.256 yaml_template: Path of the YAML template file.257 other_srcs: Other files required to generate the header, if any.258 """259 hdrgen = "//libc:hdrgen"260 cmd = "$(location {hdrgen}) $(location {yaml}) -o $@".format(261 hdrgen = hdrgen,262 yaml = yaml_template,263 )264 265 if not hdr.startswith("staging/"):266 fail(267 "Generated headers should be placed in a 'staging/' directory " +268 "so that they can be treated differently from constant source files " +269 "when bootstrapping builds.",270 )271 272 native.genrule(273 name = name,274 outs = [hdr],275 srcs = [yaml_template] + other_srcs,276 cmd = cmd,277 tools = [hdrgen],278 )279 280def libc_math_function(281 name,282 additional_deps = None):283 """Add a target for a math function.284 285 Args:286 name: The name of the function.287 additional_deps: Other deps like helper cc_library targets used by the288 math function.289 """290 additional_deps = additional_deps or []291 292 #TODO(michaelrj): Fix the floating point dependencies293 OLD_FPUTIL_DEPS = [294 ":__support_fputil_basic_operations",295 ":__support_fputil_division_and_remainder_operations",296 ":__support_fputil_fenv_impl",297 ":__support_fputil_fp_bits",298 ":__support_fputil_hypot",299 ":__support_fputil_manipulation_functions",300 ":__support_fputil_nearest_integer_operations",301 ":__support_fputil_normal_float",302 ":__support_math_extras",303 ":__support_fputil_except_value_utils",304 ]305 libc_function(306 name = name,307 srcs = ["src/math/generic/" + name + ".cpp"],308 hdrs = ["src/math/" + name + ".h"],309 deps = [":__support_common"] + OLD_FPUTIL_DEPS + additional_deps,310 )311