diff --git a/README.md b/README.md index f5c87c9..544ce04 100644 --- a/README.md +++ b/README.md @@ -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` @@ -77,6 +78,7 @@ llvm_configure( name = "local_llvm", llvm_prefix = "llvm_", clang_prefix = "clang_", + libcxx_prefix = "libcxx_", sha256 = "c80b5b10df191465df8cee8c273d9c46715e6f27f80fef118ad4ebb7d9f3a7d3", strip_prefix = "clang+llvm-9.0.0-x86_64-linux-sles11.3", urls = [ @@ -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", @@ -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"], ) ``` @@ -250,3 +256,45 @@ and `llvm_copy_c`. Just add the targets into the `data` attribute of a rule and they will appear in a `bazel-bin/external/` directory. Then the libraries can be copied into the `bazel-bin` (see genrules in the `examples/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"], +) +``` diff --git a/examples/BUILD b/examples/BUILD index a016b44..4c740aa 100644 --- a/examples/BUILD +++ b/examples/BUILD @@ -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", @@ -49,21 +51,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"], ) @@ -72,12 +79,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", @@ -94,7 +96,10 @@ cc_binary( ], deps = [ ":llvm_exp_passes", - ], + ] + if_cxx_linked([ + "@local_llvm//:cxx_shared", + "@local_llvm//:cxx_abi_shared", + ]), visibility = ["//visibility:private"], ) @@ -103,12 +108,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"]) @@ -186,7 +186,10 @@ cc_binary( ]) + if_has_x_core([ "@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( @@ -194,12 +197,7 @@ cc_binary( 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", @@ -218,7 +216,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,." diff --git a/examples/WORKSPACE b/examples/WORKSPACE index ff4274f..32e8b8a 100644 --- a/examples/WORKSPACE +++ b/examples/WORKSPACE @@ -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 diff --git a/llvm/BUILD.tpl b/llvm/BUILD.tpl index 902b4de..509373e 100644 --- a/llvm/BUILD.tpl +++ b/llvm/BUILD.tpl @@ -188,3 +188,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} diff --git a/llvm/llvm_config.bzl.tpl b/llvm/llvm_config.bzl.tpl index ec64529..fc15ed3 100644 --- a/llvm/llvm_config.bzl.tpl +++ b/llvm/llvm_config.bzl.tpl @@ -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_ is a conditional to check if we are building with the target @@ -28,6 +38,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 diff --git a/llvm/llvm_configure.bzl b/llvm/llvm_configure.bzl index 2013334..5e7d58c 100644 --- a/llvm/llvm_configure.bzl +++ b/llvm/llvm_configure.bzl @@ -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( @@ -782,6 +781,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. @@ -835,6 +857,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) @@ -1883,6 +1906,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) @@ -1895,6 +1935,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( @@ -1907,6 +1950,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 = [