build cmake if it is missing (should be configurable) (#57)

This commit is contained in:
irengrig 2018-08-22 22:06:37 +02:00 committed by GitHub
parent 322e81086b
commit d4880f8fac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 169 additions and 53 deletions

View File

@ -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",
],
)

View File

@ -0,0 +1,6 @@
load("//tools/build_defs:cmake_build.bzl", "cmake_tool")
cmake_tool(
name = "cmaketool",
cmake_srcs = "@cmake//:all",
)

View File

@ -3,5 +3,7 @@ exports_files(
"utils.sh",
"cmake.bzl",
"framework.bzl",
"ninja_build.bzl",
"cmake_build.bzl",
],
)

View File

@ -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

View File

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

View File

@ -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("/")

View File

@ -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("/")

View File

@ -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",
])

View File

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