mirror of
https://github.com/bazel-contrib/rules_foreign_cc
synced 2024-12-04 08:02:31 +00:00
3dd96c7a14
Some libraries define not only C/C++ libraries and headers, but also scripts for finding this libraries (pkg_config, CMake find/config scripts). Another important use case is defining CMake functions to be used in the CMake build of the dependent targets. As for CMake such scripts are searched for in the number of directory path combinations, relative to CMAKE_INSTALL_PREFIX, including for both Unix and Windows, <prefix>/<name>*/(lib/<arch>|lib|share)/cmake/<name>*/ (W/U) <prefix>/<name>*/(lib/<arch>|lib|share)/<name>*/ (W/U) <prefix>/<name>*/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/ (W/U) acceptable solution would be copying the whole CMake install directory under the dependencies root $EXT_BUILD_DEPS, which is passed as CMAKE_INSTALL_PREFIX. For the libraries, which put their CMake scripts into some other paths, user can add copy command using postfix_script parameter. To be documented better.
160 lines
5.8 KiB
Python
160 lines
5.8 KiB
Python
""" Defines the rule for building external library with CMake
|
|
"""
|
|
|
|
load(
|
|
"//tools/build_defs:framework.bzl",
|
|
"CC_EXTERNAL_RULE_ATTRIBUTES",
|
|
"cc_external_rule_impl",
|
|
"create_attrs",
|
|
"detect_root",
|
|
)
|
|
load("//tools/build_defs:cc_toolchain_util.bzl", "absolutize_path_in_str", "getFlagsInfo", "getToolsInfo")
|
|
|
|
def _cmake_external(ctx):
|
|
options = " ".join(ctx.attr.cmake_options)
|
|
root = detect_root(ctx.attr.lib_source)
|
|
|
|
tools = getToolsInfo(ctx)
|
|
flags = getFlagsInfo(ctx)
|
|
cache_entries = _join_cache_options(ctx, _get_toolchain_entries(ctx, tools, flags), ctx.attr.cache_entries)
|
|
|
|
install_prefix = _get_install_prefix(ctx)
|
|
|
|
cmake_string = " ".join([
|
|
" ".join(_get_toolchain_variables(ctx, tools, flags)),
|
|
" cmake",
|
|
" ".join(cache_entries),
|
|
"-DCMAKE_PREFIX_PATH=\"$EXT_BUILD_DEPS\"",
|
|
"-DCMAKE_INSTALL_PREFIX=\"{}\"".format(install_prefix),
|
|
options,
|
|
"$EXT_BUILD_ROOT/" + root,
|
|
])
|
|
copy_results = "copy_dir_contents_to_dir $TMPDIR/{} $INSTALLDIR".format(install_prefix)
|
|
|
|
attrs = create_attrs(
|
|
ctx.attr,
|
|
configure_name = "CMake",
|
|
configure_script = cmake_string,
|
|
postfix_script = copy_results + "\n" + ctx.attr.postfix_script,
|
|
)
|
|
|
|
return cc_external_rule_impl(ctx, attrs)
|
|
|
|
def _get_install_prefix(ctx):
|
|
if ctx.attr.install_prefix:
|
|
prefix = ctx.attr.install_prefix
|
|
|
|
# If not in sandbox, or after the build, the value can be absolute.
|
|
# So if the user passed the absolute value, do not touch it.
|
|
if (prefix.startswith("/")):
|
|
return prefix
|
|
return prefix if prefix.startswith("./") else "./" + prefix
|
|
if ctx.attr.lib_name:
|
|
return "./" + ctx.attr.lib_name
|
|
return "./" + ctx.attr.name
|
|
|
|
def _get_toolchain_variables(ctx, tools, flags):
|
|
vars = {}
|
|
|
|
if tools.cc:
|
|
vars["CC"] = [tools.cc]
|
|
if tools.cxx:
|
|
vars["CXX"] = [tools.cxx]
|
|
if flags.cc:
|
|
vars["CFLAGS"] = flags.cc
|
|
if flags.cc:
|
|
vars["CXXFLAGS"] = flags.cxx
|
|
if flags.assemble:
|
|
vars["ASMFLAGS"] = flags.assemble
|
|
|
|
for key in ctx.attr.env_vars:
|
|
existing = []
|
|
if vars.get(key, None):
|
|
existing = vars[key]
|
|
vars[key] = existing + [ctx.attr.env_vars[key]]
|
|
|
|
return [_env_var(ctx, key, vars[key]) for key in vars]
|
|
|
|
def _get_toolchain_entries(ctx, tools, flags):
|
|
options = {}
|
|
if tools.cxx_linker_static:
|
|
options["CMAKE_AR"] = [tools.cxx_linker_static]
|
|
|
|
# this does not work by some reason
|
|
# options += _option(ctx, "CMAKE_CXX_CREATE_STATIC_LIBRARY", ["<CMAKE_AR> <LINK_FLAGS> qc <TARGET> <OBJECTS>"])
|
|
# options += _option(ctx, "CMAKE_CXX_ARCHIVE_CREATE", ["<CMAKE_AR> <LINK_FLAGS> qc <TARGET> <OBJECTS>"])
|
|
# options += _option(ctx, "CMAKE_CXX_ARCHIVE_APPEND", ["<CMAKE_AR> <LINK_FLAGS> qc <TARGET> <OBJECTS>"])
|
|
# options += _option(ctx, "CMAKE_CXX_ARCHIVE_FINISH", ["<CMAKE_RANLIB> <TARGET>"])
|
|
|
|
if tools.cxx_linker_executable:
|
|
# https://github.com/Kitware/CMake/blob/master/Modules/CMakeCXXInformation.cmake
|
|
rule_string = " ".join([
|
|
"{}",
|
|
"<FLAGS>",
|
|
"<CMAKE_CXX_LINK_FLAGS>",
|
|
"<LINK_FLAGS>",
|
|
"<OBJECTS>",
|
|
"-o <TARGET>",
|
|
"<LINK_LIBRARIES>",
|
|
]).format(absolutize_path_in_str(ctx, tools.cxx_linker_executable, "$EXT_BUILD_ROOT/"))
|
|
options["CMAKE_CXX_LINK_EXECUTABLE"] = [rule_string]
|
|
|
|
# commented out for now, because http://cmake.3232098.n2.nabble.com/CMake-incorrectly-passes-linker-flags-to-ar-td7592436.html
|
|
# if flags.cxx_linker_static:
|
|
# options += _option(ctx, "CMAKE_STATIC_LINKER_FLAGS", flags.cxx_linker_static)
|
|
if flags.cxx_linker_shared:
|
|
options["CMAKE_SHARED_LINKER_FLAGS"] = flags.cxx_linker_shared
|
|
if flags.cxx_linker_executable:
|
|
options["CMAKE_EXE_LINKER_FLAGS"] = flags.cxx_linker_executable
|
|
|
|
return options
|
|
|
|
def _join_cache_options(ctx, toolchain_entries, user_entries):
|
|
cache_entries = dict(toolchain_entries)
|
|
|
|
for key in user_entries:
|
|
existing = []
|
|
if cache_entries.get(key, None):
|
|
existing = cache_entries[key]
|
|
cache_entries[key] = existing + [user_entries[key]]
|
|
|
|
return [_option(ctx, key, cache_entries[key]) for key in cache_entries]
|
|
|
|
def _env_var(ctx, cmake_option, flags):
|
|
return "{}=\"{}\"".format(cmake_option, _join_flags_list(ctx, flags))
|
|
|
|
def _option(ctx, cmake_option, flags):
|
|
return "-D{}=\"{}\"".format(cmake_option, _join_flags_list(ctx, flags))
|
|
|
|
def _join_flags_list(ctx, flags):
|
|
return " ".join([absolutize_path_in_str(ctx, flag, "$EXT_BUILD_ROOT/") for flag in flags])
|
|
|
|
def _attrs():
|
|
attrs = dict(CC_EXTERNAL_RULE_ATTRIBUTES)
|
|
attrs.update({
|
|
# Relative install prefix to be passed to CMake in -DCMAKE_INSTALL_PREFIX
|
|
"install_prefix": attr.string(mandatory = False),
|
|
# CMake cache entries to initialize (they will be passed with -Dkey=value)
|
|
# Values, defined by the toolchain, will be joined with the values, passed here.
|
|
# (Toolchain values come first)
|
|
"cache_entries": attr.string_dict(mandatory = False, default = {}),
|
|
# CMake environment variable values to join with toolchain-defined.
|
|
# For example, additional CXXFLAGS.
|
|
"env_vars": attr.string_dict(mandatory = False, default = {}),
|
|
# Other CMake options
|
|
"cmake_options": attr.string_list(mandatory = False, default = []),
|
|
})
|
|
return attrs
|
|
|
|
""" Rule for building external library with CMake
|
|
Attributes:
|
|
cmake_options - (list of strings) options to be passed to the cmake call
|
|
Other attributes are documented in framework.bzl:CC_EXTERNAL_RULE_ATTRIBUTES
|
|
"""
|
|
cmake_external = rule(
|
|
attrs = _attrs(),
|
|
fragments = ["cpp"],
|
|
output_to_genfiles = True,
|
|
implementation = _cmake_external,
|
|
)
|