Improve outputs handling: wrapper script in shell-abstract manner (#223)

* Improve outputs handling: wrapper script in shell-abstract manner

- extract wrapper script creation into a separate function,
- simplify the script and log names, also output the wrapper script text,
- introduce more shell primitives

related to #204

* Correct review comments
This commit is contained in:
irengrig 2019-02-14 10:00:19 +01:00 committed by GitHub
parent d8e78e4cf0
commit 4d73887da8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 386 additions and 129 deletions

View File

@ -109,16 +109,22 @@ done
"""
return FunctionAndCall(text = text)
def cleanup_function(message_cleaning, message_keeping):
def cat(filepath):
return "cat \"{}\"".format(filepath)
def redirect_out_err(from_process, to_file):
return from_process + " &> " + to_file
def assert_script_errors():
return "set -e"
def cleanup_function(on_success, on_failure):
text = "\n".join([
"local ecode=$?",
"if [ $ecode -eq 0 ]; then",
"printf \"%s\"" % message_cleaning,
"rm -rf $BUILD_TMPDIR $EXT_BUILD_DEPS",
on_success,
"else",
"printf \"\"",
"printf \"%s\"" % message_keeping,
"printf \"\"",
on_failure,
"fi",
])
return FunctionAndCall(text = text, call = "trap \"cleanup_function\" EXIT")

View File

@ -12,8 +12,17 @@ load(
"targets_windows",
)
load("@rules_foreign_cc//tools/build_defs:detect_root.bzl", "detect_root")
load("@rules_foreign_cc//tools/build_defs:run_shell_file_utils.bzl", "copy_directory", "fictive_file_in_genroot")
load("@rules_foreign_cc//tools/build_defs:shell_script_helper.bzl", "convert_shell_script", "os_name")
load(
"@rules_foreign_cc//tools/build_defs:run_shell_file_utils.bzl",
"copy_directory",
"fictive_file_in_genroot",
)
load(
"@rules_foreign_cc//tools/build_defs:shell_script_helper.bzl",
"convert_shell_script",
"create_function",
"os_name",
)
""" Dict with definitions of the context attributes, that customize cc_external_rule_impl function.
Many of the attributes have default values.
@ -205,7 +214,7 @@ def cc_external_rule_impl(ctx, attrs):
if execution_os_name != "osx":
set_cc_envs = "\n".join(["export {}=\"{}\"".format(key, cc_env[key]) for key in cc_env])
version_and_lib = "Bazel external C/C++ Rules #{}. Building library '{}'".format(VERSION, lib_name)
version_and_lib = "Bazel external C/C++ Rules #{}. Building library '{}'\\n".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
@ -227,14 +236,6 @@ def cc_external_rule_impl(ctx, attrs):
"export INSTALLDIR=$$EXT_BUILD_ROOT$$/" + empty.file.dirname + "/" + lib_name,
]
trap_function = "\n".join([
"export CLEANUP_MSG=\"rules_foreign_cc: Cleaning temp directories\"",
"export KEEP_MSG=\"rules_foreign_cc: Keeping temp build directory $$BUILD_TMPDIR$$\
and dependencies directory $$EXT_BUILD_DEPS$$ for debug.\\nrules_foreign_cc: Please note that the directories inside a sandbox are still\
cleaned unless you specify '--sandbox_debug' Bazel command line flag.\"",
"##cleanup_function## \"$$CLEANUP_MSG$$\" \"$$KEEP_MSG$$\"",
])
script_lines = [
"##echo## \"\"",
"##echo## \"{}\"".format(version_and_lib),
@ -245,9 +246,6 @@ def cc_external_rule_impl(ctx, attrs):
"##mkdirs## $$EXT_BUILD_DEPS$$",
"##mkdirs## $$INSTALLDIR$$",
_print_env(),
# the call trap is defined inside, in a way how the shell function should be called
# see, for instance, linux_commands.bzl
trap_function,
"\n".join(_copy_deps_and_tools(inputs)),
# replace placeholder with the dependencies root
"##define_absolute_paths## $$EXT_BUILD_DEPS$$ $$EXT_BUILD_DEPS$$",
@ -266,22 +264,24 @@ def cc_external_rule_impl(ctx, attrs):
]
script_text = convert_shell_script(ctx, script_lines)
print("script text: " + script_text)
execution_requirements = {"block-network": ""}
wrapped_outputs = wrap_outputs(ctx, lib_name, attrs.configure_name, script_text)
rule_outputs = outputs.declared_outputs + [installdir_copy.file]
ctx.actions.run_shell(
mnemonic = "Cc" + attrs.configure_name.capitalize() + "MakeRule",
inputs = inputs.declared_inputs + ctx.attr._cc_toolchain.files.to_list(),
outputs = rule_outputs + [empty.file],
inputs = depset(inputs.declared_inputs, transitive = [ctx.attr._cc_toolchain.files]),
outputs = rule_outputs + [
empty.file,
wrapped_outputs.log_file,
],
tools = [wrapped_outputs.script_file],
# 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 = execution_os_name != "osx",
command = script_text,
execution_requirements = execution_requirements,
command = wrapped_outputs.wrapper_script,
execution_requirements = {"block-network": ""},
# this is ignored if use_default_shell_env = True
env = cc_env,
)
@ -292,9 +292,16 @@ def cc_external_rule_impl(ctx, attrs):
lib_dir_name = attrs.out_lib_dir,
include_dir_name = attrs.out_include_dir,
)
output_groups = _declare_output_groups(installdir_copy.file, outputs.out_binary_files)
wrapped_files = [
wrapped_outputs.script_file,
wrapped_outputs.log_file,
wrapped_outputs.wrapper_script_file,
]
output_groups[attrs.configure_name + "_logs"] = wrapped_files
return [
DefaultInfo(files = depset(direct = rule_outputs)),
OutputGroupInfo(**_declare_output_groups(installdir_copy.file, outputs.out_binary_files)),
DefaultInfo(files = depset(direct = rule_outputs + wrapped_files)),
OutputGroupInfo(**output_groups),
ForeignCcDeps(artifacts = depset(
[externally_built],
transitive = _get_transitive_artifacts(attrs.deps),
@ -305,6 +312,76 @@ def cc_external_rule_impl(ctx, attrs):
),
]
WrappedOutputs = provider(
doc = "Structure for passing the log and scripts file information, and wrapper script text.",
fields = {
"script_file": "Main script file",
"log_file": "Execution log file",
"wrapper_script_file": "Wrapper script file (output for debugging purposes)",
"wrapper_script": "Wrapper script text to execute",
},
)
def wrap_outputs(ctx, lib_name, configure_name, script_text):
build_script_file = ctx.actions.declare_file("{}/logs/{}_script.sh".format(lib_name, configure_name))
ctx.actions.write(
output = build_script_file,
content = script_text,
is_executable = True,
)
build_log_file = ctx.actions.declare_file("{}/logs/{}.log".format(lib_name, configure_name))
cleanup_on_success_function = create_function(
ctx,
"cleanup_on_success",
"""##echo## \"rules_foreign_cc: Cleaning temp directories\"
rm -rf $BUILD_TMPDIR $EXT_BUILD_DEPS""",
)
cleanup_on_failure_function = create_function(
ctx,
"cleanup_on_failure",
"""##echo## "\\nrules_foreign_cc: Build failed!\
\\nrules_foreign_cc: Keeping temp build directory $$BUILD_TMPDIR$$ and dependencies directory\
$$EXT_BUILD_DEPS$$ for debug.\\nrules_foreign_cc:\
Please note that the directories inside a sandbox are still\
cleaned unless you specify '--sandbox_debug' Bazel command line flag.\\n\\n\
rules_foreign_cc: Printing build logs:\\n\\n_____ BEGIN BUILD LOGS _____\\n"
##cat## $$BUILD_LOG$$
##echo## "\\n_____ END BUILD LOGS _____\\n"
##echo## "rules_foreign_cc: Build script location: $$BUILD_SCRIPT$$\\n"
##echo## "rules_foreign_cc: Build log location: $$BUILD_LOG$$\\n\\n"
""",
)
trap_function = "##cleanup_function## cleanup_on_success cleanup_on_failure"
build_command_lines = [
"##assert_script_errors##",
cleanup_on_success_function,
cleanup_on_failure_function,
# the call trap is defined inside, in a way how the shell function should be called
# see, for instance, linux_commands.bzl
trap_function,
"export BUILD_SCRIPT=\"{}\"".format(build_script_file.path),
"export BUILD_LOG=\"{}\"".format(build_log_file.path),
# sometimes the log file is not created, we do not want our script to fail because of this
"##touch## $$BUILD_LOG$$",
"##redirect_out_err## $$BUILD_SCRIPT$$ $$BUILD_LOG$$",
]
build_command = convert_shell_script(ctx, build_command_lines)
wrapper_script_file = ctx.actions.declare_file("{}/logs/wrapper_script.sh".format(lib_name))
ctx.actions.write(
output = wrapper_script_file,
content = build_command,
)
return WrappedOutputs(
script_file = build_script_file,
log_file = build_log_file,
wrapper_script_file = wrapper_script_file,
wrapper_script = build_command,
)
def _declare_output_groups(installdir, outputs):
dict_ = {}
dict_["gen_dir"] = depset([installdir])

View File

@ -12,8 +12,17 @@ load(
"targets_windows",
)
load("@rules_foreign_cc//tools/build_defs:detect_root.bzl", "detect_root")
load("@rules_foreign_cc//tools/build_defs:run_shell_file_utils.bzl", "copy_directory", "fictive_file_in_genroot")
load("@rules_foreign_cc//tools/build_defs:shell_script_helper.bzl", "convert_shell_script", "os_name")
load(
"@rules_foreign_cc//tools/build_defs:run_shell_file_utils.bzl",
"copy_directory",
"fictive_file_in_genroot",
)
load(
"@rules_foreign_cc//tools/build_defs:shell_script_helper.bzl",
"convert_shell_script",
"create_function",
"os_name",
)
""" Dict with definitions of the context attributes, that customize cc_external_rule_impl function.
Many of the attributes have default values.
@ -205,7 +214,7 @@ def cc_external_rule_impl(ctx, attrs):
if execution_os_name != "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)
version_and_lib = "Bazel external C/C++ Rules #{}. Building library '{}'\\n".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
@ -227,14 +236,6 @@ def cc_external_rule_impl(ctx, attrs):
"export INSTALLDIR=$$EXT_BUILD_ROOT$$/" + empty.file.dirname + "/" + lib_name,
]
trap_function = "\n".join([
"export CLEANUP_MSG=\"rules_foreign_cc: Cleaning temp directories\"",
"export KEEP_MSG=\"rules_foreign_cc: Keeping temp build directory $$BUILD_TMPDIR$$\
and dependencies directory $$EXT_BUILD_DEPS$$ for debug.\\nrules_foreign_cc: Please note that the directories inside a sandbox are still\
cleaned unless you specify '--sandbox_debug' Bazel command line flag.\"",
"##cleanup_function## \"$$CLEANUP_MSG$$\" \"$$KEEP_MSG$$\"",
])
script_lines = [
"##echo## \"\"",
"##echo## \"{}\"".format(version_and_lib),
@ -245,9 +246,6 @@ def cc_external_rule_impl(ctx, attrs):
"##mkdirs## $$EXT_BUILD_DEPS$$",
"##mkdirs## $$INSTALLDIR$$",
_print_env(),
# the call trap is defined inside, in a way how the shell function should be called
# see, for instance, linux_commands.bzl
trap_function,
"\n".join(_copy_deps_and_tools(inputs)),
# replace placeholder with the dependencies root
"##define_absolute_paths## $$EXT_BUILD_DEPS$$ $$EXT_BUILD_DEPS$$",
@ -266,22 +264,24 @@ def cc_external_rule_impl(ctx, attrs):
]
script_text = convert_shell_script(ctx, script_lines)
print("script text: " + script_text)
execution_requirements = {"block-network": ""}
wrapped_outputs = wrap_outputs(ctx, lib_name, attrs.configure_name, script_text)
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],
inputs = inputs.declared_inputs + ctx.attr._cc_toolchain.files.to_list(),
outputs = rule_outputs + [
empty.file,
wrapped_outputs.log_file,
],
tools = [wrapped_outputs.script_file],
# 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 = execution_os_name != "osx",
command = script_text,
execution_requirements = execution_requirements,
command = wrapped_outputs.wrapper_script,
execution_requirements = {"block-network": ""},
# this is ignored if use_default_shell_env = True
env = env,
)
@ -292,9 +292,16 @@ def cc_external_rule_impl(ctx, attrs):
lib_dir_name = attrs.out_lib_dir,
include_dir_name = attrs.out_include_dir,
)
output_groups = _declare_output_groups(installdir_copy.file, outputs.out_binary_files)
wrapped_files = [
wrapped_outputs.script_file,
wrapped_outputs.log_file,
wrapped_outputs.wrapper_script_file,
]
output_groups[attrs.configure_name + "_logs"] = wrapped_files
return [
DefaultInfo(files = depset(direct = rule_outputs)),
OutputGroupInfo(**_declare_output_groups(installdir_copy.file, outputs.out_binary_files)),
DefaultInfo(files = depset(direct = rule_outputs + wrapped_files)),
OutputGroupInfo(**output_groups),
ForeignCcDeps(artifacts = depset(
[externally_built],
transitive = _get_transitive_artifacts(attrs.deps),
@ -306,6 +313,76 @@ def cc_external_rule_impl(ctx, attrs):
),
]
WrappedOutputs = provider(
doc = "Structure for passing the log and scripts file information, and wrapper script text.",
fields = {
"script_file": "Main script file",
"log_file": "Execution log file",
"wrapper_script_file": "Wrapper script file (output for debugging purposes)",
"wrapper_script": "Wrapper script text to execute",
},
)
def wrap_outputs(ctx, lib_name, configure_name, script_text):
build_script_file = ctx.actions.declare_file("{}/logs/{}_script.sh".format(lib_name, configure_name))
ctx.actions.write(
output = build_script_file,
content = script_text,
is_executable = True,
)
build_log_file = ctx.actions.declare_file("{}/logs/{}.log".format(lib_name, configure_name))
cleanup_on_success_function = create_function(
ctx,
"cleanup_on_success",
"""##echo## \"rules_foreign_cc: Cleaning temp directories\"
rm -rf $BUILD_TMPDIR $EXT_BUILD_DEPS""",
)
cleanup_on_failure_function = create_function(
ctx,
"cleanup_on_failure",
"""##echo## "\\nrules_foreign_cc: Build failed!\
\\nrules_foreign_cc: Keeping temp build directory $$BUILD_TMPDIR$$ and dependencies directory\
$$EXT_BUILD_DEPS$$ for debug.\\nrules_foreign_cc:\
Please note that the directories inside a sandbox are still\
cleaned unless you specify '--sandbox_debug' Bazel command line flag.\\n\\n\
rules_foreign_cc: Printing build logs:\\n\\n_____ BEGIN BUILD LOGS _____\\n"
##cat## $$BUILD_LOG$$
##echo## "\\n_____ END BUILD LOGS _____\\n"
##echo## "rules_foreign_cc: Build script location: $$BUILD_SCRIPT$$\\n"
##echo## "rules_foreign_cc: Build log location: $$BUILD_LOG$$\\n\\n"
""",
)
trap_function = "##cleanup_function## cleanup_on_success cleanup_on_failure"
build_command_lines = [
"##assert_script_errors##",
cleanup_on_success_function,
cleanup_on_failure_function,
# the call trap is defined inside, in a way how the shell function should be called
# see, for instance, linux_commands.bzl
trap_function,
"export BUILD_SCRIPT=\"{}\"".format(build_script_file.path),
"export BUILD_LOG=\"{}\"".format(build_log_file.path),
# sometimes the log file is not created, we do not want our script to fail because of this
"##touch## $$BUILD_LOG$$",
"##redirect_out_err## $$BUILD_SCRIPT$$ $$BUILD_LOG$$",
]
build_command = convert_shell_script(ctx, build_command_lines)
wrapper_script_file = ctx.actions.declare_file("{}/logs/wrapper_script.sh".format(lib_name))
ctx.actions.write(
output = wrapper_script_file,
content = build_command,
)
return WrappedOutputs(
script_file = build_script_file,
log_file = build_log_file,
wrapper_script_file = wrapper_script_file,
wrapper_script = build_command,
)
def _declare_output_groups(installdir, outputs):
dict_ = {}
dict_["gen_dir"] = depset([installdir])

View File

@ -12,8 +12,17 @@ load(
"targets_windows",
)
load("@rules_foreign_cc//tools/build_defs:detect_root.bzl", "detect_root")
load("@rules_foreign_cc//tools/build_defs:run_shell_file_utils.bzl", "copy_directory", "fictive_file_in_genroot")
load("@rules_foreign_cc//tools/build_defs:shell_script_helper.bzl", "convert_shell_script", "os_name")
load(
"@rules_foreign_cc//tools/build_defs:run_shell_file_utils.bzl",
"copy_directory",
"fictive_file_in_genroot",
)
load(
"@rules_foreign_cc//tools/build_defs:shell_script_helper.bzl",
"convert_shell_script",
"create_function",
"os_name",
)
""" Dict with definitions of the context attributes, that customize cc_external_rule_impl function.
Many of the attributes have default values.
@ -205,7 +214,7 @@ def cc_external_rule_impl(ctx, attrs):
if execution_os_name != "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)
version_and_lib = "Bazel external C/C++ Rules #{}. Building library '{}'\\n".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
@ -227,14 +236,6 @@ def cc_external_rule_impl(ctx, attrs):
"export INSTALLDIR=$$EXT_BUILD_ROOT$$/" + empty.file.dirname + "/" + lib_name,
]
trap_function = "\n".join([
"export CLEANUP_MSG=\"rules_foreign_cc: Cleaning temp directories\"",
"export KEEP_MSG=\"rules_foreign_cc: Keeping temp build directory $$BUILD_TMPDIR$$\
and dependencies directory $$EXT_BUILD_DEPS$$ for debug.\\nrules_foreign_cc: Please note that the directories inside a sandbox are still\
cleaned unless you specify '--sandbox_debug' Bazel command line flag.\\n\"",
"##cleanup_function## \"$$CLEANUP_MSG$$\" \"$$KEEP_MSG$$\"",
])
script_lines = [
"##echo## \"\"",
"##echo## \"{}\"".format(version_and_lib),
@ -245,9 +246,6 @@ def cc_external_rule_impl(ctx, attrs):
"##mkdirs## $$EXT_BUILD_DEPS$$",
"##mkdirs## $$INSTALLDIR$$",
_print_env(),
# the call trap is defined inside, in a way how the shell function should be called
# see, for instance, linux_commands.bzl
trap_function,
"\n".join(_copy_deps_and_tools(inputs)),
# replace placeholder with the dependencies root
"##define_absolute_paths## $$EXT_BUILD_DEPS$$ $$EXT_BUILD_DEPS$$",
@ -266,47 +264,24 @@ def cc_external_rule_impl(ctx, attrs):
]
script_text = convert_shell_script(ctx, script_lines)
execution_requirements = {"block-network": ""}
wrapped_outputs = wrap_outputs(ctx, lib_name, attrs.configure_name, script_text)
rule_outputs = outputs.declared_outputs + [installdir_copy.file]
build_script_file = ctx.actions.declare_file("{}_Cc{}MakeRuleScript.sh".format(lib_name, attrs.configure_name.capitalize()))
ctx.actions.write(
output = build_script_file,
content = script_text,
is_executable = True,
)
build_log_file = ctx.actions.declare_file("{}_Cc{}MakeRuleLog.txt".format(lib_name, attrs.configure_name.capitalize()))
build_command_lines = [
"export BUILD_SCRIPT=\"{}\"".format(build_script_file.path),
"export BUILD_LOG=\"{}\"".format(build_log_file.path),
"$$BUILD_SCRIPT$$ &> $$BUILD_LOG$$",
"BUILD_EXIT_CODE=$?",
"if [[ $$BUILD_EXIT_CODE$$ -ne 0 ]]",
"then",
"echo \"rules_foreign_cc: Build failed! Printing build logs:\"",
"echo \"##### BEGIN BUILD LOGS #####\"",
"cat $$BUILD_LOG$$",
"echo \"##### END BUILD LOGS #####\"",
"echo \"rules_foreign_cc: Build script location: $$BUILD_SCRIPT$$\"",
"echo \"rules_foreign_cc: Build log location: $$BUILD_LOG$$\"",
"exit 1",
"fi",
]
build_command = convert_shell_script(ctx, build_command_lines)
ctx.actions.run_shell(
mnemonic = "Cc" + attrs.configure_name.capitalize() + "MakeRule",
inputs = inputs.declared_inputs + ctx.attr._cc_toolchain.files.to_list(),
outputs = rule_outputs + [empty.file, build_log_file],
tools = [build_script_file],
inputs = depset(inputs.declared_inputs, transitive = [ctx.attr._cc_toolchain.files]),
outputs = rule_outputs + [
empty.file,
wrapped_outputs.log_file,
],
tools = [wrapped_outputs.script_file],
# 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 = execution_os_name != "osx",
command = build_command,
execution_requirements = execution_requirements,
command = wrapped_outputs.wrapper_script,
execution_requirements = {"block-network": ""},
# this is ignored if use_default_shell_env = True
env = env,
)
@ -317,9 +292,16 @@ def cc_external_rule_impl(ctx, attrs):
lib_dir_name = attrs.out_lib_dir,
include_dir_name = attrs.out_include_dir,
)
output_groups = _declare_output_groups(installdir_copy.file, outputs.out_binary_files)
wrapped_files = [
wrapped_outputs.script_file,
wrapped_outputs.log_file,
wrapped_outputs.wrapper_script_file,
]
output_groups[attrs.configure_name + "_logs"] = wrapped_files
return [
DefaultInfo(files = depset(direct = rule_outputs)),
OutputGroupInfo(**_declare_output_groups(installdir_copy.file, outputs.out_binary_files)),
DefaultInfo(files = depset(direct = rule_outputs + wrapped_files)),
OutputGroupInfo(**output_groups),
ForeignCcDeps(artifacts = depset(
[externally_built],
transitive = _get_transitive_artifacts(attrs.deps),
@ -331,6 +313,76 @@ def cc_external_rule_impl(ctx, attrs):
),
]
WrappedOutputs = provider(
doc = "Structure for passing the log and scripts file information, and wrapper script text.",
fields = {
"script_file": "Main script file",
"log_file": "Execution log file",
"wrapper_script_file": "Wrapper script file (output for debugging purposes)",
"wrapper_script": "Wrapper script text to execute",
},
)
def wrap_outputs(ctx, lib_name, configure_name, script_text):
build_script_file = ctx.actions.declare_file("{}/logs/{}_script.sh".format(lib_name, configure_name))
ctx.actions.write(
output = build_script_file,
content = script_text,
is_executable = True,
)
build_log_file = ctx.actions.declare_file("{}/logs/{}.log".format(lib_name, configure_name))
cleanup_on_success_function = create_function(
ctx,
"cleanup_on_success",
"""##echo## \"rules_foreign_cc: Cleaning temp directories\"
rm -rf $BUILD_TMPDIR $EXT_BUILD_DEPS""",
)
cleanup_on_failure_function = create_function(
ctx,
"cleanup_on_failure",
"""##echo## "\\nrules_foreign_cc: Build failed!\
\\nrules_foreign_cc: Keeping temp build directory $$BUILD_TMPDIR$$ and dependencies directory\
$$EXT_BUILD_DEPS$$ for debug.\\nrules_foreign_cc:\
Please note that the directories inside a sandbox are still\
cleaned unless you specify '--sandbox_debug' Bazel command line flag.\\n\\n\
rules_foreign_cc: Printing build logs:\\n\\n_____ BEGIN BUILD LOGS _____\\n"
##cat## $$BUILD_LOG$$
##echo## "\\n_____ END BUILD LOGS _____\\n"
##echo## "rules_foreign_cc: Build script location: $$BUILD_SCRIPT$$\\n"
##echo## "rules_foreign_cc: Build log location: $$BUILD_LOG$$\\n\\n"
""",
)
trap_function = "##cleanup_function## cleanup_on_success cleanup_on_failure"
build_command_lines = [
"##assert_script_errors##",
cleanup_on_success_function,
cleanup_on_failure_function,
# the call trap is defined inside, in a way how the shell function should be called
# see, for instance, linux_commands.bzl
trap_function,
"export BUILD_SCRIPT=\"{}\"".format(build_script_file.path),
"export BUILD_LOG=\"{}\"".format(build_log_file.path),
# sometimes the log file is not created, we do not want our script to fail because of this
"##touch## $$BUILD_LOG$$",
"##redirect_out_err## $$BUILD_SCRIPT$$ $$BUILD_LOG$$",
]
build_command = convert_shell_script(ctx, build_command_lines)
wrapper_script_file = ctx.actions.declare_file("{}/logs/wrapper_script.sh".format(lib_name))
ctx.actions.write(
output = wrapper_script_file,
content = build_command,
)
return WrappedOutputs(
script_file = build_script_file,
log_file = build_log_file,
wrapper_script_file = wrapper_script_file,
wrapper_script = build_command,
)
def _declare_output_groups(installdir, outputs):
dict_ = {}
dict_["gen_dir"] = depset([installdir])
@ -348,9 +400,9 @@ def _get_transitive_artifacts(deps):
def _print_env():
return "\n".join([
"##echo## \"Environment:______________\"",
"##echo## \"Environment:______________\\n\"",
"##env##",
"##echo## \"__________________________\"",
"##echo## \"__________________________\\n\"",
])
def _correct_path_variable(env):

View File

@ -37,6 +37,9 @@ load("//tools/build_defs/shell_toolchain/toolchains:commands.bzl", "PLATFORM_COM
def os_name(ctx):
return call_shell(create_context(ctx), "os_name")
def create_function(ctx, name, text):
return call_shell(create_context(ctx), "define_function", name, text)
def convert_shell_script(ctx, script):
""" Converts shell script from the intermediate notation to actual schell script.
Please see the file header for the notation description.

View File

@ -145,12 +145,30 @@ NB symlinks from the source directory are copied.""",
doc = """Find subdirectory inside a passed directory with *.pc files and add it
to the PKG_CONFIG_PATH""",
),
"assert_script_errors": CommandInfo(
arguments = [],
doc = "Script fragment that stops the execution after any error",
),
"cat": CommandInfo(
arguments = [
ArgumentInfo(name = "filepath", type_ = type(""), doc = "Path to the file"),
],
doc = "Output the file contents to stdout",
),
"redirect_out_err": CommandInfo(
arguments = [
ArgumentInfo(name = "from_process", type_ = type(""), doc = "Process to run"),
ArgumentInfo(name = "to_file", type_ = type(""), doc = "File to redirect output to"),
],
doc = "Read the result of the execution of the previous command, execute success or failure callbacks",
),
"cleanup_function": CommandInfo(
arguments = [
ArgumentInfo(name = "message_cleaning", type_ = type(""), doc = "Message to output about cleaning"),
ArgumentInfo(name = "message_keeping", type_ = type(""), doc = "Message to output about keeping directories"),
ArgumentInfo(name = "on_success", type_ = type(""), doc = "Command(s) to be executed on success"),
ArgumentInfo(name = "on_failure", type_ = type(""), doc = "Command(s) to be executed on failure"),
],
doc = "Trap function called after the script is finished",
# doc = "Read the result of the execution of the previous command, execute success or failure callbacks",
),
"children_to_path": CommandInfo(
arguments = [

View File

@ -109,16 +109,22 @@ done
"""
return FunctionAndCall(text = text)
def cleanup_function(message_cleaning, message_keeping):
def cat(filepath):
return "cat \"{}\"".format(filepath)
def redirect_out_err(from_process, to_file):
return from_process + " &> " + to_file
def assert_script_errors():
return "set -e"
def cleanup_function(on_success, on_failure):
text = "\n".join([
"local ecode=$?",
"if [ $ecode -eq 0 ]; then",
"printf \"%s\"" % message_cleaning,
"rm -rf $BUILD_TMPDIR $EXT_BUILD_DEPS",
on_success,
"else",
"printf \"\"",
"printf \"%s\"" % message_keeping,
"printf \"\"",
on_failure,
"fi",
])
return FunctionAndCall(text = text, call = "trap \"cleanup_function\" EXIT")

View File

@ -109,16 +109,22 @@ done
"""
return FunctionAndCall(text = text)
def cleanup_function(message_cleaning, message_keeping):
def cat(filepath):
return "cat \"{}\"".format(filepath)
def redirect_out_err(from_process, to_file):
return from_process + " &> " + to_file
def assert_script_errors():
return "set -e"
def cleanup_function(on_success, on_failure):
text = "\n".join([
"local ecode=$?",
"if [ $ecode -eq 0 ]; then",
"printf \"%s\"" % message_cleaning,
"rm -rf $BUILD_TMPDIR $EXT_BUILD_DEPS",
on_success,
"else",
"printf \"\"",
"printf \"%s\"" % message_keeping,
"printf \"\"",
on_failure,
"fi",
])
return FunctionAndCall(text = text, call = "trap \"cleanup_function\" EXIT")

View File

@ -120,16 +120,22 @@ done
"""
return FunctionAndCall(text = text)
def cleanup_function(message_cleaning, message_keeping):
def cat(filepath):
return "cat \"{}\"".format(filepath)
def redirect_out_err(from_process, to_file):
return from_process + " &> " + to_file
def assert_script_errors():
return "set -e"
def cleanup_function(on_success, on_failure):
text = "\n".join([
"local ecode=$?",
"if [ $ecode -eq 0 ]; then",
"printf \"%s\"" % message_cleaning,
"rm -rf $BUILD_TMPDIR $EXT_BUILD_DEPS",
on_success,
"else",
"printf \"\"",
"printf \"%s\"" % message_keeping,
"printf \"\"",
on_failure,
"fi",
])
return FunctionAndCall(text = text, call = "trap \"cleanup_function\" EXIT")

View File

@ -116,16 +116,22 @@ done
"""
return FunctionAndCall(text = text)
def cleanup_function(message_cleaning, message_keeping):
def cat(filepath):
return "cat \"{}\"".format(filepath)
def redirect_out_err(from_process, to_file):
return from_process + " &> " + to_file
def assert_script_errors():
return "set -e"
def cleanup_function(on_success, on_failure):
text = "\n".join([
"local ecode=$?",
"if [ $ecode -eq 0 ]; then",
"printf \"%s\"" % message_cleaning,
"rm -rf $BUILD_TMPDIR $EXT_BUILD_DEPS",
on_success,
"else",
"printf \"\"",
"printf \"%s\"" % message_keeping,
"printf \"\"",
on_failure,
"fi",
])
return FunctionAndCall(text = text, call = "trap \"cleanup_function\" EXIT")

View File

@ -1 +1 @@
VERSION = "0.0.6" # shell toolchain and native tools toolchains
VERSION = "0.0.7" # output refactoring