2021-10-20 20:20:42 +00:00
|
|
|
"""
|
2022-03-21 18:31:08 +00:00
|
|
|
This file specifies a clang toolchain that can run on a Linux host which doesn't depend on any
|
2021-10-20 20:20:42 +00:00
|
|
|
installed packages from the host machine.
|
|
|
|
|
|
|
|
See build_toolchain.bzl for more details on the creation of the toolchain.
|
|
|
|
|
|
|
|
It uses the usr subfolder of the built toolchain as a sysroot
|
|
|
|
|
|
|
|
It follows the example of:
|
|
|
|
- https://docs.bazel.build/versions/4.2.1/tutorial/cc-toolchain-config.html
|
|
|
|
- https://github.com/emscripten-core/emsdk/blob/7f39d100d8cd207094decea907121df72065517e/bazel/emscripten_toolchain/crosstool.bzl
|
|
|
|
"""
|
|
|
|
|
|
|
|
load(
|
|
|
|
"@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
|
|
|
|
"action_config",
|
|
|
|
"feature",
|
2022-03-16 12:33:44 +00:00
|
|
|
"feature_set",
|
2021-10-20 20:20:42 +00:00
|
|
|
"flag_group",
|
|
|
|
"flag_set",
|
|
|
|
"tool",
|
|
|
|
"variable_with_value",
|
|
|
|
)
|
|
|
|
load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
|
|
|
|
|
|
|
|
# The location of the created clang toolchain.
|
2022-01-11 12:35:26 +00:00
|
|
|
EXTERNAL_TOOLCHAIN = "external/clang_linux_amd64"
|
2021-10-20 20:20:42 +00:00
|
|
|
|
2022-04-01 12:29:11 +00:00
|
|
|
def _linux_amd64_toolchain_info(ctx):
|
2021-10-20 20:20:42 +00:00
|
|
|
action_configs = _make_action_configs()
|
|
|
|
features = []
|
|
|
|
features += _make_default_flags()
|
|
|
|
features += _make_diagnostic_flags()
|
2022-03-16 12:33:44 +00:00
|
|
|
features += _make_iwyu_flags()
|
2021-10-20 20:20:42 +00:00
|
|
|
|
|
|
|
# https://docs.bazel.build/versions/main/skylark/lib/cc_common.html#create_cc_toolchain_config_info
|
|
|
|
# Note, this rule is defined in Java code, not Starlark
|
|
|
|
# https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/starlarkbuildapi/cpp/CcModuleApi.java
|
|
|
|
return cc_common.create_cc_toolchain_config_info(
|
|
|
|
ctx = ctx,
|
|
|
|
features = features,
|
|
|
|
abi_libc_version = "unknown",
|
|
|
|
abi_version = "unknown",
|
|
|
|
action_configs = action_configs,
|
2022-01-11 12:35:26 +00:00
|
|
|
# This is important because the linker will complain if the libc shared libraries are not
|
|
|
|
# under this directory. Because we extract the libc libraries to
|
|
|
|
# EXTERNAL_TOOLCHAIN/lib, and the various headers and shared libraries to
|
|
|
|
# EXTERNAL_TOOLCHAIN/usr, we make the top level folder the sysroot so the linker can
|
|
|
|
# find the referenced libraries (e.g. EXTERNAL_TOOLCHAIN/usr/lib/x86_64-linux-gnu/libc.so
|
|
|
|
# is just a text file that refers to "/lib/x86_64-linux-gnu/libc.so.6" and
|
|
|
|
# "/lib64/ld-linux-x86-64.so.2" which will use the sysroot as the root).
|
|
|
|
builtin_sysroot = EXTERNAL_TOOLCHAIN,
|
2021-10-20 20:20:42 +00:00
|
|
|
compiler = "clang",
|
|
|
|
host_system_name = "local",
|
|
|
|
target_cpu = "k8",
|
2022-01-11 12:35:26 +00:00
|
|
|
# It is unclear if target_libc matters.
|
|
|
|
target_libc = "glibc-2.31",
|
2021-10-20 20:20:42 +00:00
|
|
|
target_system_name = "local",
|
|
|
|
toolchain_identifier = "clang-toolchain",
|
|
|
|
)
|
|
|
|
|
2022-04-01 12:29:11 +00:00
|
|
|
provide_linux_amd64_toolchain_config = rule(
|
2021-10-20 20:20:42 +00:00
|
|
|
attrs = {},
|
|
|
|
provides = [CcToolchainConfigInfo],
|
2022-04-01 12:29:11 +00:00
|
|
|
implementation = _linux_amd64_toolchain_info,
|
2021-10-20 20:20:42 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
def _make_action_configs():
|
|
|
|
"""
|
|
|
|
This function sets up the tools needed to perform the various compile/link actions.
|
|
|
|
|
|
|
|
Bazel normally restricts us to referring to (and therefore running) executables/scripts
|
|
|
|
that are in this directory (That is EXEC_ROOT/toolchain). However, the executables we want
|
|
|
|
to run are brought in via WORKSPACE.bazel and are located in EXEC_ROOT/external/clang....
|
|
|
|
Therefore, we make use of "trampoline scripts" that will call the binaries from the
|
|
|
|
toolchain directory.
|
|
|
|
|
|
|
|
These action_configs also let us dynamically specify arguments from the Bazel
|
|
|
|
environment if necessary (see cpp_link_static_library_action).
|
|
|
|
"""
|
|
|
|
|
|
|
|
# https://cs.opensource.google/bazel/bazel/+/master:tools/cpp/cc_toolchain_config_lib.bzl;l=435;drc=3b9e6f201a9a3465720aad8712ab7bcdeaf2e5da
|
|
|
|
clang_tool = tool(path = "clang_trampoline.sh")
|
|
|
|
lld_tool = tool(path = "lld_trampoline.sh")
|
|
|
|
ar_tool = tool(path = "ar_trampoline.sh")
|
|
|
|
|
|
|
|
# https://cs.opensource.google/bazel/bazel/+/master:tools/cpp/cc_toolchain_config_lib.bzl;l=488;drc=3b9e6f201a9a3465720aad8712ab7bcdeaf2e5da
|
|
|
|
assemble_action = action_config(
|
|
|
|
action_name = ACTION_NAMES.assemble,
|
|
|
|
tools = [clang_tool],
|
|
|
|
)
|
|
|
|
c_compile_action = action_config(
|
|
|
|
action_name = ACTION_NAMES.c_compile,
|
|
|
|
tools = [clang_tool],
|
|
|
|
)
|
|
|
|
cpp_compile_action = action_config(
|
|
|
|
action_name = ACTION_NAMES.cpp_compile,
|
|
|
|
tools = [clang_tool],
|
|
|
|
)
|
|
|
|
linkstamp_compile_action = action_config(
|
|
|
|
action_name = ACTION_NAMES.linkstamp_compile,
|
|
|
|
tools = [clang_tool],
|
|
|
|
)
|
|
|
|
preprocess_assemble_action = action_config(
|
|
|
|
action_name = ACTION_NAMES.preprocess_assemble,
|
|
|
|
tools = [clang_tool],
|
|
|
|
)
|
|
|
|
|
|
|
|
cpp_link_dynamic_library_action = action_config(
|
|
|
|
action_name = ACTION_NAMES.cpp_link_dynamic_library,
|
|
|
|
tools = [lld_tool],
|
|
|
|
)
|
|
|
|
cpp_link_executable_action = action_config(
|
|
|
|
action_name = ACTION_NAMES.cpp_link_executable,
|
|
|
|
# Bazel assumes it is talking to clang when building an executable. There are
|
|
|
|
# "-Wl" flags on the command: https://releases.llvm.org/6.0.1/tools/clang/docs/ClangCommandLineReference.html#cmdoption-clang-Wl
|
|
|
|
tools = [clang_tool],
|
|
|
|
)
|
|
|
|
cpp_link_nodeps_dynamic_library_action = action_config(
|
|
|
|
action_name = ACTION_NAMES.cpp_link_nodeps_dynamic_library,
|
|
|
|
tools = [lld_tool],
|
|
|
|
)
|
|
|
|
|
|
|
|
# This is the same rule as
|
|
|
|
# https://github.com/emscripten-core/emsdk/blob/7f39d100d8cd207094decea907121df72065517e/bazel/emscripten_toolchain/crosstool.bzl#L143
|
|
|
|
# By default, there are no flags or libraries passed to the llvm-ar tool, so
|
|
|
|
# we need to specify them. The variables mentioned by expand_if_available are defined
|
|
|
|
# https://docs.bazel.build/versions/main/cc-toolchain-config-reference.html#cctoolchainconfiginfo-build-variables
|
|
|
|
cpp_link_static_library_action = action_config(
|
|
|
|
action_name = ACTION_NAMES.cpp_link_static_library,
|
|
|
|
flag_sets = [
|
|
|
|
flag_set(
|
|
|
|
flag_groups = [
|
|
|
|
flag_group(
|
|
|
|
# https://llvm.org/docs/CommandGuide/llvm-ar.html
|
|
|
|
# replace existing files or insert them if they already exist,
|
|
|
|
# create the file if it doesn't already exist
|
|
|
|
# symbol table should be added
|
|
|
|
# Deterministic timestamps should be used
|
|
|
|
flags = ["rcsD", "%{output_execpath}"],
|
|
|
|
# Despite the name, output_execpath just refers to linker output,
|
|
|
|
# e.g. libFoo.a
|
|
|
|
expand_if_available = "output_execpath",
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
flag_set(
|
|
|
|
flag_groups = [
|
|
|
|
flag_group(
|
|
|
|
iterate_over = "libraries_to_link",
|
|
|
|
flag_groups = [
|
|
|
|
flag_group(
|
|
|
|
flags = ["%{libraries_to_link.name}"],
|
|
|
|
expand_if_equal = variable_with_value(
|
|
|
|
name = "libraries_to_link.type",
|
|
|
|
value = "object_file",
|
|
|
|
),
|
|
|
|
),
|
|
|
|
flag_group(
|
|
|
|
flags = ["%{libraries_to_link.object_files}"],
|
|
|
|
iterate_over = "libraries_to_link.object_files",
|
|
|
|
expand_if_equal = variable_with_value(
|
|
|
|
name = "libraries_to_link.type",
|
|
|
|
value = "object_file_group",
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
expand_if_available = "libraries_to_link",
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
flag_set(
|
|
|
|
flag_groups = [
|
|
|
|
flag_group(
|
|
|
|
flags = ["@%{linker_param_file}"],
|
|
|
|
expand_if_available = "linker_param_file",
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
tools = [ar_tool],
|
|
|
|
)
|
|
|
|
|
|
|
|
action_configs = [
|
|
|
|
assemble_action,
|
|
|
|
c_compile_action,
|
|
|
|
cpp_compile_action,
|
|
|
|
cpp_link_dynamic_library_action,
|
|
|
|
cpp_link_executable_action,
|
|
|
|
cpp_link_nodeps_dynamic_library_action,
|
|
|
|
cpp_link_static_library_action,
|
|
|
|
linkstamp_compile_action,
|
|
|
|
preprocess_assemble_action,
|
|
|
|
]
|
|
|
|
return action_configs
|
|
|
|
|
|
|
|
def _make_default_flags():
|
|
|
|
"""Here we define the flags for certain actions that are always applied."""
|
|
|
|
cxx_compile_includes = flag_set(
|
|
|
|
actions = [
|
|
|
|
ACTION_NAMES.c_compile,
|
|
|
|
ACTION_NAMES.cpp_compile,
|
|
|
|
],
|
|
|
|
flag_groups = [
|
|
|
|
flag_group(
|
|
|
|
flags = [
|
|
|
|
# THIS ORDER MATTERS GREATLY. If these are in the wrong order, the
|
2022-01-11 12:35:26 +00:00
|
|
|
# #include_next directives will fail to find the files, causing a compilation
|
|
|
|
# error (or, without -no-canonical-prefixes, a mysterious case where files
|
|
|
|
# are included with an absolute path and fail the build).
|
2021-10-20 20:20:42 +00:00
|
|
|
"-isystem",
|
|
|
|
EXTERNAL_TOOLCHAIN + "/include/c++/v1",
|
|
|
|
"-isystem",
|
2022-01-11 12:35:26 +00:00
|
|
|
EXTERNAL_TOOLCHAIN + "/usr/include",
|
|
|
|
"-isystem",
|
2021-10-20 20:20:42 +00:00
|
|
|
EXTERNAL_TOOLCHAIN + "/lib/clang/13.0.0/include",
|
|
|
|
"-isystem",
|
2022-01-11 12:35:26 +00:00
|
|
|
EXTERNAL_TOOLCHAIN + "/usr/include/x86_64-linux-gnu",
|
|
|
|
# We do not want clang to search in absolute paths for files. This makes
|
|
|
|
# Bazel think we are using an outside resource and fail the compile.
|
|
|
|
"-no-canonical-prefixes",
|
2021-10-20 20:20:42 +00:00
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
|
|
|
cpp_compile_includes = flag_set(
|
|
|
|
actions = [
|
|
|
|
ACTION_NAMES.cpp_compile,
|
|
|
|
],
|
|
|
|
flag_groups = [
|
|
|
|
flag_group(
|
|
|
|
flags = [
|
2022-01-31 21:12:44 +00:00
|
|
|
"-std=c++17",
|
[infra] Add initial Bazel rules and files
These rules can be used to build our GMs on WASM+WebGL and
libskia.a with just the CPU backend (and most other features
turned off).
This can be done with the following commands:
- bazel build //modules/canvaskit:gm-bindings-wasm --gpu_backend=gl_backend --with_gl_standard=webgl_standard
- bazel build :skia-core --config clang
This pivots slightly from http://review.skia.org/463517
by using config_settings [1] instead of platforms for
the optional features that we control. This pivot was
suggested in [2]
We have BUILD.bazel files in many of the subdirectories
that specify filegroups for the appropriate files. In
an effort to make //BUILD.bazel more readable, it is
the responsibility of these subfolders to deal with
conditionally including certain .h or .cpp files.
This is done using select statements and config_settings
or platform constraints as necessary.
For example, src/gpu/BUILD.bazel will different private
filegroups for each of the supported gpu backends [3]
and a more-visible filegroup called "srcs" that has
the right selection of the private files to be used
for compilation.
An effort has been made to avoid using glob() in our
BUILD.bazel files. These file lists were made by using
`ls -1` and some regex to add in quotes. We might want
to make a helper script to assist with that, if necessary.
To specify which options we have, the settings in
//bazel/common_config_settings/BUILD.bazel have been
redesigned. They make use of a macro `string_flag_with_values`
that removes the boilerplate. Patchset 36 shows what the
file looks like w/o the macro.
The top level BUILD.bazel file will still need to use
some logic to handle defines, because local_defines is
a list of strings, not a list of labels [4].
Suggested Review Order:
- WORKSPACE.bazel to see the new dependencies on the
emsdk toolchain and bazel_skylib
- bazel/common_config_settings/* to see the few settings
defined (we have more to define, see BUILD.gn and
//gn/skia.gni for ideas)
- BUILD.bazel to see the "skia-core" cc_library rule.
See also "gms" and "tests"
- modules/canvaskit/BUILD.bazel to see the use of
the emscripten "wasm_cc_binary" rule, which depends
on the "skia-core", "gms", and "tests" rule. Note that
it only builds some of the gms as a proof of concept.
- The other BUILD.bazel files. Some of these are not
platform or feature dependent (e.g. pathops). Others
are (e.g. gpu).
- All other files.
[1] https://docs.bazel.build/versions/4.2.1/skylark/config.html#user-defined-build-settings
[2] https://github.com/emscripten-core/emsdk/pull/920
[3] In this CL, that's just the webgl one.
[4] https://docs.bazel.build/versions/main/be/c-cpp.html#cc_library.local_defines
Change-Id: Ieecf9c106d5e3a6ae97d13d66be06b4b3c207089
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/458637
Reviewed-by: Ben Wagner <bungeman@google.com>
Reviewed-by: Leandro Lovisolo <lovisolo@google.com>
Owners-Override: Kevin Lubick <kjlubick@google.com>
2021-11-08 20:26:09 +00:00
|
|
|
"-Wno-psabi", # noisy
|
2021-10-20 20:20:42 +00:00
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
|
|
|
link_exe_flags = flag_set(
|
|
|
|
actions = [ACTION_NAMES.cpp_link_executable],
|
|
|
|
flag_groups = [
|
|
|
|
flag_group(
|
|
|
|
flags = [
|
|
|
|
"-fuse-ld=lld",
|
|
|
|
# We chose to use the llvm runtime, not the gcc one because it is already
|
|
|
|
# included in the clang binary
|
|
|
|
"--rtlib=compiler-rt",
|
2022-01-31 21:12:44 +00:00
|
|
|
"-std=c++17",
|
2022-01-11 12:35:26 +00:00
|
|
|
# We statically include these libc++ libraries so they do not need to be
|
|
|
|
# on a developer's machine (they can be tricky to get).
|
|
|
|
EXTERNAL_TOOLCHAIN + "/lib/libc++.a",
|
|
|
|
EXTERNAL_TOOLCHAIN + "/lib/libc++abi.a",
|
|
|
|
EXTERNAL_TOOLCHAIN + "/lib/libunwind.a",
|
|
|
|
# Dynamically Link in the other parts of glibc (not needed in glibc 2.34+)
|
|
|
|
"-lpthread",
|
|
|
|
"-lm",
|
|
|
|
"-ldl",
|
2021-10-20 20:20:42 +00:00
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
return [feature(
|
|
|
|
"default_flags",
|
|
|
|
enabled = True,
|
|
|
|
flag_sets = [
|
|
|
|
cxx_compile_includes,
|
|
|
|
cpp_compile_includes,
|
|
|
|
link_exe_flags,
|
|
|
|
],
|
|
|
|
)]
|
|
|
|
|
|
|
|
def _make_diagnostic_flags():
|
|
|
|
"""Here we define the flags that can be turned on via features to yield debug info."""
|
|
|
|
cxx_diagnostic = flag_set(
|
|
|
|
actions = [
|
|
|
|
ACTION_NAMES.c_compile,
|
|
|
|
ACTION_NAMES.cpp_compile,
|
|
|
|
],
|
|
|
|
flag_groups = [
|
|
|
|
flag_group(
|
|
|
|
flags = [
|
|
|
|
"--trace-includes",
|
|
|
|
"-v",
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
|
|
|
link_diagnostic = flag_set(
|
|
|
|
actions = [ACTION_NAMES.cpp_link_executable],
|
|
|
|
flag_groups = [
|
|
|
|
flag_group(
|
|
|
|
flags = [
|
|
|
|
"-Wl,--verbose",
|
|
|
|
"-v",
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
|
|
|
link_search_dirs = flag_set(
|
|
|
|
actions = [ACTION_NAMES.cpp_link_executable],
|
|
|
|
flag_groups = [
|
|
|
|
flag_group(
|
|
|
|
flags = [
|
|
|
|
"--print-search-dirs",
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
return [
|
|
|
|
# Running a Bazel command with --features diagnostic will cause the compilation and
|
|
|
|
# link steps to be more verbose.
|
|
|
|
feature(
|
|
|
|
"diagnostic",
|
|
|
|
enabled = False,
|
|
|
|
flag_sets = [
|
|
|
|
cxx_diagnostic,
|
|
|
|
link_diagnostic,
|
|
|
|
],
|
|
|
|
),
|
|
|
|
# Running a Bazel command with --features print_search_dirs will cause the link to fail
|
|
|
|
# but directories searched for libraries, etc will be displayed.
|
|
|
|
feature(
|
|
|
|
"print_search_dirs",
|
|
|
|
enabled = False,
|
|
|
|
flag_sets = [
|
|
|
|
link_search_dirs,
|
|
|
|
],
|
|
|
|
),
|
|
|
|
]
|
2022-03-16 12:33:44 +00:00
|
|
|
|
|
|
|
def _make_iwyu_flags():
|
|
|
|
"""Here we define the flags that signal whether or not to enforce IWYU."""
|
|
|
|
|
|
|
|
# https://bazel.build/docs/cc-toolchain-config-reference#features
|
|
|
|
opt_file_into_iwyu = flag_set(
|
|
|
|
actions = [
|
|
|
|
ACTION_NAMES.c_compile,
|
|
|
|
ACTION_NAMES.cpp_compile,
|
|
|
|
],
|
|
|
|
flag_groups = [
|
|
|
|
flag_group(
|
|
|
|
flags = [
|
|
|
|
# This define does not impact compilation, but it acts as a signal to the
|
|
|
|
# clang_trampoline.sh whether check the file with include-what-you-use
|
|
|
|
# A define was chosen because it is ignored by clang and IWYU, but can be
|
|
|
|
# easily found with bash.
|
|
|
|
"-DSKIA_ENFORCE_IWYU_FOR_THIS_FILE",
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
|
|
|
return [
|
|
|
|
feature(
|
|
|
|
# The IWYU checks can add some overhead to the build (1-5 seconds per file), so we only
|
|
|
|
# want to run them sometimes. By adding --feature skia_enforce_iwyu to the Bazel
|
|
|
|
# command, this will turn on the checking (for all files that have not been opted-out).
|
|
|
|
"skia_enforce_iwyu",
|
|
|
|
enabled = False,
|
|
|
|
),
|
|
|
|
feature(
|
|
|
|
"skia_opt_file_into_iwyu",
|
|
|
|
enabled = False,
|
|
|
|
flag_sets = [
|
|
|
|
opt_file_into_iwyu,
|
|
|
|
],
|
|
|
|
# If the skia_enforce_iwyu features is not enabled (e.g. globally via a CLI flag), we
|
|
|
|
# will not run the IWYU analysis on any files.
|
|
|
|
requires = [
|
|
|
|
feature_set(features = [
|
|
|
|
"skia_enforce_iwyu",
|
|
|
|
]),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
]
|