def _genrule_repository(ctx): ctx.download_and_extract( ctx.attr.urls, "", # output ctx.attr.sha256, "", # type ctx.attr.strip_prefix, ) for ii, patch in enumerate(ctx.attr.patches): patch_input = "patch-input-%d.patch" % (ii,) ctx.symlink(patch, patch_input) patch_result = ctx.execute(["patch", "-p0", "--input", patch_input]) if patch_result.return_code != 0: fail("Failed to apply patch %r: %s" % (patch, patch_result.stderr)) # https://github.com/bazelbuild/bazel/issues/3766 genrule_cmd_file = Label("@envoy//bazel").relative(str(ctx.attr.genrule_cmd_file)) ctx.symlink(genrule_cmd_file, "_envoy_genrule_cmd.genrule_cmd") cat_genrule_cmd = ctx.execute(["cat", "_envoy_genrule_cmd.genrule_cmd"]) if cat_genrule_cmd.return_code != 0: fail("Failed to read genrule command %r: %s" % ( genrule_cmd_file, cat_genrule_cmd.stderr, )) ctx.file("WORKSPACE", "workspace(name=%r)" % (ctx.name,)) ctx.symlink(ctx.attr.build_file, "BUILD.bazel") # Inject the genrule_cmd content into a .bzl file that can be loaded # from the repository BUILD file. We force the user to look up the # command content "by label" so the inclusion source is obvious. ctx.file("genrule_cmd.bzl", """ _GENRULE_CMD = {%r: %r} def genrule_cmd(label): return _GENRULE_CMD[label] """ % (str(genrule_cmd_file), cat_genrule_cmd.stdout)) genrule_repository = repository_rule( attrs = { "urls": attr.string_list( mandatory = True, allow_empty = False, ), "sha256": attr.string(), "strip_prefix": attr.string(), "patches": attr.label_list( allow_files = [".patch"], allow_empty = True, ), "genrule_cmd_file": attr.label( mandatory = True, allow_single_file = [".genrule_cmd"], ), "build_file": attr.label( mandatory = True, allow_single_file = [".BUILD"], ), }, implementation = _genrule_repository, ) def _genrule_cc_deps(ctx): outs = depset() for dep in ctx.attr.deps: outs = dep.cc.transitive_headers + dep.cc.libs + outs return DefaultInfo(files = outs) genrule_cc_deps = rule( attrs = { "deps": attr.label_list( providers = [], # CcStarlarkApiProvider mandatory = True, allow_empty = False, ), }, implementation = _genrule_cc_deps, ) def _absolute_bin(path): # If the binary path looks like it's relative to the current directory, # transform it to be absolute by appending "${PWD}". if "/" in path and not path.startswith("/"): return '"${PWD}"/%r' % (path,) return "%r" % (path,) def _genrule_environment(ctx): lines = [] # Bazel uses the same command for C and C++ compilation. c_compiler = ctx.var["CC"] # Bare minimum cflags to get included test binaries to link. # # See .bazelrc for the full set. asan_flags = ["-fsanitize=address,undefined"] tsan_flags = ["-fsanitize=thread"] # Older versions of GCC in Ubuntu, including GCC 5 used in CI images, # incorrectly invoke the older `/usr/bin/ld` with gold-specific options when # building with sanitizers enabled. Work around this by forcing use of gold # in sanitize mode. # # This is not a great solution because it doesn't detect GCC when Bazel has # wrapped it in an intermediate script, but it works well enough to keep CI # running. # # https://stackoverflow.com/questions/37603238/fsanitize-not-using-gold-linker-in-gcc-6-1 force_ld = [] if "clang" in c_compiler: force_ld = ["-fuse-ld=lld"] elif "gcc" in c_compiler or "g++" in c_compiler: force_ld = ["-fuse-ld=gold"] cc_flags = [] ld_flags = [] ld_libs = [] if ctx.var.get("ENVOY_CONFIG_COVERAGE"): ld_libs.append("-lgcov") if ctx.var.get("ENVOY_CONFIG_ASAN"): cc_flags += asan_flags ld_flags += asan_flags ld_flags += force_ld if ctx.var.get("ENVOY_CONFIG_TSAN"): cc_flags += tsan_flags ld_flags += tsan_flags ld_flags += force_ld lines.append("export CFLAGS=%r" % (" ".join(cc_flags),)) lines.append("export LDFLAGS=%r" % (" ".join(ld_flags),)) lines.append("export LIBS=%r" % (" ".join(ld_libs),)) lines.append("export CC=%s" % (_absolute_bin(c_compiler),)) lines.append("export CXX=%s" % (_absolute_bin(c_compiler),)) # Some Autoconf helper binaries leak, which makes ./configure think the # system is unable to do anything. Turn off leak checking during part of # the build. lines.append("export ASAN_OPTIONS=detect_leaks=0") lines.append("") out = ctx.actions.declare_file(ctx.attr.name + ".sh") ctx.actions.write(out, "\n".join(lines)) return DefaultInfo(files = depset([out])) genrule_environment = rule( implementation = _genrule_environment, )