2
0
Fork 0
mirror of https://github.com/bazel-contrib/rules_foreign_cc synced 2024-12-04 08:02:31 +00:00
rules_foreign_cc/tools/build_defs/cmake.bzl
irengrig 3dd96c7a14
Important refactoring of the $EXT_BUILD_DEPS directory structure. (#41)
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.
2018-08-20 18:47:49 +02:00

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,
)