From aaedbc0a6549a31d8f8374583c73812e990cb4a8 Mon Sep 17 00:00:00 2001 From: John Sun <79071267+jsun-splunk@users.noreply.github.com> Date: Tue, 19 Nov 2024 10:11:17 +1100 Subject: [PATCH] feat: configurable ldflags (#1226) --- foreign_cc/configure.bzl | 34 ++++++++++----- foreign_cc/make.bzl | 26 ++++++++++- foreign_cc/private/configure_script.bzl | 20 ++++++++- foreign_cc/private/make_env_vars.bzl | 58 ++++++++++++++++++++----- foreign_cc/private/make_script.bzl | 25 ++++++++++- 5 files changed, 136 insertions(+), 27 deletions(-) diff --git a/foreign_cc/configure.bzl b/foreign_cc/configure.bzl index 64551f341..f001abf12 100644 --- a/foreign_cc/configure.bzl +++ b/foreign_cc/configure.bzl @@ -74,7 +74,6 @@ def _create_configure_script(configureParameters): user_env = expand_locations_and_make_variables(ctx, ctx.attr.env, "env", data) - make_commands = [] prefix = "{} ".format(expand_locations_and_make_variables(ctx, attrs.tool_prefix, "tool_prefix", data)) if attrs.tool_prefix else "" configure_prefix = "{} ".format(expand_locations_and_make_variables(ctx, ctx.attr.configure_prefix, "configure_prefix", data)) if ctx.attr.configure_prefix else "" configure_options = [expand_locations_and_make_variables(ctx, option, "configure_option", data) for option in ctx.attr.configure_options] if ctx.attr.configure_options else [] @@ -83,15 +82,6 @@ def _create_configure_script(configureParameters): if xcompile_options: configure_options.extend(xcompile_options) - for target in ctx.attr.targets: - # Configure will have generated sources into `$BUILD_TMPDIR` so make sure we `cd` there - make_commands.append("{prefix}{make} {target} {args}".format( - prefix = prefix, - make = attrs.make_path, - args = args, - target = target, - )) - configure = create_configure_script( workspace_name = ctx.workspace_name, tools = tools, @@ -112,8 +102,12 @@ def _create_configure_script(configureParameters): autogen = ctx.attr.autogen, autogen_command = ctx.attr.autogen_command, autogen_options = ctx.attr.autogen_options, - make_commands = make_commands, + make_prefix = prefix, make_path = attrs.make_path, + make_targets = ctx.attr.targets, + make_args = args, + executable_ldflags_vars = ctx.attr.executable_ldflags_vars, + shared_ldflags_vars = ctx.attr.shared_ldflags_vars, ) return define_install_prefix + configure @@ -198,6 +192,15 @@ def _attrs(): ), default = False, ), + "executable_ldflags_vars": attr.string_list( + doc = ( + "A list of variable names use as LDFLAGS for executables. These variables " + + "will be passed to the make command as make vars and overwrite what is defined in " + + "the Makefile." + ), + mandatory = False, + default = [], + ), "install_prefix": attr.string( doc = ( "Install prefix, i.e. relative path to where to install the result of the build. " + @@ -212,6 +215,15 @@ def _attrs(): mandatory = False, default = "--prefix=", ), + "shared_ldflags_vars": attr.string_list( + doc = ( + "A list of variable names use as LDFLAGS for shared libraries. These variables " + + "will be passed to the make command as make vars and overwrite what is defined in " + + "the Makefile." + ), + mandatory = False, + default = [], + ), "targets": attr.string_list( doc = ( "A list of targets within the foreign build system to produce. An empty string (`\"\"`) will result in " + diff --git a/foreign_cc/make.bzl b/foreign_cc/make.bzl index 79e76a26b..187f2ccc7 100644 --- a/foreign_cc/make.bzl +++ b/foreign_cc/make.bzl @@ -74,7 +74,13 @@ def _create_make_script(configureParameters): deps = ctx.attr.deps, inputs = inputs, env_vars = user_env, - make_commands = make_commands, + make_prefix = prefix, + make_path = attrs.make_path, + make_targets = ctx.attr.targets, + make_args = args, + make_install_prefix = ctx.attr.install_prefix, + executable_ldflags_vars = ctx.attr.executable_ldflags_vars, + shared_ldflags_vars = ctx.attr.shared_ldflags_vars, ) def _attrs(): @@ -83,6 +89,15 @@ def _attrs(): "args": attr.string_list( doc = "A list of arguments to pass to the call to `make`", ), + "executable_ldflags_vars": attr.string_list( + doc = ( + "A string list of variable names use as LDFLAGS for executables. These variables " + + "will be passed to the make command as make vars and overwrite what is defined in " + + "the Makefile." + ), + mandatory = False, + default = [], + ), "install_prefix": attr.string( doc = ( "Install prefix, i.e. relative path to where to install the result of the build. " + @@ -91,6 +106,15 @@ def _attrs(): mandatory = False, default = "$$INSTALLDIR$$", ), + "shared_ldflags_vars": attr.string_list( + doc = ( + "A string list of variable names use as LDFLAGS for shared libraries. These variables " + + "will be passed to the make command as make vars and overwrite what is defined in " + + "the Makefile." + ), + mandatory = False, + default = [], + ), "targets": attr.string_list( doc = ( "A list of targets within the foreign build system to produce. An empty string (`\"\"`) will result in " + diff --git a/foreign_cc/private/configure_script.bzl b/foreign_cc/private/configure_script.bzl index 06c516ea5..ac385d719 100644 --- a/foreign_cc/private/configure_script.bzl +++ b/foreign_cc/private/configure_script.bzl @@ -1,5 +1,5 @@ # buildifier: disable=module-docstring -load(":make_env_vars.bzl", "get_make_env_vars") +load(":make_env_vars.bzl", "get_ldflags_make_vars", "get_make_env_vars") load(":make_script.bzl", "pkgconfig_script") # buildifier: disable=function-docstring @@ -23,8 +23,12 @@ def create_configure_script( autogen, autogen_command, autogen_options, + make_prefix, make_path, - make_commands): + make_targets, + make_args, + executable_ldflags_vars, + shared_ldflags_vars): ext_build_dirs = inputs.ext_build_dirs script = pkgconfig_script(ext_build_dirs) @@ -77,6 +81,18 @@ def create_configure_script( user_options = " ".join(user_options), )) + ldflags_make_vars = get_ldflags_make_vars(executable_ldflags_vars, shared_ldflags_vars, workspace_name, flags, env_vars, deps, inputs) + + make_commands = [] + for target in make_targets: + make_commands.append("{prefix}{make} {make_vars} {target} {args}".format( + prefix = make_prefix, + make = make_path, + make_vars = ldflags_make_vars, + args = make_args, + target = target, + )) + script.extend(make_commands) script.append("##disable_tracing##") diff --git a/foreign_cc/private/make_env_vars.bzl b/foreign_cc/private/make_env_vars.bzl index 30e91c3b5..d2d1912c3 100644 --- a/foreign_cc/private/make_env_vars.bzl +++ b/foreign_cc/private/make_env_vars.bzl @@ -34,6 +34,24 @@ def get_make_env_vars( return " ".join(["{}=\"{}\"" .format(key, _join_flags_list(workspace_name, vars[key])) for key in vars]) +# buildifier: disable=function-docstring +def get_ldflags_make_vars( + executable_ldflags_vars, + shared_ldflags_vars, + workspace_name, + flags, + user_vars, + deps, + inputs): + vars = _get_ldflags_vars(executable_ldflags_vars, shared_ldflags_vars, flags, user_vars) + + deps_flags = _define_deps_flags(deps, inputs) + for key in vars.keys(): + vars[key] = vars[key] + deps_flags.libs + + return " ".join(["{}=\"{}\"" + .format(key, _join_flags_list(workspace_name, vars[key])) for key in vars]) + def _define_deps_flags(deps, inputs): # It is very important to keep the order for the linker => put them into list lib_dirs = [] @@ -99,17 +117,7 @@ _MAKE_TOOLS = { } def _get_make_variables(workspace_name, tools, flags, user_env_vars, make_commands): - vars = {} - - for flag in _MAKE_FLAGS: - toolchain_flags = getattr(flags, _MAKE_FLAGS[flag], []) - user_flags = [ - user_flag - for user_flag in user_env_vars.get(flag, "").split(" ") - if user_flag - ] - if toolchain_flags or user_flags: - vars[flag] = toolchain_flags + user_flags + vars = _merge_env_vars(flags, _MAKE_FLAGS, user_env_vars) # Add user defined CPPFLAGS user_cpp_flags = [flag for flag in user_env_vars.get("CPPFLAGS", "").split(" ") if flag] @@ -146,6 +154,34 @@ def _get_make_variables(workspace_name, tools, flags, user_env_vars, make_comman return vars +def _get_ldflags_vars( + executable_ldflags_vars, + shared_ldflags_vars, + flags, + user_env_vars): + executable_ldflags = {var: "cxx_linker_executable" for var in executable_ldflags_vars} + shared_ldflags = {var: "cxx_linker_shared" for var in shared_ldflags_vars} + + linker_make_flags = {} + for ldflags in [executable_ldflags, shared_ldflags]: + linker_make_flags.update(ldflags) + + return _merge_env_vars(flags, linker_make_flags, user_env_vars) + +def _merge_env_vars(flags, make_flags, user_env_vars): + vars = {} + + for flag in make_flags: + toolchain_flags = getattr(flags, make_flags[flag], []) + user_flags = [ + user_flag + for user_flag in user_env_vars.get(flag, "").split(" ") + if user_flag + ] + if toolchain_flags or user_flags: + vars[flag] = toolchain_flags + user_flags + return vars + def _absolutize(workspace_name, text, force = False): return absolutize_path_in_str(workspace_name, "$$EXT_BUILD_ROOT$$/", text, force) diff --git a/foreign_cc/private/make_script.bzl b/foreign_cc/private/make_script.bzl index 5a3754011..5c86e8da8 100644 --- a/foreign_cc/private/make_script.bzl +++ b/foreign_cc/private/make_script.bzl @@ -1,6 +1,6 @@ """A module for creating the build script for `make` builds""" -load(":make_env_vars.bzl", "get_make_env_vars") +load(":make_env_vars.bzl", "get_ldflags_make_vars", "get_make_env_vars") # buildifier: disable=function-docstring def create_make_script( @@ -11,7 +11,13 @@ def create_make_script( env_vars, deps, inputs, - make_commands): + make_prefix, + make_path, + make_targets, + make_args, + make_install_prefix, + executable_ldflags_vars, + shared_ldflags_vars): ext_build_dirs = inputs.ext_build_dirs script = pkgconfig_script(ext_build_dirs) @@ -19,7 +25,22 @@ def create_make_script( script.append("##symlink_contents_to_dir## $$EXT_BUILD_ROOT$$/{} $$BUILD_TMPDIR$$ False".format(root)) script.append("##enable_tracing##") + + ldflags_make_vars = get_ldflags_make_vars(executable_ldflags_vars, shared_ldflags_vars, workspace_name, flags, env_vars, deps, inputs) + + make_commands = [] + for target in make_targets: + make_commands.append("{prefix}{make} {make_vars} {target} {args} PREFIX={install_prefix}".format( + prefix = make_prefix, + make = make_path, + make_vars = ldflags_make_vars, + args = make_args, + target = target, + install_prefix = make_install_prefix, + )) + configure_vars = get_make_env_vars(workspace_name, tools, flags, env_vars, deps, inputs, make_commands) + script.extend(["{env_vars} {command}".format( env_vars = configure_vars, command = command,