mirror of
https://github.com/bazel-contrib/rules_foreign_cc
synced 2024-11-28 08:43:26 +00:00
Do not support Bazel before 0.20 (#195)
This commit is contained in:
parent
99ea1b09fc
commit
4dc369a845
|
@ -7,7 +7,7 @@ Rules for building C/C++ projects using foreign build systems inside Bazel proje
|
|||
* This is not an officially supported Google product
|
||||
(meaning, support and/or new releases may be limited.)
|
||||
|
||||
**NOTE**: this requires Bazel version starting from 0.17.1.
|
||||
**NOTE**: this requires Bazel version starting from 0.20.0
|
||||
|
||||
It also requires passing Bazel the following flag:
|
||||
(**please pay attention @foreign_cc_impl was added** due to adoption to Starlark API changes that are goning to happen in Bazel 0.21)
|
||||
|
@ -19,6 +19,8 @@ Where ```rules_foreign_cc``` is the name of this repository in your WORKSPACE fi
|
|||
## News
|
||||
**January 2019:**
|
||||
|
||||
- Should be used with Bazel 0.20.0 or newer.
|
||||
|
||||
- Examples package became the separate workspace.
|
||||
This also allows to illustrate how to initialize rules_foreign_cc.
|
||||
|
||||
|
|
|
@ -27,13 +27,11 @@ generate_implementation_fragments = repository_rule(
|
|||
default = [
|
||||
"@rules_foreign_cc//tools/build_defs/new_11_2018/cc_toolchain_util.bzl",
|
||||
"@rules_foreign_cc//tools/build_defs/new_11_2018/framework.bzl",
|
||||
|
||||
"@rules_foreign_cc//tools/build_defs/old_11_2018/cc_toolchain_util.bzl",
|
||||
"@rules_foreign_cc//tools/build_defs/old_11_2018/framework.bzl",
|
||||
|
||||
"@rules_foreign_cc//tools/build_defs/old_10_2018/cc_toolchain_util.bzl",
|
||||
"@rules_foreign_cc//tools/build_defs/old_10_2018/framework.bzl",
|
||||
]
|
||||
"@rules_foreign_cc//tools/build_defs/old_12_2018/cc_toolchain_util.bzl",
|
||||
"@rules_foreign_cc//tools/build_defs/old_12_2018/framework.bzl",
|
||||
],
|
||||
),
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
|
@ -1,425 +0,0 @@
|
|||
""" Defines create_linking_info, which wraps passed libraries into CcLinkingInfo
|
||||
"""
|
||||
|
||||
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
|
||||
load(
|
||||
"@bazel_tools//tools/build_defs/cc:action_names.bzl",
|
||||
"ASSEMBLE_ACTION_NAME",
|
||||
"CPP_COMPILE_ACTION_NAME",
|
||||
"CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME",
|
||||
"CPP_LINK_EXECUTABLE_ACTION_NAME",
|
||||
"CPP_LINK_STATIC_LIBRARY_ACTION_NAME",
|
||||
"C_COMPILE_ACTION_NAME",
|
||||
)
|
||||
|
||||
LibrariesToLinkInfo = provider(
|
||||
doc = "Libraries to be wrapped into CcLinkingInfo",
|
||||
fields = dict(
|
||||
static_libraries = "Static library files, optional",
|
||||
shared_libraries = "Shared library files, optional",
|
||||
interface_libraries = "Interface library files, optional",
|
||||
),
|
||||
)
|
||||
|
||||
CxxToolsInfo = provider(
|
||||
doc = "Paths to the C/C++ tools, taken from the toolchain",
|
||||
fields = dict(
|
||||
cc = "C compiler",
|
||||
cxx = "C++ compiler",
|
||||
cxx_linker_static = "C++ linker to link static library",
|
||||
cxx_linker_executable = "C++ linker to link executable",
|
||||
),
|
||||
)
|
||||
|
||||
CxxFlagsInfo = provider(
|
||||
doc = "Flags for the C/C++ tools, taken from the toolchain",
|
||||
fields = dict(
|
||||
cc = "C compiler flags",
|
||||
cxx = "C++ compiler flags",
|
||||
cxx_linker_shared = "C++ linker flags when linking shared library",
|
||||
cxx_linker_static = "C++ linker flags when linking static library",
|
||||
cxx_linker_executable = "C++ linker flags when linking executable",
|
||||
assemble = "Assemble flags",
|
||||
),
|
||||
)
|
||||
|
||||
def _to_list(element):
|
||||
if element == None:
|
||||
return []
|
||||
else:
|
||||
return [element]
|
||||
|
||||
def _to_depset(element):
|
||||
if element == None:
|
||||
return depset()
|
||||
return depset(element)
|
||||
|
||||
def _perform_error_checks(
|
||||
system_provided,
|
||||
shared_library_artifacts,
|
||||
interface_library_artifacts,
|
||||
targets_windows):
|
||||
# If the shared library will be provided by system during runtime, users are not supposed to
|
||||
# specify shared_library.
|
||||
if system_provided and shared_library_artifacts:
|
||||
fail("'shared_library' shouldn't be specified when 'system_provided' is true")
|
||||
|
||||
# If a shared library won't be provided by system during runtime and we are linking the shared
|
||||
# library through interface library, the shared library must be specified.
|
||||
if (not system_provided and not shared_library_artifacts and
|
||||
interface_library_artifacts):
|
||||
fail("'shared_library' should be specified when 'system_provided' is false")
|
||||
|
||||
if targets_windows and shared_library_artifacts:
|
||||
fail("'interface library' must be specified when using cc_import for " +
|
||||
"shared library on Windows")
|
||||
|
||||
def _build_static_library_to_link(ctx, library):
|
||||
if library == None:
|
||||
fail("Parameter 'static_library_artifact' cannot be None")
|
||||
|
||||
static_library_category = None
|
||||
if ctx.attr.alwayslink:
|
||||
static_library_category = "alwayslink_static_library"
|
||||
else:
|
||||
static_library_category = "static_library"
|
||||
|
||||
return cc_common.create_library_to_link(
|
||||
ctx = ctx,
|
||||
library = library,
|
||||
artifact_category = static_library_category,
|
||||
)
|
||||
|
||||
def _build_shared_library_to_link(ctx, library, cc_toolchain, targets_windows):
|
||||
if library == None:
|
||||
fail("Parameter 'shared_library_artifact' cannot be None")
|
||||
|
||||
if not targets_windows and hasattr(cc_common, "create_symlink_library_to_link"):
|
||||
return cc_common.create_symlink_library_to_link(
|
||||
ctx = ctx,
|
||||
cc_toolchain = cc_toolchain,
|
||||
library = library,
|
||||
)
|
||||
|
||||
return cc_common.create_library_to_link(
|
||||
ctx = ctx,
|
||||
library = library,
|
||||
artifact_category = "dynamic_library",
|
||||
)
|
||||
|
||||
def _build_interface_library_to_link(ctx, library, cc_toolchain, targets_windows):
|
||||
if library == None:
|
||||
fail("Parameter 'interface_library_artifact' cannot be None")
|
||||
|
||||
if not targets_windows and hasattr(cc_common, "create_symlink_library_to_link"):
|
||||
return cc_common.create_symlink_library_to_link(
|
||||
ctx = ctx,
|
||||
cc_toolchain = cc_toolchain,
|
||||
library = library,
|
||||
)
|
||||
return cc_common.create_library_to_link(
|
||||
ctx = ctx,
|
||||
library = library,
|
||||
artifact_category = "interface_library",
|
||||
)
|
||||
|
||||
# we could possibly take a decision about linking interface/shared library beased on each library name
|
||||
# (usefull for the case when multiple output targets are provided)
|
||||
def _build_libraries_to_link_and_runtime_artifact(ctx, files, cc_toolchain, targets_windows):
|
||||
static_libraries = [_build_static_library_to_link(ctx, lib) for lib in (files.static_libraries or [])]
|
||||
|
||||
shared_libraries = []
|
||||
runtime_artifacts = []
|
||||
if files.shared_libraries != None:
|
||||
for lib in files.shared_libraries:
|
||||
shared_library = _build_shared_library_to_link(ctx, lib, cc_toolchain, targets_windows)
|
||||
shared_libraries += [shared_library]
|
||||
runtime_artifacts += [shared_library.artifact()]
|
||||
|
||||
interface_libraries = []
|
||||
if files.interface_libraries != None:
|
||||
for lib in files.interface_libraries:
|
||||
interface_libraries += [_build_interface_library_to_link(ctx, lib, cc_toolchain, targets_windows)]
|
||||
|
||||
dynamic_libraries_for_linking = None
|
||||
if len(interface_libraries) > 0:
|
||||
dynamic_libraries_for_linking = interface_libraries
|
||||
else:
|
||||
dynamic_libraries_for_linking = shared_libraries
|
||||
|
||||
return {
|
||||
"static_libraries": static_libraries,
|
||||
"dynamic_libraries": dynamic_libraries_for_linking,
|
||||
"runtime_artifacts": runtime_artifacts,
|
||||
}
|
||||
|
||||
def _build_cc_link_params(
|
||||
ctx,
|
||||
user_link_flags,
|
||||
static_libraries,
|
||||
dynamic_libraries,
|
||||
runtime_artifacts):
|
||||
static_shared = None
|
||||
static_no_shared = None
|
||||
if static_libraries != None and len(static_libraries) > 0:
|
||||
static_shared = cc_common.create_cc_link_params(
|
||||
ctx = ctx,
|
||||
user_link_flags = user_link_flags,
|
||||
libraries_to_link = _to_depset(static_libraries),
|
||||
)
|
||||
static_no_shared = cc_common.create_cc_link_params(
|
||||
ctx = ctx,
|
||||
libraries_to_link = _to_depset(static_libraries),
|
||||
)
|
||||
else:
|
||||
static_shared = cc_common.create_cc_link_params(
|
||||
ctx = ctx,
|
||||
user_link_flags = user_link_flags,
|
||||
libraries_to_link = _to_depset(dynamic_libraries),
|
||||
dynamic_libraries_for_runtime = _to_depset(runtime_artifacts),
|
||||
)
|
||||
static_no_shared = cc_common.create_cc_link_params(
|
||||
ctx = ctx,
|
||||
libraries_to_link = _to_depset(dynamic_libraries),
|
||||
dynamic_libraries_for_runtime = _to_depset(runtime_artifacts),
|
||||
)
|
||||
|
||||
no_static_shared = None
|
||||
no_static_no_shared = None
|
||||
if dynamic_libraries != None and len(dynamic_libraries) > 0:
|
||||
no_static_shared = cc_common.create_cc_link_params(
|
||||
ctx = ctx,
|
||||
user_link_flags = user_link_flags,
|
||||
libraries_to_link = _to_depset(dynamic_libraries),
|
||||
dynamic_libraries_for_runtime = _to_depset(runtime_artifacts),
|
||||
)
|
||||
no_static_no_shared = cc_common.create_cc_link_params(
|
||||
ctx = ctx,
|
||||
libraries_to_link = _to_depset(dynamic_libraries),
|
||||
dynamic_libraries_for_runtime = _to_depset(runtime_artifacts),
|
||||
)
|
||||
else:
|
||||
no_static_shared = cc_common.create_cc_link_params(
|
||||
ctx = ctx,
|
||||
user_link_flags = user_link_flags,
|
||||
libraries_to_link = _to_depset(static_libraries),
|
||||
)
|
||||
no_static_no_shared = cc_common.create_cc_link_params(
|
||||
ctx = ctx,
|
||||
libraries_to_link = _to_depset(static_libraries),
|
||||
)
|
||||
|
||||
return {
|
||||
"static_mode_params_for_dynamic_library": static_shared,
|
||||
"static_mode_params_for_executable": static_no_shared,
|
||||
"dynamic_mode_params_for_dynamic_library": no_static_shared,
|
||||
"dynamic_mode_params_for_executable": no_static_no_shared,
|
||||
}
|
||||
|
||||
def targets_windows(ctx, cc_toolchain):
|
||||
""" Returns true if build is targeting Windows
|
||||
Args:
|
||||
ctx - rule context
|
||||
cc_toolchain - optional - Cc toolchain
|
||||
"""
|
||||
toolchain = cc_toolchain if cc_toolchain else find_cpp_toolchain(ctx)
|
||||
feature_configuration = cc_common.configure_features(
|
||||
cc_toolchain = toolchain,
|
||||
requested_features = ctx.features,
|
||||
unsupported_features = ctx.disabled_features,
|
||||
)
|
||||
|
||||
return cc_common.is_enabled(
|
||||
feature_configuration = feature_configuration,
|
||||
feature_name = "targets_windows",
|
||||
)
|
||||
|
||||
def create_linking_info(ctx, user_link_flags, files):
|
||||
""" Creates CcLinkingInfo for the passed user link options and libraries.
|
||||
Args:
|
||||
ctx - rule context
|
||||
user_link_flags - (list of strings) link optins, provided by user
|
||||
files - (LibrariesToLink) provider with the library files
|
||||
"""
|
||||
cc_toolchain = find_cpp_toolchain(ctx)
|
||||
for_windows = targets_windows(ctx, cc_toolchain)
|
||||
|
||||
_perform_error_checks(
|
||||
False,
|
||||
files.shared_libraries,
|
||||
files.interface_libraries,
|
||||
for_windows,
|
||||
)
|
||||
|
||||
artifacts = _build_libraries_to_link_and_runtime_artifact(
|
||||
ctx,
|
||||
files,
|
||||
cc_toolchain,
|
||||
for_windows,
|
||||
)
|
||||
|
||||
link_params = _build_cc_link_params(ctx, user_link_flags, **artifacts)
|
||||
|
||||
return CcLinkingInfo(**link_params)
|
||||
|
||||
def get_env_vars(ctx):
|
||||
cc_toolchain = find_cpp_toolchain(ctx)
|
||||
feature_configuration = cc_common.configure_features(
|
||||
cc_toolchain = cc_toolchain,
|
||||
requested_features = ctx.features,
|
||||
unsupported_features = ctx.disabled_features,
|
||||
)
|
||||
copts = ctx.attr.copts if hasattr(ctx.attr, "copts") else depset()
|
||||
|
||||
vars = dict()
|
||||
|
||||
for action_name in [C_COMPILE_ACTION_NAME, CPP_LINK_STATIC_LIBRARY_ACTION_NAME, CPP_LINK_EXECUTABLE_ACTION_NAME]:
|
||||
vars.update(cc_common.get_environment_variables(
|
||||
feature_configuration = feature_configuration,
|
||||
action_name = action_name,
|
||||
variables = cc_common.create_compile_variables(
|
||||
feature_configuration = feature_configuration,
|
||||
cc_toolchain = cc_toolchain,
|
||||
user_compile_flags = copts,
|
||||
),
|
||||
))
|
||||
return vars
|
||||
|
||||
def is_debug_mode(ctx):
|
||||
# see workspace_definitions.bzl
|
||||
return str(True) == ctx.attr._is_debug[config_common.FeatureFlagInfo].value
|
||||
|
||||
def get_tools_info(ctx):
|
||||
""" Takes information about tools paths from cc_toolchain, returns CxxToolsInfo
|
||||
Args:
|
||||
ctx - rule context
|
||||
"""
|
||||
cc_toolchain = find_cpp_toolchain(ctx)
|
||||
feature_configuration = cc_common.configure_features(
|
||||
cc_toolchain = cc_toolchain,
|
||||
requested_features = ctx.features,
|
||||
unsupported_features = ctx.disabled_features,
|
||||
)
|
||||
|
||||
return CxxToolsInfo(
|
||||
cc = cc_common.get_tool_for_action(
|
||||
feature_configuration = feature_configuration,
|
||||
action_name = C_COMPILE_ACTION_NAME,
|
||||
),
|
||||
cxx = cc_common.get_tool_for_action(
|
||||
feature_configuration = feature_configuration,
|
||||
action_name = CPP_COMPILE_ACTION_NAME,
|
||||
),
|
||||
cxx_linker_static = cc_common.get_tool_for_action(
|
||||
feature_configuration = feature_configuration,
|
||||
action_name = CPP_LINK_STATIC_LIBRARY_ACTION_NAME,
|
||||
),
|
||||
cxx_linker_executable = cc_common.get_tool_for_action(
|
||||
feature_configuration = feature_configuration,
|
||||
action_name = CPP_LINK_EXECUTABLE_ACTION_NAME,
|
||||
),
|
||||
)
|
||||
|
||||
def get_flags_info(ctx):
|
||||
""" Takes information about flags from cc_toolchain, returns CxxFlagsInfo
|
||||
Args:
|
||||
ctx - rule context
|
||||
"""
|
||||
cc_toolchain = find_cpp_toolchain(ctx)
|
||||
feature_configuration = cc_common.configure_features(
|
||||
cc_toolchain = cc_toolchain,
|
||||
requested_features = ctx.features,
|
||||
unsupported_features = ctx.disabled_features,
|
||||
)
|
||||
copts = ctx.attr.copts if hasattr(ctx.attr, "copts") else depset()
|
||||
|
||||
return CxxFlagsInfo(
|
||||
cc = cc_common.get_memory_inefficient_command_line(
|
||||
feature_configuration = feature_configuration,
|
||||
action_name = C_COMPILE_ACTION_NAME,
|
||||
variables = cc_common.create_compile_variables(
|
||||
feature_configuration = feature_configuration,
|
||||
cc_toolchain = cc_toolchain,
|
||||
user_compile_flags = copts,
|
||||
),
|
||||
),
|
||||
cxx = cc_common.get_memory_inefficient_command_line(
|
||||
feature_configuration = feature_configuration,
|
||||
action_name = CPP_COMPILE_ACTION_NAME,
|
||||
variables = cc_common.create_compile_variables(
|
||||
feature_configuration = feature_configuration,
|
||||
cc_toolchain = cc_toolchain,
|
||||
user_compile_flags = copts,
|
||||
add_legacy_cxx_options = True,
|
||||
),
|
||||
),
|
||||
cxx_linker_shared = cc_common.get_memory_inefficient_command_line(
|
||||
feature_configuration = feature_configuration,
|
||||
action_name = CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME,
|
||||
variables = cc_common.create_link_variables(
|
||||
cc_toolchain = cc_toolchain,
|
||||
feature_configuration = feature_configuration,
|
||||
is_using_linker = True,
|
||||
is_linking_dynamic_library = True,
|
||||
),
|
||||
),
|
||||
cxx_linker_static = cc_common.get_memory_inefficient_command_line(
|
||||
feature_configuration = feature_configuration,
|
||||
action_name = CPP_LINK_STATIC_LIBRARY_ACTION_NAME,
|
||||
variables = cc_common.create_link_variables(
|
||||
cc_toolchain = cc_toolchain,
|
||||
feature_configuration = feature_configuration,
|
||||
is_using_linker = False,
|
||||
is_linking_dynamic_library = False,
|
||||
),
|
||||
),
|
||||
cxx_linker_executable = cc_common.get_memory_inefficient_command_line(
|
||||
feature_configuration = feature_configuration,
|
||||
action_name = CPP_LINK_EXECUTABLE_ACTION_NAME,
|
||||
variables = cc_common.create_link_variables(
|
||||
cc_toolchain = cc_toolchain,
|
||||
feature_configuration = feature_configuration,
|
||||
is_using_linker = True,
|
||||
is_linking_dynamic_library = False,
|
||||
),
|
||||
),
|
||||
assemble = cc_common.get_memory_inefficient_command_line(
|
||||
feature_configuration = feature_configuration,
|
||||
action_name = ASSEMBLE_ACTION_NAME,
|
||||
variables = cc_common.create_compile_variables(
|
||||
feature_configuration = feature_configuration,
|
||||
cc_toolchain = cc_toolchain,
|
||||
user_compile_flags = copts,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
def absolutize_path_in_str(workspace_name, root_str, text, force = False):
|
||||
""" Replaces relative paths in [the middle of] 'text', prepending them with 'root_str'.
|
||||
If there is nothing to replace, returns the 'text'.
|
||||
|
||||
We only will replace relative paths starting with either 'external/' or '<top-package-name>/',
|
||||
because we only want to point with absolute paths to external repositories or inside our
|
||||
current workspace. (And also to limit the possibility of error with such not exact replacing.)
|
||||
|
||||
Args:
|
||||
workspace_name - workspace name
|
||||
text - the text to do replacement in
|
||||
root_str - the text to prepend to the found relative path
|
||||
"""
|
||||
new_text = _prefix(text, "external/", root_str)
|
||||
if new_text == text:
|
||||
new_text = _prefix(text, workspace_name + "/", root_str)
|
||||
# absolutize relative by adding our working directory
|
||||
# this works because we ru on windows under msys now
|
||||
if force and new_text == text and not text.startswith("/"):
|
||||
new_text = root_str + "/" + text
|
||||
|
||||
return new_text
|
||||
|
||||
def _prefix(text, from_str, prefix):
|
||||
text = text.replace('"', '\\"')
|
||||
(before, middle, after) = text.partition(from_str)
|
||||
if not middle or before.endswith("/"):
|
||||
return text
|
||||
return before + prefix + middle + after
|
|
@ -1,601 +0,0 @@
|
|||
""" Contains definitions for creation of external C/C++ build rules (for building external libraries
|
||||
with CMake, configure/make, autotools)
|
||||
"""
|
||||
|
||||
load("@bazel_skylib//lib:collections.bzl", "collections")
|
||||
load("@rules_foreign_cc//tools/build_defs:version.bzl", "VERSION")
|
||||
load(
|
||||
":cc_toolchain_util.bzl",
|
||||
"LibrariesToLinkInfo",
|
||||
"create_linking_info",
|
||||
"get_env_vars",
|
||||
"targets_windows",
|
||||
)
|
||||
load("@rules_foreign_cc//tools/build_defs:detect_root.bzl", "detect_root")
|
||||
load("@foreign_cc_platform_utils//:os_info.bzl", "OSInfo")
|
||||
load("@rules_foreign_cc//tools/build_defs:run_shell_file_utils.bzl", "copy_directory", "fictive_file_in_genroot")
|
||||
|
||||
""" Dict with definitions of the context attributes, that customize cc_external_rule_impl function.
|
||||
Many of the attributes have default values.
|
||||
|
||||
Typically, the concrete external library rule will use this structure to create the attributes
|
||||
description dict. See cmake.bzl as an example.
|
||||
"""
|
||||
CC_EXTERNAL_RULE_ATTRIBUTES = {
|
||||
# Library name. Defines the name of the install directory and the name of the static library,
|
||||
# if no output files parameters are defined (any of static_libraries, shared_libraries,
|
||||
# interface_libraries, binaries_names)
|
||||
# Optional. If not defined, defaults to the target's name.
|
||||
"lib_name": attr.string(mandatory = False),
|
||||
# Label with source code to build. Typically a filegroup for the source of remote repository.
|
||||
# Mandatory.
|
||||
"lib_source": attr.label(mandatory = True, allow_files = True),
|
||||
# Optional compilation definitions to be passed to the dependencies of this library.
|
||||
# They are NOT passed to the compiler, you should duplicate them in the configuration options.
|
||||
"defines": attr.string_list(mandatory = False, default = []),
|
||||
#
|
||||
# Optional additional inputs to be declared as needed for the shell script action.
|
||||
# Not used by the shell script part in cc_external_rule_impl.
|
||||
"additional_inputs": attr.label_list(mandatory = False, allow_files = True, default = []),
|
||||
# Optional additional tools needed for the building.
|
||||
# Not used by the shell script part in cc_external_rule_impl.
|
||||
"additional_tools": attr.label_list(mandatory = False, allow_files = True, default = []),
|
||||
#
|
||||
# Optional part of the shell script to be added after the make commands
|
||||
"postfix_script": attr.string(mandatory = False),
|
||||
# Optinal make commands, defaults to ["make", "make install"]
|
||||
"make_commands": attr.string_list(mandatory = False, default = ["make", "make install"]),
|
||||
#
|
||||
# Optional dependencies to be copied into the directory structure.
|
||||
# Typically those directly required for the external building of the library/binaries.
|
||||
# (i.e. those that the external buidl system will be looking for and paths to which are
|
||||
# provided by the calling rule)
|
||||
"deps": attr.label_list(mandatory = False, allow_files = True, default = []),
|
||||
# Optional tools to be copied into the directory structure.
|
||||
# Similar to deps, those directly required for the external building of the library/binaries.
|
||||
"tools_deps": attr.label_list(mandatory = False, allow_files = True, default = []),
|
||||
#
|
||||
# Optional name of the output subdirectory with the header files, defaults to 'include'.
|
||||
"out_include_dir": attr.string(mandatory = False, default = "include"),
|
||||
# Optional name of the output subdirectory with the library files, defaults to 'lib'.
|
||||
"out_lib_dir": attr.string(mandatory = False, default = "lib"),
|
||||
# Optional name of the output subdirectory with the binary files, defaults to 'bin'.
|
||||
"out_bin_dir": attr.string(mandatory = False, default = "bin"),
|
||||
#
|
||||
# Optional. if true, link all the object files from the static library,
|
||||
# even if they are not used.
|
||||
"alwayslink": attr.bool(mandatory = False, default = False),
|
||||
# Optional link options to be passed up to the dependencies of this library
|
||||
"linkopts": attr.string_list(mandatory = False, default = []),
|
||||
#
|
||||
# Output files names parameters. If any of them is defined, only these files are passed to
|
||||
# Bazel providers.
|
||||
# if no of them is defined, default lib_name.a/lib_name.lib static library is assumed.
|
||||
#
|
||||
# Optional names of the resulting static libraries.
|
||||
"static_libraries": attr.string_list(mandatory = False),
|
||||
# Optional names of the resulting shared libraries.
|
||||
"shared_libraries": attr.string_list(mandatory = False),
|
||||
# Optional names of the resulting interface libraries.
|
||||
"interface_libraries": attr.string_list(mandatory = False),
|
||||
# Optional names of the resulting binaries.
|
||||
"binaries": attr.string_list(mandatory = False),
|
||||
# Flag variable to indicate that the library produces only headers
|
||||
"headers_only": attr.bool(mandatory = False, default = False),
|
||||
#
|
||||
# link to the shell utilities used by the shell script in cc_external_rule_impl.
|
||||
"_utils": attr.label(
|
||||
default = "@foreign_cc_platform_utils//:shell_utils",
|
||||
allow_single_file = True,
|
||||
),
|
||||
"_is_debug": attr.label(
|
||||
default = "@foreign_cc_platform_utils//:compilation_mode",
|
||||
),
|
||||
# link to the shell utilities used by the shell script in cc_external_rule_impl.
|
||||
"_target_os": attr.label(
|
||||
default = "@foreign_cc_platform_utils//:target_os",
|
||||
),
|
||||
# we need to declare this attribute to access cc_toolchain
|
||||
"_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
|
||||
}
|
||||
|
||||
def create_attrs(attr_struct, configure_name, create_configure_script, **kwargs):
|
||||
""" Function for adding/modifying context attributes struct (originally from ctx.attr),
|
||||
provided by user, to be passed to the cc_external_rule_impl function as a struct.
|
||||
|
||||
Copies a struct 'attr_struct' values (with attributes from CC_EXTERNAL_RULE_ATTRIBUTES)
|
||||
to the resulting struct, adding or replacing attributes passed in 'configure_name',
|
||||
'configure_script', and '**kwargs' parameters.
|
||||
"""
|
||||
attrs = {}
|
||||
for key in CC_EXTERNAL_RULE_ATTRIBUTES:
|
||||
if not key.startswith("_") and hasattr(attr_struct, key):
|
||||
attrs[key] = getattr(attr_struct, key)
|
||||
|
||||
attrs["configure_name"] = configure_name
|
||||
attrs["create_configure_script"] = create_configure_script
|
||||
|
||||
for arg in kwargs:
|
||||
attrs[arg] = kwargs[arg]
|
||||
return struct(**attrs)
|
||||
|
||||
ForeignCcDeps = provider(
|
||||
doc = """Provider to pass transitive information about external libraries.""",
|
||||
fields = {"artifacts": "Depset of ForeignCcArtifact"},
|
||||
)
|
||||
|
||||
ForeignCcArtifact = provider(
|
||||
doc = """Groups information about the external library install directory,
|
||||
and relative bin, include and lib directories.
|
||||
|
||||
Serves to pass transitive information about externally built artifacts up the dependency chain.
|
||||
|
||||
Can not be used as a top-level provider.
|
||||
Instances of ForeignCcArtifact are incapsulated in a depset ForeignCcDeps#artifacts.""",
|
||||
fields = {
|
||||
"gen_dir": "Install directory",
|
||||
"bin_dir_name": "Bin directory, relative to install directory",
|
||||
"lib_dir_name": "Lib directory, relative to install directory",
|
||||
"include_dir_name": "Include directory, relative to install directory",
|
||||
},
|
||||
)
|
||||
|
||||
ConfigureParameters = provider(
|
||||
doc = """Parameters of create_configure_script callback function, called by
|
||||
cc_external_rule_impl function. create_configure_script creates the configuration part
|
||||
of the script, and allows to reuse the inputs structure, created by the framework.""",
|
||||
fields = dict(
|
||||
ctx = "Rule context",
|
||||
attrs = """Attributes struct, created by create_attrs function above""",
|
||||
inputs = """InputFiles provider: summarized information on rule inputs, created by framework
|
||||
function, to be reused in script creator. Contains in particular merged compilation and linking
|
||||
dependencies.""",
|
||||
),
|
||||
)
|
||||
|
||||
def cc_external_rule_impl(ctx, attrs):
|
||||
""" Framework function for performing external C/C++ building.
|
||||
|
||||
To be used to build external libraries or/and binaries with CMake, configure/make, autotools etc.,
|
||||
and use results in Bazel.
|
||||
It is possible to use it to build a group of external libraries, that depend on each other or on
|
||||
Bazel library, and pass nessesary tools.
|
||||
|
||||
Accepts the actual commands for build configuration/execution in attrs.
|
||||
|
||||
Creates and runs a shell script, which:
|
||||
|
||||
1) prepares directory structure with sources, dependencies, and tools symlinked into subdirectories
|
||||
of the execroot directory. Adds tools into PATH.
|
||||
2) defines the correct absolute paths in tools with the script paths, see 7
|
||||
3) defines the following environment variables:
|
||||
EXT_BUILD_ROOT: execroot directory
|
||||
EXT_BUILD_DEPS: subdirectory of execroot, which contains the following subdirectories:
|
||||
|
||||
For cmake_external built dependencies:
|
||||
symlinked install directories of the dependencies
|
||||
|
||||
for Bazel built/imported dependencies:
|
||||
|
||||
include - here the include directories are symlinked
|
||||
lib - here the library files are symlinked
|
||||
lib/pkgconfig - here the pkgconfig files are symlinked
|
||||
bin - here the tools are copied
|
||||
INSTALLDIR: subdirectory of the execroot (named by the lib_name), where the library/binary
|
||||
will be installed
|
||||
|
||||
These variables should be used by the calling rule to refer to the created directory structure.
|
||||
4) calls 'attrs.create_configure_script'
|
||||
5) calls 'attrs.make_commands'
|
||||
6) calls 'attrs.postfix_script'
|
||||
7) replaces absolute paths in possibly created scripts with a placeholder value
|
||||
|
||||
Please see cmake.bzl for example usage.
|
||||
|
||||
Args:
|
||||
ctx: calling rule context
|
||||
attrs: attributes struct, created by create_attrs function above.
|
||||
Contains fields from CC_EXTERNAL_RULE_ATTRIBUTES (see descriptions there),
|
||||
two mandatory fields:
|
||||
- configure_name: name of the configuration tool, to be used in action mnemonic,
|
||||
- create_configure_script(ConfigureParameters): function that creates configuration
|
||||
script, accepts ConfigureParameters
|
||||
and some other fields provided by the rule, which have been passed to create_attrs.
|
||||
"""
|
||||
lib_name = attrs.lib_name or ctx.attr.name
|
||||
|
||||
inputs = _define_inputs(attrs)
|
||||
outputs = _define_outputs(ctx, attrs, lib_name)
|
||||
out_cc_info = _define_out_cc_info(ctx, attrs, inputs, outputs)
|
||||
|
||||
shell_utils = ctx.attr._utils.files.to_list()[0].path
|
||||
|
||||
env = _correct_path_variable(get_env_vars(ctx))
|
||||
set_envs = ""
|
||||
if not ctx.attr._target_os[OSInfo].is_osx:
|
||||
set_envs = "\n".join(["export {}=\"{}\"".format(key, env[key]) for key in env])
|
||||
|
||||
version_and_lib = "Bazel external C/C++ Rules #{}. Building library '{}'".format(VERSION, lib_name)
|
||||
|
||||
# We can not declare outputs of the action, which are in parent-child relashion,
|
||||
# so we need to have a (symlinked) copy of the output directory to provide
|
||||
# both the C/C++ artifacts - libraries, headers, and binaries,
|
||||
# and the install directory as a whole (which is mostly nessesary for chained external builds).
|
||||
#
|
||||
# We want the install directory output of this rule to have the same name as the library,
|
||||
# so symlink it under the same name but in a subdirectory
|
||||
installdir_copy = copy_directory(ctx.actions, "$INSTALLDIR", "copy_{}/{}".format(lib_name, lib_name))
|
||||
|
||||
# we need this fictive file in the root to get the path of the root in the script
|
||||
empty = fictive_file_in_genroot(ctx.actions, ctx.label.name)
|
||||
|
||||
define_variables = [
|
||||
set_envs,
|
||||
"set_platform_env_vars",
|
||||
"export EXT_BUILD_ROOT=$BUILD_PWD",
|
||||
"export BUILD_TMPDIR=$(mktemp -d)",
|
||||
"export EXT_BUILD_DEPS=$EXT_BUILD_ROOT/bazel_foreign_cc_deps_" + lib_name,
|
||||
"export INSTALLDIR=$EXT_BUILD_ROOT/" + empty.file.dirname + "/" + lib_name,
|
||||
]
|
||||
|
||||
trap_function = [
|
||||
"function cleanup() {",
|
||||
"local ecode=$?",
|
||||
"if [ $ecode -eq 0 ]; then",
|
||||
"echo \"rules_foreign_cc: Cleaning temp directories\"",
|
||||
"rm -rf $BUILD_TMPDIR $EXT_BUILD_ROOT/bazel_foreign_cc_deps_" + lib_name,
|
||||
"else",
|
||||
"echo \"\"",
|
||||
"echo \"rules_foreign_cc: Keeping temp build directory $BUILD_TMPDIR\
|
||||
and dependencies directory $EXT_BUILD_ROOT/bazel_foreign_cc_deps_" + lib_name + " for debug.\"",
|
||||
"echo \"rules_foreign_cc: Please note that the directories inside a sandbox are still\
|
||||
cleaned unless you specify '--sandbox_debug' Bazel command line flag.\"",
|
||||
"echo \"\"",
|
||||
"fi",
|
||||
"}",
|
||||
]
|
||||
|
||||
script_lines = [
|
||||
"echo \"\n{}\n\"".format(version_and_lib),
|
||||
"set -e",
|
||||
"source " + shell_utils,
|
||||
"\n".join(define_variables),
|
||||
"path $EXT_BUILD_ROOT",
|
||||
"\n".join(trap_function),
|
||||
"mkdir -p $EXT_BUILD_DEPS",
|
||||
"mkdir -p $INSTALLDIR",
|
||||
_print_env(),
|
||||
"trap \"cleanup\" EXIT",
|
||||
"\n".join(_copy_deps_and_tools(inputs)),
|
||||
# replace placeholder with the dependencies root
|
||||
"define_absolute_paths $EXT_BUILD_DEPS $EXT_BUILD_DEPS",
|
||||
"pushd $BUILD_TMPDIR",
|
||||
attrs.create_configure_script(ConfigureParameters(ctx = ctx, attrs = attrs, inputs = inputs)),
|
||||
"\n".join(attrs.make_commands),
|
||||
attrs.postfix_script or "",
|
||||
# replace references to the root directory when building ($BUILD_TMPDIR)
|
||||
# and the root where the dependencies were installed ($EXT_BUILD_DEPS)
|
||||
# for the results which are in $INSTALLDIR (with placeholder)
|
||||
"replace_absolute_paths $INSTALLDIR $BUILD_TMPDIR",
|
||||
"replace_absolute_paths $INSTALLDIR $EXT_BUILD_DEPS",
|
||||
installdir_copy.script,
|
||||
empty.script,
|
||||
"popd",
|
||||
]
|
||||
|
||||
script_text = "\n".join(script_lines)
|
||||
print("script text: " + script_text)
|
||||
|
||||
execution_requirements = {"block-network": ""}
|
||||
|
||||
rule_outputs = outputs.declared_outputs + [installdir_copy.file]
|
||||
|
||||
ctx.actions.run_shell(
|
||||
mnemonic = "Cc" + attrs.configure_name.capitalize() + "MakeRule",
|
||||
inputs = depset(inputs.declared_inputs) + ctx.attr._cc_toolchain.files,
|
||||
outputs = rule_outputs + [empty.file],
|
||||
tools = ctx.attr._utils.files,
|
||||
# We should take the default PATH passed by Bazel, not that from cc_toolchain
|
||||
# for Windows, because the PATH under msys2 is different and that is which we need
|
||||
# for shell commands
|
||||
use_default_shell_env = not ctx.attr._target_os[OSInfo].is_osx,
|
||||
command = script_text,
|
||||
execution_requirements = execution_requirements,
|
||||
# this is ignored if use_default_shell_env = True
|
||||
env = env,
|
||||
)
|
||||
|
||||
externally_built = ForeignCcArtifact(
|
||||
gen_dir = installdir_copy.file,
|
||||
bin_dir_name = attrs.out_bin_dir,
|
||||
lib_dir_name = attrs.out_lib_dir,
|
||||
include_dir_name = attrs.out_include_dir,
|
||||
)
|
||||
return [
|
||||
DefaultInfo(files = depset(direct = rule_outputs)),
|
||||
OutputGroupInfo(**_declare_output_groups(installdir_copy.file, outputs.out_binary_files)),
|
||||
ForeignCcDeps(artifacts = depset(
|
||||
[externally_built],
|
||||
transitive = _get_transitive_artifacts(attrs.deps),
|
||||
)),
|
||||
cc_common.create_cc_skylark_info(ctx = ctx),
|
||||
out_cc_info.compilation_info,
|
||||
out_cc_info.linking_info,
|
||||
]
|
||||
|
||||
def _declare_output_groups(installdir, outputs):
|
||||
dict_ = {}
|
||||
dict_["gen_dir"] = depset([installdir])
|
||||
for output in outputs:
|
||||
dict_[output.basename] = [output]
|
||||
return dict_
|
||||
|
||||
def _get_transitive_artifacts(deps):
|
||||
artifacts = []
|
||||
for dep in deps:
|
||||
foreign_dep = get_foreign_cc_dep(dep)
|
||||
if foreign_dep:
|
||||
artifacts += [foreign_dep.artifacts]
|
||||
return artifacts
|
||||
|
||||
def _print_env():
|
||||
return "\n".join([
|
||||
"echo \"Environment:______________\"",
|
||||
"env",
|
||||
"echo \"__________________________\"",
|
||||
])
|
||||
|
||||
def _correct_path_variable(env):
|
||||
value = env.get("PATH", "")
|
||||
if not value:
|
||||
return env
|
||||
value = env.get("PATH", "").replace("C:\\", "/c/")
|
||||
value = value.replace("\\", "/")
|
||||
value = value.replace(";", ":")
|
||||
env["PATH"] = "$PATH:" + value
|
||||
return env
|
||||
|
||||
def _depset(item):
|
||||
if item == None:
|
||||
return depset()
|
||||
return depset([item])
|
||||
|
||||
def _list(item):
|
||||
if item:
|
||||
return [item]
|
||||
return []
|
||||
|
||||
def _copy_deps_and_tools(files):
|
||||
lines = []
|
||||
lines += _symlink_to_dir("lib", files.libs, False)
|
||||
lines += _symlink_to_dir("include", files.headers + files.include_dirs, True)
|
||||
|
||||
lines += _symlink_to_dir("bin", files.tools_files, False)
|
||||
|
||||
for ext_dir in files.ext_build_dirs:
|
||||
lines += ["symlink_to_dir $EXT_BUILD_ROOT/{} $EXT_BUILD_DEPS".format(_file_path(ext_dir))]
|
||||
|
||||
lines += ["if [ -d $EXT_BUILD_DEPS/bin ]; then"]
|
||||
|
||||
lines += [" tools=$(find $EXT_BUILD_DEPS/bin -maxdepth 1 -mindepth 1)"]
|
||||
lines += [" for tool in $tools;"]
|
||||
lines += [" do"]
|
||||
lines += [" if [[ -d \"$tool\" ]] || [[ -L \"$tool\" ]]; then"]
|
||||
lines += [" export PATH=$PATH:$tool"]
|
||||
lines += [" fi"]
|
||||
lines += [" done"]
|
||||
lines += ["fi"]
|
||||
lines += ["path $EXT_BUILD_DEPS/bin"]
|
||||
|
||||
return lines
|
||||
|
||||
def _symlink_to_dir(dir_name, files_list, link_children):
|
||||
if len(files_list) == 0:
|
||||
return []
|
||||
lines = ["mkdir -p $EXT_BUILD_DEPS/" + dir_name]
|
||||
|
||||
paths_list = []
|
||||
for file in files_list:
|
||||
paths_list += [_file_path(file)]
|
||||
|
||||
link_function = "symlink_contents_to_dir" if link_children else "symlink_to_dir"
|
||||
for path in paths_list:
|
||||
lines += ["{} $EXT_BUILD_ROOT/{} $EXT_BUILD_DEPS/{}".format(link_function, path, dir_name)]
|
||||
|
||||
return lines
|
||||
|
||||
def _file_path(file):
|
||||
return file if type(file) == "string" else file.path
|
||||
|
||||
def _check_file_name(var, name):
|
||||
if (len(var) == 0):
|
||||
fail("{} can not be empty string.".format(name.capitalize()))
|
||||
|
||||
if (not var[0:1].isalpha()):
|
||||
fail("{} should start with a letter.".format(name.capitalize()))
|
||||
for index in range(1, len(var) - 1):
|
||||
letter = var[index]
|
||||
if not letter.isalnum() and letter != "_":
|
||||
fail("{} should be alphanumeric or '_'.".format(name.capitalize()))
|
||||
|
||||
_Outputs = provider(
|
||||
doc = "Provider to keep different kinds of the external build output files and directories",
|
||||
fields = dict(
|
||||
out_include_dir = "Directory with header files (relative to install directory)",
|
||||
out_binary_files = "Binary files, which will be created by the action",
|
||||
libraries = "Library files, which will be created by the action",
|
||||
declared_outputs = "All output files and directories of the action",
|
||||
),
|
||||
)
|
||||
|
||||
def _define_outputs(ctx, attrs, lib_name):
|
||||
static_libraries = []
|
||||
if not hasattr(attrs, "headers_only") or not attrs.headers_only:
|
||||
if (not (hasattr(attrs, "static_libraries") and len(attrs.static_libraries) > 0) and
|
||||
not (hasattr(attrs, "shared_libraries") and len(attrs.shared_libraries) > 0) and
|
||||
not (hasattr(attrs, "interface_libraries") and len(attrs.interface_libraries) > 0) and
|
||||
not (hasattr(attrs, "binaries") and len(attrs.binaries) > 0)):
|
||||
static_libraries = [lib_name + (".lib" if targets_windows(ctx, None) else ".a")]
|
||||
else:
|
||||
static_libraries = attrs.static_libraries
|
||||
|
||||
_check_file_name(lib_name, "Library name")
|
||||
|
||||
out_include_dir = ctx.actions.declare_directory(lib_name + "/" + attrs.out_include_dir)
|
||||
|
||||
out_binary_files = _declare_out(ctx, lib_name, attrs.out_bin_dir, attrs.binaries)
|
||||
|
||||
libraries = LibrariesToLinkInfo(
|
||||
static_libraries = _declare_out(ctx, lib_name, attrs.out_lib_dir, static_libraries),
|
||||
shared_libraries = _declare_out(ctx, lib_name, attrs.out_lib_dir, attrs.shared_libraries),
|
||||
interface_libraries = _declare_out(ctx, lib_name, attrs.out_lib_dir, attrs.interface_libraries),
|
||||
)
|
||||
declared_outputs = [out_include_dir] + out_binary_files
|
||||
declared_outputs += libraries.static_libraries
|
||||
declared_outputs += libraries.shared_libraries + libraries.interface_libraries
|
||||
|
||||
return _Outputs(
|
||||
out_include_dir = out_include_dir,
|
||||
out_binary_files = out_binary_files,
|
||||
libraries = libraries,
|
||||
declared_outputs = declared_outputs,
|
||||
)
|
||||
|
||||
def _declare_out(ctx, lib_name, dir_, files):
|
||||
if files and len(files) > 0:
|
||||
return [ctx.actions.declare_file("/".join([lib_name, dir_, file])) for file in files]
|
||||
return []
|
||||
|
||||
InputFiles = provider(
|
||||
doc = """Provider to keep different kinds of input files, directories,
|
||||
and C/C++ compilation and linking info from dependencies""",
|
||||
fields = dict(
|
||||
headers = """Include files built by Bazel. Will be copied into $EXT_BUILD_DEPS/include.""",
|
||||
include_dirs = """Include directories built by Bazel.
|
||||
Will be copied into $EXT_BUILD_DEPS/include.""",
|
||||
libs = """Library files built by Bazel.
|
||||
Will be copied into $EXT_BUILD_DEPS/lib.""",
|
||||
tools_files = """Files and directories with tools needed for configuration/building
|
||||
to be copied into the bin folder, which is added to the PATH""",
|
||||
ext_build_dirs = """Directories with libraries, built by framework function.
|
||||
This directories should be copied into $EXT_BUILD_DEPS/lib-name as is, with all contents.""",
|
||||
deps_compilation_info = "Merged CcCompilationInfo from deps attribute",
|
||||
deps_linking_info = "Merged CcLinkingInfo from deps attribute",
|
||||
declared_inputs = "All files and directories that must be declared as action inputs",
|
||||
),
|
||||
)
|
||||
|
||||
def _define_inputs(attrs):
|
||||
compilation_infos_all = []
|
||||
linking_infos_all = []
|
||||
|
||||
bazel_headers = []
|
||||
bazel_system_includes = []
|
||||
bazel_libs = []
|
||||
|
||||
# This framework function-built libraries: copy result directories under
|
||||
# $EXT_BUILD_DEPS/lib-name
|
||||
ext_build_dirs = []
|
||||
ext_build_dirs_set = {}
|
||||
|
||||
for dep in attrs.deps:
|
||||
external_deps = get_foreign_cc_dep(dep)
|
||||
|
||||
linking_infos_all += [dep[CcLinkingInfo]]
|
||||
compilation_infos_all += [dep[CcCompilationInfo]]
|
||||
|
||||
if external_deps:
|
||||
for artifact in external_deps.artifacts:
|
||||
if not ext_build_dirs_set.get(artifact.gen_dir):
|
||||
ext_build_dirs_set[artifact.gen_dir] = 1
|
||||
ext_build_dirs += [artifact.gen_dir]
|
||||
else:
|
||||
headers_info = _get_headers(dep[CcCompilationInfo])
|
||||
bazel_headers += headers_info.headers
|
||||
bazel_system_includes += headers_info.include_dirs
|
||||
bazel_libs += _collect_libs(dep[CcLinkingInfo])
|
||||
|
||||
tools_roots = []
|
||||
tools_files = []
|
||||
for tool in attrs.tools_deps:
|
||||
tool_root = detect_root(tool)
|
||||
tools_roots += [tool_root]
|
||||
for file_list in tool.files:
|
||||
tools_files += _list(file_list)
|
||||
|
||||
for tool in attrs.additional_tools:
|
||||
for file_list in tool.files:
|
||||
tools_files += _list(file_list)
|
||||
|
||||
# These variables are needed for correct C/C++ providers constraction,
|
||||
# they should contain all libraries and include directories.
|
||||
deps_compilation = cc_common.merge_cc_compilation_infos(cc_compilation_infos = compilation_infos_all)
|
||||
deps_linking = cc_common.merge_cc_linking_infos(cc_linking_infos = linking_infos_all)
|
||||
|
||||
return InputFiles(
|
||||
headers = bazel_headers,
|
||||
include_dirs = bazel_system_includes,
|
||||
libs = bazel_libs,
|
||||
tools_files = tools_roots,
|
||||
deps_compilation_info = deps_compilation,
|
||||
deps_linking_info = deps_linking,
|
||||
ext_build_dirs = ext_build_dirs,
|
||||
declared_inputs = depset(attrs.lib_source.files) + bazel_libs + tools_files +
|
||||
attrs.additional_inputs + deps_compilation.headers + ext_build_dirs,
|
||||
)
|
||||
|
||||
def get_foreign_cc_dep(dep):
|
||||
return dep[ForeignCcDeps] if ForeignCcDeps in dep else None
|
||||
|
||||
# consider optimization here to do not iterate both collections
|
||||
def _get_headers(compilation_info):
|
||||
include_dirs = collections.uniq(compilation_info.system_includes.to_list())
|
||||
headers = []
|
||||
for header in compilation_info.headers:
|
||||
path = header.path
|
||||
included = False
|
||||
for dir_ in include_dirs:
|
||||
if path.startswith(dir_):
|
||||
included = True
|
||||
break
|
||||
if not included:
|
||||
headers += [header]
|
||||
return struct(
|
||||
headers = headers,
|
||||
include_dirs = include_dirs,
|
||||
)
|
||||
|
||||
def _define_out_cc_info(ctx, attrs, inputs, outputs):
|
||||
compilation_info = CcCompilationInfo(
|
||||
headers = depset([outputs.out_include_dir]),
|
||||
system_includes = depset([outputs.out_include_dir.path]),
|
||||
defines = depset(attrs.defines),
|
||||
)
|
||||
out_compilation_info = cc_common.merge_cc_compilation_infos(
|
||||
cc_compilation_infos = [inputs.deps_compilation_info, compilation_info],
|
||||
)
|
||||
|
||||
linking_info = create_linking_info(ctx, depset(direct = attrs.linkopts), outputs.libraries)
|
||||
out_linking_info = cc_common.merge_cc_linking_infos(
|
||||
cc_linking_infos = [linking_info, inputs.deps_linking_info],
|
||||
)
|
||||
|
||||
return struct(
|
||||
compilation_info = out_compilation_info,
|
||||
linking_info = out_linking_info,
|
||||
)
|
||||
|
||||
def _extract_link_params(cc_linking):
|
||||
return [
|
||||
cc_linking.static_mode_params_for_dynamic_library,
|
||||
cc_linking.static_mode_params_for_executable,
|
||||
cc_linking.dynamic_mode_params_for_dynamic_library,
|
||||
cc_linking.dynamic_mode_params_for_executable,
|
||||
]
|
||||
|
||||
def _collect_libs(cc_linking):
|
||||
libs = []
|
||||
for params in _extract_link_params(cc_linking):
|
||||
libs += [lib.artifact() for lib in params.libraries_to_link]
|
||||
libs += params.dynamic_libraries_for_runtime.to_list()
|
||||
return collections.uniq(libs)
|
Loading…
Reference in a new issue