Skip to content
This repository has been archived by the owner on Aug 4, 2021. It is now read-only.

Commit

Permalink
Add the cxx_* targets for libc++
Browse files Browse the repository at this point in the history
The following targets will be added to deal with the libc++ standard
library:

 - libcxx_static
 - libcxx_shared
 - libcxx_copy_shared
 - libcxx_abi_static
 - libcxx_abi_shared
 - libcxx_copy_abi_shared

The 'libcxx' prefix can be configured in the 'WORKSPACE' file using the
'libcxx_prefix' optional parameter of the 'llvm_configure' repository
rule.

To protect adding of the targets as dependencies, a number of macroses
are put into the 'llvm_config.bzl' generated file: the `if_cxx_linked`
function that evaluated its first argument when the local LLVM
installation is linked against libc++ and 'llvm_cxx_copts' array that
contains the `-stdlib=libc++` compiler option in this case.

Signed-off-by: Pavel Samolysov <samolisov@gmail.com>
  • Loading branch information
samolisov committed Oct 21, 2019
1 parent ba21e0a commit 1e1c34c
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 39 deletions.
62 changes: 55 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,17 @@ llvm_configure(
name = "local_llvm",
llvm_prefix = "llvm_",
clang_prefix = "clang_",
libcxx_prefix = "libcxx_",
add_headers_to_deps = False,
)
```

Where `name` is whatever you want, default values for `llvm_prefix` and `clang_prefix`
may be omitted. By default, the header libraries will be automatically included as dependency
to the generated targets (the LLVM header library to LLVM's, Clang's and other project's
targets, the Clang header library to Clang's targets, etc.) If you would like to manually
put the header libraries to dependencies, set up the `add_headers_to_deps` attribute of the
reporitory rule to `False`.
Where `name` is whatever you want, default values for `llvm_prefix`, `clang_prefix` and
`libcxx_prefix` may be omitted. By default, the header libraries will be automatically
included as dependency to the generated targets (the LLVM header library to LLVM's, Clang's
and other project's targets, the Clang header library to Clang's targets, etc.) If you would
like to manually put the header libraries to dependencies, set up the `add_headers_to_deps`
attribute of the reporitory rule to `False`.

There are three ways to use the library: the first, primarily, is shown
above: the LLVM libraries are fetched from a local installation so the `LLVM_INSTALL_PREFIX`
Expand All @@ -77,6 +78,7 @@ llvm_configure(
name = "local_llvm",
llvm_prefix = "llvm_",
clang_prefix = "clang_",
libcxx_prefix = "libcxx_",
sha256 = "ec5d7fd082137ce5b72c7b4dde9a83c07a7e298773351ab6a0693a8200d0fa0c",
strip_prefix = "clang+llvm-8.0.1-x86_64-linux-sles11.3",
urls = [
Expand All @@ -98,6 +100,7 @@ llvm_configure(
name = "local_llvm",
llvm_prefix = "llvm_",
clang_prefix = "clang_",
libcxx_prefix = "libcxx_",
build_file = "//:llvm.autogenerated.BUILD",
config_file = "//:llvm_config.bzl",
sha256 = "345dcab760b0e13f1df1b57efa0651dbaae300187bc1556379b562b85bec9e11",
Expand Down Expand Up @@ -145,7 +148,10 @@ cc_binary(
deps = [
"@local_llvm//:llvm_headers",
"@local_llvm//:llvm_bit_reader",
],
] + if_cxx_linked([
"@local_llvm//:libcxx_shared",
"@local_llvm//:libcxx_abi_shared",
]),
visibility = ["//visibility:private"],
)
```
Expand Down Expand Up @@ -251,3 +257,45 @@ a rule and it will appear in
a `bazel-bin/external/<name of llvm_configure repository rule>`
directory. Then the library can be copied into the `bazel-bin` (see the
genrule in the BUILD file) and be used for running your applications.

### Linking against the libc++ standard library

Archives hosted on the http://releases.llvm.org/download.html official website,
usually are built against the 'libc++' standard library. A number of Starlark
macroses and pre-defined arrays are developed to deal with the 'libc++' standard
library and can be loaded from the generated `llvm_config.bzl` file. The `if_cxx_linked`
function is used to safely add the `libcxx_static/libcxx_shared` and
`libcxx_abi_static/libcxx_abi_shared` targets as dependencies. The first argument
of the function will be taken into account when the local LLVM installation
is linked against 'libc++', otherwise the second one (optional) will be used.

The `-stdlib=libc++` compiler option can be added as the `llvm_cxx_copts` array.
If 'libc++' is not used, the array will just be empty, so that the array
should not be wrapped in the `if_cxx_linked` function.

There is an example how to use the `libcxx_*` targets and options:

```bzl
llvm_copts = select({
":linux_x86_64": llvm_nix_copts + llvm_cxx_copts,
":macos_x86_64": llvm_nix_copts + llvm_cxx_copts,
":windows_x86_64": llvm_win_copts,
"//conditions:default": [],
})
cc_binary(
name = 'llvm_bb_counter',
srcs = [
"llvm/llvm_bb_counter.cc",
],
copts = llvm_copts,
deps = [
"@local_llvm//:llvm_headers",
"@local_llvm//:llvm_bit_reader",
] + if_cxx_linked([
"@local_llvm//:libcxx_static", # if you prefer shared libraries,
"@local_llvm//:libcxx_abi_static", # use libcxx_shared and libcxx_abi_shared
]),
visibility = ["//visibility:private"],
)
```
57 changes: 29 additions & 28 deletions examples/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ config_setting(
load("@local_llvm//:llvm_config.bzl",
"llvm_nix_copts",
"llvm_win_copts",
"llvm_cxx_copts",
"if_cxx_linked",
"if_has_aarch64",
"if_has_amdgpu",
"if_has_arm",
Expand All @@ -48,21 +50,26 @@ load("@local_llvm//:llvm_config.bzl",
"if_has_x86",
"if_has_x_core")

llvm_copts = select({
":linux_x86_64": llvm_nix_copts + llvm_cxx_copts,
":macos_x86_64": llvm_nix_copts + llvm_cxx_copts,
":windows_x86_64": llvm_win_copts,
"//conditions:default": [],
})

cc_binary(
name = 'llvm_bb_counter',
srcs = [
"llvm/llvm_bb_counter.cc",
],
copts = select({
":linux_x86_64": llvm_nix_copts,
":macos_x86_64": llvm_nix_copts,
":windows_x86_64": llvm_win_copts,
"//conditions:default": [],
}),
copts = llvm_copts,
deps = [
"@local_llvm//:headers",
"@local_llvm//:bit_reader",
],
] + if_cxx_linked([
"@local_llvm//:cxx_static",
"@local_llvm//:cxx_abi_static",
]),
visibility = ["//visibility:private"],
)

Expand All @@ -71,12 +78,7 @@ cc_library(
srcs = [
"llvm/function_argument_usage_pass.cc",
],
copts = select({
":linux_x86_64": llvm_nix_copts,
":macos_x86_64": llvm_nix_copts,
":windows_x86_64": llvm_win_copts,
"//conditions:default": [],
}),
copts = llvm_copts,
deps = [
"@local_llvm//:headers",
"@local_llvm//:core",
Expand All @@ -93,7 +95,10 @@ cc_binary(
],
deps = [
":llvm_exp_passes",
],
] + if_cxx_linked([
"@local_llvm//:cxx_shared",
"@local_llvm//:cxx_abi_shared",
]),
visibility = ["//visibility:private"],
)

Expand All @@ -102,12 +107,7 @@ cc_binary(
srcs = [
"llvm/llvm_print_supported_targets.cc",
],
copts = select({
":linux_x86_64": llvm_nix_copts,
":macos_x86_64": llvm_nix_copts,
":windows_x86_64": llvm_win_copts,
"//conditions:default": [],
}),
copts = llvm_copts,
defines = if_has_aarch64(["LLVM_SUPPORTS_TARGET_AARCH64"])
+ if_has_amdgpu(["LLVM_SUPPORTS_TARGET_AMDGPU"])
+ if_has_arm(["LLVM_SUPPORTS_TARGET_ARM"])
Expand Down Expand Up @@ -194,20 +194,18 @@ cc_binary(
"@local_llvm//:x_core_asm_printer",
"@local_llvm//:x_core_code_gen",
"@local_llvm//:x_core_disassembler",
])
]) + if_cxx_linked([
"@local_llvm//:cxx_shared",
"@local_llvm//:cxx_abi_shared",
]),
)

cc_binary(
name = 'clang_list_methods',
srcs = [
"clang/clang_list_methods.cc",
],
copts = select({
":linux_x86_64": llvm_nix_copts,
":macos_x86_64": llvm_nix_copts,
":windows_x86_64": llvm_win_copts,
"//conditions:default": [],
}),
copts = llvm_copts,
data = select({
":linux_x86_64": [
"copy_local_llvm_shared_lin",
Expand All @@ -226,7 +224,10 @@ cc_binary(
"@local_llvm//:config_headers",
"@local_llvm//:headers",
"@local_llvm//:support",
],
] + if_cxx_linked([
"@local_llvm//:cxx_shared",
"@local_llvm//:cxx_abi_shared",
]),
linkopts = select({
":linux_x86_64": [
"-Wl,-R -Wl,."
Expand Down
1 change: 1 addition & 0 deletions examples/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ llvm_configure(
name = "local_llvm",
llvm_prefix = "", # default value: llvm_
clang_prefix = "cl_", # default value: clang_
libcxx_prefix = "cxx_", # default value: libcxx_
add_headers_to_deps = False, # default value: True

# Either the LLVM_INSTALL_PREFIX environment variable must point to
Expand Down
7 changes: 7 additions & 0 deletions llvm/BUILD.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,10 @@ exports_files(["LICENSE.TXT"])
%{LLVM_CONFIG_GENRULE}
%{LLVM_CONFIG_LIB}
%{DEP_LIBS}

%{LIBCXX_STATIC_LIB}
%{LIBCXX_SHARED_LIB}
%{LIBCXX_SHARED_COPY_GENRULE}
%{LIBCXX_ABI_STATIC_LIB}
%{LIBCXX_ABI_SHARED_LIB}
%{LIBCXX_ABI_SHARED_COPY_GENRULE}
19 changes: 19 additions & 0 deletions llvm/llvm_config.bzl.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ llvm_win_copts is a convenient set of platform-dependent compiler options
to enable the building process of LLVM-dependent targets for Windows platform.
It can disable RTTI and enable the right level of C++.
llvm_cxx_copts is a convenient set of "libc++" specific compiler options.
May be used to enable "libc++" as a standard library for the build.
llvm_cxx_linked is a flag that displays if LLVM is linked against the "libc++"
standard library.
if_cxx_linked is a conditional to check if the LLVM installation
is built against the "libc++" standard library. If so, the first argument
will be returned, otherwise the second one.
llvm_targets is a list of supported targets ("AArch64", "ARM", "X86", etc.)
if_has_<TARGET> is a conditional to check if we are building with the target
Expand All @@ -27,6 +37,15 @@ llvm_targets = [
%{LLVM_TARGETS}
]

llvm_cxx_linked = %{LLVM_CXX_LINKED}

llvm_cxx_copts = [
%{LLVM_CXX_COPT}
]

def if_cxx_linked(if_true, if_false = []):
return if_true if llvm_cxx_linked else if_false

def if_has_aarch64(if_true, if_false = []):
return if_true if "AArch64" in llvm_targets else if_false

Expand Down
52 changes: 48 additions & 4 deletions llvm/llvm_configure.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -368,10 +368,9 @@ def _llvm_get_rule_name(
'prefix_dict'.
"""
concat_format = "%s%s"
if name.startswith("llvm_"):
return concat_format % (prefix_dict["llvm"], name[len("llvm_"):])
if name.startswith("clang_"):
return concat_format % (prefix_dict["clang"], name[len("clang_"):])
for old_prefix, new_prefix in prefix_dict.items():
if name.startswith(old_prefix):
return concat_format % (new_prefix, name[len(old_prefix) + 1:])
return name

def _llvm_get_rule_names(
Expand Down Expand Up @@ -787,6 +786,29 @@ def _llvm_local_enabled(repository_ctx):
]))
return enabled

def _llvm_is_linked_against_cxx(repository_ctx, directory = "lib"):
"""Returns whether the LLVM installation is linked against the libc++
standard library.
Args:
repository_ctx: the repository_ctx object.
directory: where to search the libc++ files, 'lib' by default.
Returns:
True if any of the libc++ binaries presents in the
local LLVM installation, False otherwise.
"""
library_files_params = [
_static_library_file_params(repository_ctx),
_import_library_file_params(repository_ctx)
]

for library_prefix, library_ext in library_files_params:
libcxx_file = "%s/%s%s.%s" % (directory, library_prefix, "c++", library_ext)
if repository_ctx.path(libcxx_file).exists:
return True

return False

def _llvm_get_install_path(repository_ctx):
"""Returns a path to a local LLVM installation passed in
the '_LLVM_INSTALL_PREFIX' environment variable.
Expand Down Expand Up @@ -842,6 +864,7 @@ def _llvm_installed_impl(repository_ctx):
prefix_dictionary = {
"llvm": repository_ctx.attr.llvm_prefix,
"clang": repository_ctx.attr.clang_prefix,
"libcxx": repository_ctx.attr.libcxx_prefix,
}
# if there are duplicated prefixes, fail.
_llvm_check_duplicated_prefixes(prefix_dictionary)
Expand Down Expand Up @@ -1907,6 +1930,23 @@ def _llvm_installed_impl(repository_ctx):
"%{LLVM_CONFIG_LIB}":
_llvm_get_config_library_rule(ctx, prx, "llvm_config_headers",
"llvm_config_files", "generated/include"),

"%{LIBCXX_STATIC_LIB}":
_llvm_get_library_rule(ctx, prx, "libcxx_static", "c++"),
"%{LIBCXX_SHARED_LIB}":
_llvm_get_shared_library_rule(ctx, prx, "libcxx_shared", "c++"),
"%{LIBCXX_SHARED_COPY_GENRULE}":
_llvm_get_shared_lib_genrule(ctx, prx, "libcxx_copy_shared",
llvm_path, "c++"),
"%{LIBCXX_ABI_STATIC_LIB}":
_llvm_get_library_rule(ctx, prx, "libcxx_abi_static", "c++abi"),
"%{LIBCXX_ABI_SHARED_LIB}":
_llvm_get_shared_library_rule(ctx, prx, "libcxx_abi_shared",
"c++abi"),
"%{LIBCXX_ABI_SHARED_COPY_GENRULE}":
_llvm_get_shared_lib_genrule(ctx, prx, "libcxx_copy_abi_shared",
llvm_path, "c++abi"),

"%{DEP_LIBS}":
"\n".join([_llvm_get_shared_library_rule(ctx, prx, dep_name, dep_name,
ignore_prefix = True, directory = dep_name)
Expand All @@ -1919,6 +1959,9 @@ def _llvm_installed_impl(repository_ctx):
_tpl(repository_ctx, "llvm_config.bzl", {
"%{LLVM_TARGETS}": _llvm_get_formatted_target_list(repository_ctx,
supported_targets),
"%{LLVM_CXX_LINKED}": str(_llvm_is_linked_against_cxx(repository_ctx)),
"%{LLVM_CXX_COPT}": "\"-stdlib=libc++\"" if _llvm_is_linked_against_cxx(
repository_ctx) else "",
})

llvm_configure = repository_rule(
Expand All @@ -1931,6 +1974,7 @@ llvm_configure = repository_rule(
"strip_prefix": attr.string(default = ""),
"llvm_prefix": attr.string(default = "llvm_"),
"clang_prefix": attr.string(default = "clang_"),
"libcxx_prefix": attr.string(default = "libcxx_"),
"add_headers_to_deps": attr.bool(default = True),
},
environ = [
Expand Down

0 comments on commit 1e1c34c

Please sign in to comment.