build cmake if it is missing (should be configurable) (#57)
This commit is contained in:
parent
322e81086b
commit
d4880f8fac
|
@ -131,3 +131,12 @@ http_archive(
|
|||
"https://github.com/nghttp2/nghttp2/archive/e5b3f9addd49bca27e2f99c5c65a564eb5c0cf6d.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "cmake",
|
||||
build_file_content = all_content,
|
||||
strip_prefix = "CMake-3.12.1",
|
||||
urls = [
|
||||
"https://github.com/Kitware/CMake/archive/v3.12.1.tar.gz",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
load("//tools/build_defs:cmake_build.bzl", "cmake_tool")
|
||||
|
||||
cmake_tool(
|
||||
name = "cmaketool",
|
||||
cmake_srcs = "@cmake//:all",
|
||||
)
|
|
@ -3,5 +3,7 @@ exports_files(
|
|||
"utils.sh",
|
||||
"cmake.bzl",
|
||||
"framework.bzl",
|
||||
"ninja_build.bzl",
|
||||
"cmake_build.bzl",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -6,9 +6,13 @@ load(
|
|||
"CC_EXTERNAL_RULE_ATTRIBUTES",
|
||||
"cc_external_rule_impl",
|
||||
"create_attrs",
|
||||
)
|
||||
load(
|
||||
"//tools/build_defs:detect_root.bzl",
|
||||
"detect_root",
|
||||
)
|
||||
load("//tools/build_defs:cc_toolchain_util.bzl", "absolutize_path_in_str", "getFlagsInfo", "getToolsInfo")
|
||||
load("@foreign_cc_platform_utils//:cmake_globals.bzl", "CMAKE_COMMAND", "CMAKE_DEPS")
|
||||
|
||||
def _cmake_external(ctx):
|
||||
options = " ".join(ctx.attr.cmake_options)
|
||||
|
@ -22,7 +26,7 @@ def _cmake_external(ctx):
|
|||
|
||||
cmake_string = " ".join([
|
||||
" ".join(_get_toolchain_variables(ctx, tools, flags)),
|
||||
" cmake",
|
||||
" " + CMAKE_COMMAND,
|
||||
" ".join(cache_entries),
|
||||
"-DCMAKE_PREFIX_PATH=\"$EXT_BUILD_DEPS\"",
|
||||
"-DCMAKE_INSTALL_PREFIX=\"{}\"".format(install_prefix),
|
||||
|
@ -31,11 +35,13 @@ def _cmake_external(ctx):
|
|||
])
|
||||
copy_results = "copy_dir_contents_to_dir $TMPDIR/{} $INSTALLDIR".format(install_prefix)
|
||||
|
||||
tools_deps = ctx.attr.tools_deps + [ctx.attr._cmake_dep]
|
||||
attrs = create_attrs(
|
||||
ctx.attr,
|
||||
configure_name = "CMake",
|
||||
configure_script = cmake_string,
|
||||
postfix_script = copy_results + "\n" + ctx.attr.postfix_script,
|
||||
tools_deps = tools_deps,
|
||||
)
|
||||
|
||||
return cc_external_rule_impl(ctx, attrs)
|
||||
|
@ -143,6 +149,12 @@ def _attrs():
|
|||
"env_vars": attr.string_dict(mandatory = False, default = {}),
|
||||
# Other CMake options
|
||||
"cmake_options": attr.string_list(mandatory = False, default = []),
|
||||
"_cmake_dep": attr.label(
|
||||
default = "@foreign_cc_platform_utils//:cmake",
|
||||
cfg = "target",
|
||||
allow_files = True,
|
||||
# allow_single_file = True,
|
||||
),
|
||||
})
|
||||
return attrs
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
load(":detect_root.bzl", "detect_root")
|
||||
|
||||
def _cmake_tool(ctx):
|
||||
root = detect_root(ctx.attr.cmake_srcs)
|
||||
|
||||
cmake = ctx.actions.declare_directory("cmake")
|
||||
script_text = "\n".join([
|
||||
"BUILD_DIR=$(pwd)",
|
||||
"export TMPDIR=$(mktemp -d)",
|
||||
"cp -R ./{}/. $TMPDIR".format(root),
|
||||
"mkdir " + cmake.path,
|
||||
"pushd $TMPDIR",
|
||||
"./bootstrap --prefix=install",
|
||||
"make install",
|
||||
"cp -a ./install/. $BUILD_DIR/" + cmake.path,
|
||||
"popd",
|
||||
])
|
||||
|
||||
ctx.actions.run_shell(
|
||||
mnemonic = "BootstrapCMake",
|
||||
inputs = ctx.attr.cmake_srcs.files,
|
||||
outputs = [cmake],
|
||||
tools = [],
|
||||
use_default_shell_env = True,
|
||||
command = script_text,
|
||||
execution_requirements = {"block-network": ""},
|
||||
)
|
||||
|
||||
return [DefaultInfo(files = depset([cmake]))]
|
||||
|
||||
cmake_tool = rule(
|
||||
attrs = {
|
||||
"cmake_srcs": attr.label(mandatory = True),
|
||||
},
|
||||
fragments = ["cpp"],
|
||||
output_to_genfiles = True,
|
||||
implementation = _cmake_tool,
|
||||
)
|
|
@ -0,0 +1,48 @@
|
|||
def detect_root(source):
|
||||
"""Detects the path to the topmost directory of the 'source' outputs.
|
||||
To be used with external build systems to point to the source code/tools directories.
|
||||
|
||||
If the target groups the sources of the external dependency, the workspace root is used,
|
||||
and no other checks are performed (i.e. it is assumed that the whole contents of the external
|
||||
dependency is used).
|
||||
Otherwise, for the "usual" targets, target's files are iterated and the path with the least length
|
||||
is selected.
|
||||
"""
|
||||
|
||||
# root = source.label.workspace_root
|
||||
root = ""
|
||||
sources = source.files
|
||||
if (root and len(root) > 0) or len(sources) == 0:
|
||||
return root
|
||||
|
||||
root = ""
|
||||
level = -1
|
||||
num_at_level = 0
|
||||
|
||||
# find topmost directory
|
||||
for file in sources:
|
||||
file_level = _get_level(file.path)
|
||||
if level == -1 or level > file_level:
|
||||
root = file.path
|
||||
level = file_level
|
||||
num_at_level = 1
|
||||
elif level == file_level:
|
||||
num_at_level += 1
|
||||
|
||||
if num_at_level == 1:
|
||||
return root
|
||||
|
||||
(before, sep, after) = root.rpartition("/")
|
||||
if before and sep and after:
|
||||
return before
|
||||
return root
|
||||
|
||||
def _get_level(path):
|
||||
normalized = path
|
||||
for i in range(len(path)):
|
||||
new_normalized = normalized.replace("//", "/")
|
||||
if len(new_normalized) == len(normalized):
|
||||
break
|
||||
normalized = new_normalized
|
||||
|
||||
return normalized.count("/")
|
|
@ -9,6 +9,7 @@ load(
|
|||
"create_linking_info",
|
||||
"targets_windows",
|
||||
)
|
||||
load("//tools/build_defs:detect_root.bzl", "detect_root")
|
||||
|
||||
""" Dict with definitions of the context attributes, that customize cc_external_rule_impl function.
|
||||
Many of the attributes have default values.
|
||||
|
@ -464,50 +465,3 @@ def _collect_flags(cc_linking):
|
|||
for params in _extract_link_params(cc_linking):
|
||||
linkopts = params.linkopts.to_list()
|
||||
return collections.uniq(linkopts)
|
||||
|
||||
def detect_root(source):
|
||||
"""Detects the path to the topmost directory of the 'source' outputs.
|
||||
To be used with external build systems to point to the source code/tools directories.
|
||||
|
||||
If the target groups the sources of the external dependency, the workspace root is used,
|
||||
and no other checks are performed (i.e. it is assumed that the whole contents of the external
|
||||
dependency is used).
|
||||
Otherwise, for the "usual" targets, target's files are iterated and the path with the least length
|
||||
is selected.
|
||||
"""
|
||||
root = source.label.workspace_root
|
||||
sources = source.files
|
||||
if (root and len(root) > 0) or len(sources) == 0:
|
||||
return root
|
||||
|
||||
root = ""
|
||||
level = -1
|
||||
num_at_level = 0
|
||||
|
||||
# find topmost directory
|
||||
for file in sources:
|
||||
file_level = _get_level(file.path)
|
||||
if level == -1 or level > file_level:
|
||||
root = file.path
|
||||
level = file_level
|
||||
num_at_level = 1
|
||||
elif level == file_level:
|
||||
num_at_level += 1
|
||||
|
||||
if num_at_level == 1:
|
||||
return root
|
||||
|
||||
(before, sep, after) = root.rpartition("/")
|
||||
if before and sep and after:
|
||||
return before
|
||||
return root
|
||||
|
||||
def _get_level(path):
|
||||
normalized = path
|
||||
for i in range(len(path)):
|
||||
new_normalized = normalized.replace("//", "/")
|
||||
if len(new_normalized) == len(normalized):
|
||||
break
|
||||
normalized = new_normalized
|
||||
|
||||
return normalized.count("/")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
load("//tools/build_defs:framework.bzl", "detect_root")
|
||||
load("//tools/build_defs:detect_root.bzl", "detect_root")
|
||||
|
||||
def _ninja_tool(ctx):
|
||||
root = detect_root(ctx.attr.ninja_srcs)
|
||||
|
@ -6,9 +6,8 @@ def _ninja_tool(ctx):
|
|||
ninja = ctx.actions.declare_directory("ninja")
|
||||
script_text = "\n".join([
|
||||
"mkdir " + ninja.path,
|
||||
"cp -r ./{}/** {}".format(root, ninja.path),
|
||||
"cp -R ./{}/. {}".format(root, ninja.path),
|
||||
"cd " + ninja.path,
|
||||
"pwd",
|
||||
"./configure.py --bootstrap",
|
||||
])
|
||||
|
||||
|
|
|
@ -8,14 +8,62 @@ def _define_shell_utils_impl(rctx):
|
|||
if os_name.find("windows") != -1:
|
||||
utils_name = "utils_win.bat"
|
||||
fail("Not supported yet!")
|
||||
rctx.file("WORKSPACE", "workspace(name='foreign_cc_platform_utils')")
|
||||
|
||||
existing_cmake = rctx.which("cmake")
|
||||
|
||||
is_ci = rctx.os.environ.get("CI")
|
||||
print("IS_CI: " + str(is_ci))
|
||||
|
||||
cmake_globals_text = ""
|
||||
cmake_text = ""
|
||||
if existing_cmake != None:
|
||||
cmake_globals_text = """
|
||||
CMAKE_COMMAND="cmake"
|
||||
CMAKE_DEPS=[]
|
||||
"""
|
||||
cmake_text = """
|
||||
sh_library(
|
||||
name = "cmake",
|
||||
visibility = ["//visibility:public"]
|
||||
)
|
||||
"""
|
||||
else:
|
||||
path_to_cmake_build = rctx.path(Label("//tools/build_defs:cmake_build.bzl"))
|
||||
rctx.template("cmake_build.bzl", path_to_cmake_build)
|
||||
|
||||
path_to_detect_root = rctx.path(Label("//tools/build_defs:detect_root.bzl"))
|
||||
rctx.template("detect_root.bzl", path_to_detect_root)
|
||||
|
||||
cmake_globals_text = """
|
||||
CMAKE_COMMAND="$EXT_BUILD_DEPS/bin/cmake/bin/cmake"
|
||||
CMAKE_DEPS=[Label("@foreign_cc_platform_utils//:cmake")]
|
||||
"""
|
||||
cmake_text = """
|
||||
sh_library(
|
||||
name = "cmake",
|
||||
srcs = [":cmake_externally_built"],
|
||||
visibility = ["//visibility:public"]
|
||||
)
|
||||
|
||||
load("//:cmake_build.bzl", "cmake_tool")
|
||||
cmake_tool(
|
||||
name = "cmake_externally_built",
|
||||
cmake_srcs = "@cmake//:all"
|
||||
)
|
||||
"""
|
||||
|
||||
rctx.file("cmake_globals.bzl", cmake_globals_text)
|
||||
|
||||
rctx.file("WORKSPACE", """workspace(name='foreign_cc_platform_utils')""")
|
||||
|
||||
rctx.file("BUILD.bazel", """
|
||||
sh_library(
|
||||
name = "shell_utils",
|
||||
srcs = ["{}"],
|
||||
visibility = ["//visibility:public"]
|
||||
)
|
||||
""".format(utils_name))
|
||||
""".format(utils_name) + cmake_text)
|
||||
|
||||
path = rctx.path(Label("//tools/build_defs:" + utils_name))
|
||||
rctx.template(utils_name, path, executable = True)
|
||||
|
||||
|
|
Loading…
Reference in New Issue