7a14f783bd
bazel run //example:hello_world --config=clang causes a window to open and draws a circle and a square. Text to follow in a future CL. To make this work, I had to get rid of musl and use glibc. All the shared libraries (.so files) that were pre-built and available for download (e.g. from https://packages.debian.org/bullseye/amd64/libgl1/download) were compiled against glibc. When I tried to run a program statically linked with musl and dynamically linked against things using glibc, I got a segmentation fault on things like calloc(). Initial attempts to use glibc had failed because it was thought that the libc.so.6 file could only be referred to by absolute path (and thus Bazel would not be happy about it). As it turns out, that was simply a misconfiguration of the builtin_sysroot parameter to cc_common.create_cc_toolchain_config_info (see //toolchain/clang_toolchain_config.bzl). By setting that to `external/clang_linux_amd64` and not `external/clang_linux_amd64/usr`, the libc binary which had been extracted to `external/clang_linux_amd64/lib/x86_64-linux-gnu` was perfectly reachable from `external/clang_linux_amd64/usr/usr/lib/x86_64-linux-gnu/libc.so` To bring in the shared libraries to link against (e.g. X11, GL) I made build_toolchain.bzl easier to modify in that we simply need to add a debian download url and sha256 hash to a list (rather than having to plumb this through via arguments). Recommended Review Order: - example/BUILD.bazel (not sure if we always want to set bare link arguments like that or if we want to use "features" to pass those along to the toolchain). - tools/sk_app/BUILD.bazel to see initial cc_library for wrapping sk_app code. - toolchain/build_toolchain.bzl to see removal of musl and new list of debs. - toolchain/clang_toolchain_config.bzl (where use of the no-canonical-prefixes was key to compilation success). Notice also that we statically linked libc++ (I did not have any shared libraries for it locally, so I guessed a typical developer might not either). - Rest of toolchain/ for trivial renames. - bazel/Makefile to see extra docs on those targets and a new target that compiles all the exes so far for a quick way to test the build. - third_party/BUILD.bazel and src/gpu/BUILD.bazel which have non-generated changes. (all other BUILD.bazel files do). - go.mod, which needed to update the infra repo version in order to pick up http://review.skia.org/491736). Change-Id: I8687bd227353040eca2dffa9465798d8bd395027 Bug: skia:12541 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/492117 Reviewed-by: Ben Wagner <bungeman@google.com> Reviewed-by: Leandro Lovisolo <lovisolo@google.com> Commit-Queue: Kevin Lubick <kjlubick@google.com>
334 lines
13 KiB
Python
334 lines
13 KiB
Python
"""
|
|
This file specifies a clang toolchain that can run on a Linux host which does depend on any
|
|
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",
|
|
"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.
|
|
EXTERNAL_TOOLCHAIN = "external/clang_linux_amd64"
|
|
|
|
def _clang_impl(ctx):
|
|
action_configs = _make_action_configs()
|
|
features = []
|
|
features += _make_default_flags()
|
|
features += _make_diagnostic_flags()
|
|
|
|
# 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,
|
|
# 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,
|
|
compiler = "clang",
|
|
host_system_name = "local",
|
|
target_cpu = "k8",
|
|
# It is unclear if target_libc matters.
|
|
target_libc = "glibc-2.31",
|
|
target_system_name = "local",
|
|
toolchain_identifier = "clang-toolchain",
|
|
)
|
|
|
|
provide_clang_toolchain_config = rule(
|
|
attrs = {},
|
|
provides = [CcToolchainConfigInfo],
|
|
implementation = _clang_impl,
|
|
)
|
|
|
|
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
|
|
# #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).
|
|
"-isystem",
|
|
EXTERNAL_TOOLCHAIN + "/include/c++/v1",
|
|
"-isystem",
|
|
EXTERNAL_TOOLCHAIN + "/usr/include",
|
|
"-isystem",
|
|
EXTERNAL_TOOLCHAIN + "/lib/clang/13.0.0/include",
|
|
"-isystem",
|
|
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",
|
|
],
|
|
),
|
|
],
|
|
)
|
|
|
|
cpp_compile_includes = flag_set(
|
|
actions = [
|
|
ACTION_NAMES.cpp_compile,
|
|
],
|
|
flag_groups = [
|
|
flag_group(
|
|
flags = [
|
|
# http://g/skia-staff/bhPPBV4YdeU/5oyG5GRgBQAJ
|
|
"-std=c++14",
|
|
"-Wno-c++17-extensions",
|
|
"-Wno-psabi", # noisy
|
|
],
|
|
),
|
|
],
|
|
)
|
|
|
|
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",
|
|
"-std=c++14",
|
|
# 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",
|
|
],
|
|
),
|
|
],
|
|
)
|
|
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,
|
|
],
|
|
),
|
|
]
|