From 2c6262f8f487cd3481db27e2c509d9e6d30bfe53 Mon Sep 17 00:00:00 2001 From: jheaff1 <48310225+jheaff1@users.noreply.github.com> Date: Wed, 9 Nov 2022 11:54:39 +0000 Subject: [PATCH] Hermetic pkg config (#979) --- .bazelci/config.yaml | 13 +- README.md | 6 +- WORKSPACE.bazel | 2 +- examples/.bazelrc | 8 ++ examples/WORKSPACE.bazel | 3 +- examples/third_party/WORKSPACE.bazel | 2 +- .../third_party/openssl/BUILD.openssl.bazel | 5 +- foreign_cc/built_tools/pkgconfig_build.bzl | 111 ++++++++++++++++ foreign_cc/configure.bzl | 5 +- foreign_cc/private/framework.bzl | 21 ++- .../framework/toolchains/freebsd_commands.bzl | 2 +- .../framework/toolchains/linux_commands.bzl | 2 +- .../framework/toolchains/macos_commands.bzl | 2 +- .../framework/toolchains/windows_commands.bzl | 2 +- foreign_cc/private/runnable_binary_wrapper.sh | 2 +- foreign_cc/repositories.bzl | 23 ++-- foreign_cc/utils.bzl | 34 +++-- toolchains/BUILD.bazel | 26 ++++ toolchains/built_toolchains.bzl | 124 +++++++++++++++++- .../native_tools/native_tools_toolchain.bzl | 26 +++- toolchains/pkgconfig-detectenv.patch | 16 +++ toolchains/pkgconfig-makefile-vc.patch | 11 ++ toolchains/toolchains.bzl | 4 + 23 files changed, 408 insertions(+), 42 deletions(-) create mode 100644 examples/.bazelrc create mode 100644 foreign_cc/built_tools/pkgconfig_build.bzl create mode 100644 toolchains/pkgconfig-detectenv.patch create mode 100644 toolchains/pkgconfig-makefile-vc.patch diff --git a/.bazelci/config.yaml b/.bazelci/config.yaml index f082ef0e6..58bcbd4f5 100644 --- a/.bazelci/config.yaml +++ b/.bazelci/config.yaml @@ -131,8 +131,6 @@ tasks: - "-//cmake_with_data/..." build_targets: *windows_targets test_targets: *windows_targets - test_flags: - - "--enable_runfiles" rbe_ubuntu1604_flags: name: Flags platform: rbe_ubuntu1604 @@ -193,8 +191,14 @@ tasks: platform: ubuntu1804 build_targets: - "//..." + # experimental_enable_aggregating_middleman=False is required in bazel 4 otherwise ctx.resolve_command fails. + # This was resolved in https://github.com/bazelbuild/bazel/commit/fb1c369530bd26f9a13560c5979929a999e585e2 + build_flags: + - "--experimental_enable_aggregating_middleman=False" test_targets: - "//..." + test_flags: + - "--experimental_enable_aggregating_middleman=False" min_supported_version_examples: name: "Minimum Supported Version Examples" bazel: "4.0.0" @@ -203,7 +207,12 @@ tasks: min_supported_targets: &min_supported_targets - "//..." build_targets: *min_supported_targets + # See comment above regarding --experimental_enable_aggregating_middleman=False + build_flags: + - "--experimental_enable_aggregating_middleman=False" test_targets: *min_supported_targets + test_flags: + - "--experimental_enable_aggregating_middleman=False" buildifier: version: "4.2.5" diff --git a/README.md b/README.md index 65d626c65..f0d8aa252 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,11 @@ Documentation for all rules and providers are available at: https://bazelbuild.g ## Bazel versions compatibility -Works with Bazel after 4.0.0 without any flags. +Works with Bazel after 4.0.0. + +The following flags are required in Bazel 4.x but not Bazel 5.x or newer: + +- `--experimental_enable_aggregating_middleman=False` Note that the rules may be compatible with older versions of Bazel but support may break in future changes as these older versions are not tested. diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel index d22623349..0e6ec2ba4 100644 --- a/WORKSPACE.bazel +++ b/WORKSPACE.bazel @@ -3,7 +3,7 @@ workspace(name = "rules_foreign_cc") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies") -rules_foreign_cc_dependencies() +rules_foreign_cc_dependencies(register_built_pkgconfig_toolchain = True) local_repository( name = "rules_foreign_cc_examples", diff --git a/examples/.bazelrc b/examples/.bazelrc new file mode 100644 index 000000000..d2615fcb6 --- /dev/null +++ b/examples/.bazelrc @@ -0,0 +1,8 @@ + +# Required for Windows +build --enable_runfiles + +# These are required otherwise paths are too long +startup --windows_enable_symlinks +build --action_env=MSYS=winsymlinks:nativestrict +test --action_env=MSYS=winsymlinks:nativestrict diff --git a/examples/WORKSPACE.bazel b/examples/WORKSPACE.bazel index 3f64e982b..481353ee2 100644 --- a/examples/WORKSPACE.bazel +++ b/examples/WORKSPACE.bazel @@ -7,8 +7,7 @@ local_repository( load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies") -# Don't use preinstalled tools to ensure builds are as hermetic as possible -rules_foreign_cc_dependencies(register_preinstalled_tools = False) +rules_foreign_cc_dependencies(register_built_pkgconfig_toolchain = True) load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") diff --git a/examples/third_party/WORKSPACE.bazel b/examples/third_party/WORKSPACE.bazel index a8f975bcc..cbc7b0225 100644 --- a/examples/third_party/WORKSPACE.bazel +++ b/examples/third_party/WORKSPACE.bazel @@ -7,7 +7,7 @@ local_repository( load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies") -rules_foreign_cc_dependencies(register_preinstalled_tools = False) +rules_foreign_cc_dependencies(register_built_pkgconfig_toolchain = True) local_repository( name = "rules_foreign_cc_examples", diff --git a/examples/third_party/openssl/BUILD.openssl.bazel b/examples/third_party/openssl/BUILD.openssl.bazel index 9e231c9a4..a947c9777 100644 --- a/examples/third_party/openssl/BUILD.openssl.bazel +++ b/examples/third_party/openssl/BUILD.openssl.bazel @@ -125,10 +125,7 @@ filegroup( runnable_binary( name = "runnable_openssl", - binary = select({ - "@platforms//os:windows": "openssl.exe", - "//conditions:default": "openssl", - }), + binary = "openssl", foreign_cc_target = "@openssl//:openssl", visibility = ["//visibility:public"], ) diff --git a/foreign_cc/built_tools/pkgconfig_build.bzl b/foreign_cc/built_tools/pkgconfig_build.bzl new file mode 100644 index 000000000..11110e744 --- /dev/null +++ b/foreign_cc/built_tools/pkgconfig_build.bzl @@ -0,0 +1,111 @@ +""" Rule for building pkg-config from source. """ + +load("//foreign_cc:defs.bzl", "make_variant", "runnable_binary") +load( + "//foreign_cc/built_tools/private:built_tools_framework.bzl", + "FOREIGN_CC_BUILT_TOOLS_ATTRS", + "FOREIGN_CC_BUILT_TOOLS_FRAGMENTS", + "FOREIGN_CC_BUILT_TOOLS_HOST_FRAGMENTS", + "built_tool_rule_impl", +) +load("//toolchains/native_tools:tool_access.bzl", "get_make_data") + +def _pkgconfig_tool_impl(ctx): + make_data = get_make_data(ctx) + script = [ + "./configure --with-internal-glib --prefix=$$INSTALLDIR$$", + "%s" % make_data.path, + "%s install" % make_data.path, + ] + + additional_tools = depset(transitive = [dep.files for dep in make_data.deps]) + + return built_tool_rule_impl( + ctx, + script, + ctx.actions.declare_directory("pkgconfig"), + "BootstrapPkgConfig", + additional_tools, + ) + +pkgconfig_tool_unix = rule( + doc = "Rule for building pkgconfig on Unix operating systems", + attrs = FOREIGN_CC_BUILT_TOOLS_ATTRS, + host_fragments = FOREIGN_CC_BUILT_TOOLS_HOST_FRAGMENTS, + fragments = FOREIGN_CC_BUILT_TOOLS_FRAGMENTS, + output_to_genfiles = True, + implementation = _pkgconfig_tool_impl, + toolchains = [ + "@rules_foreign_cc//foreign_cc/private/framework:shell_toolchain", + "@rules_foreign_cc//toolchains:make_toolchain", + "@bazel_tools//tools/cpp:toolchain_type", + ], +) + +def pkgconfig_tool(name, srcs, **kwargs): + """ + Macro that provides targets for building pkg-config from source + + Args: + name: The target name + srcs: The pkg-config source files + **kwargs: Remaining keyword arguments + """ + tags = ["manual"] + kwargs.pop("tags", []) + + native.config_setting( + name = "msvc_compiler", + flag_values = { + "@bazel_tools//tools/cpp:compiler": "msvc-cl", + }, + ) + + native.alias( + name = name, + actual = select({ + ":msvc_compiler": "{}_msvc".format(name), + "//conditions:default": "{}_default".format(name), + }), + ) + + pkgconfig_tool_unix( + name = "{}_default".format(name), + srcs = srcs, + tags = tags, + **kwargs + ) + + make_variant( + name = "{}_msvc_build".format(name), + lib_source = srcs, + args = [ + "-f Makefile.vc", + "CFG=release", + "GLIB_PREFIX=\"$$EXT_BUILD_ROOT/external/glib_dev\"", + ], + out_binaries = ["pkg-config.exe"], + env = {"INCLUDE": "$$EXT_BUILD_ROOT/external/glib_src"}, + out_static_libs = [], + out_shared_libs = [], + deps = [ + "@glib_dev", + "@glib_src//:msvc_hdr", + "@gettext_runtime", + ], + postfix_script = select({ + "@platforms//os:windows": "cp release/x64/pkg-config.exe $$INSTALLDIR$$/bin", + "//conditions:default": "", + }), + toolchain = "@rules_foreign_cc//toolchains:preinstalled_nmake_toolchain", + tags = tags, + **kwargs + ) + + runnable_binary( + name = "{}_msvc".format(name), + binary = "pkg-config", + foreign_cc_target = "{}_msvc_build".format(name), + # Tools like CMake and Meson search for "pkg-config" on the PATH + match_binary_name = True, + tags = tags, + ) diff --git a/foreign_cc/configure.bzl b/foreign_cc/configure.bzl index f79d6189a..177842067 100644 --- a/foreign_cc/configure.bzl +++ b/foreign_cc/configure.bzl @@ -20,12 +20,13 @@ load( ) load("//foreign_cc/private:transitions.bzl", "make_variant") load("//foreign_cc/private/framework:platform.bzl", "os_name") -load("//toolchains/native_tools:tool_access.bzl", "get_make_data") +load("//toolchains/native_tools:tool_access.bzl", "get_make_data", "get_pkgconfig_data") def _configure_make(ctx): make_data = get_make_data(ctx) + pkg_config_data = get_pkgconfig_data(ctx) - tools_deps = ctx.attr.tools_deps + make_data.deps + tools_deps = ctx.attr.tools_deps + make_data.deps + pkg_config_data.deps if ctx.attr.autogen and not ctx.attr.configure_in_place: fail("`autogen` requires `configure_in_place = True`. Please update {}".format( diff --git a/foreign_cc/private/framework.bzl b/foreign_cc/private/framework.bzl index dff4ad1ba..a5c95093e 100644 --- a/foreign_cc/private/framework.bzl +++ b/foreign_cc/private/framework.bzl @@ -274,6 +274,9 @@ dependencies.""", ), ) +def _is_msvc_var(var): + return var == "INCLUDE" or var == "LIB" + def get_env_prelude(ctx, lib_name, data_dependencies, target_root): """Generate a bash snippet containing environment variable definitions @@ -321,8 +324,10 @@ def get_env_prelude(ctx, lib_name, data_dependencies, target_root): # If user has defined a PATH variable (e.g. PATH, LD_LIBRARY_PATH, CPATH) prepend it to the existing variable for user_var in user_vars: - if "PATH" in user_var and cc_env.get(user_var): - env.update({user_var: user_vars.get(user_var) + ":" + cc_env.get(user_var)}) + is_existing_var = "PATH" in user_var or _is_msvc_var(user_var) + list_delimiter = ";" if _is_msvc_var(user_var) else ":" + if is_existing_var and cc_env.get(user_var): + env.update({user_var: user_vars.get(user_var) + list_delimiter + cc_env.get(user_var)}) cc_toolchain = find_cpp_toolchain(ctx) if cc_toolchain.compiler == "msvc-cl": @@ -404,7 +409,7 @@ def cc_external_rule_impl(ctx, attrs): installdir_copy = copy_directory(ctx.actions, "$$INSTALLDIR$$", "copy_{}/{}".format(lib_name, lib_name)) target_root = paths.dirname(installdir_copy.file.dirname) - data_dependencies = ctx.attr.data + ctx.attr.build_data + ctx.attr.toolchains + data_dependencies = ctx.attr.data + ctx.attr.build_data + ctx.attr.toolchains + attrs.tools_deps # Also add legacy dependencies while they're still available data_dependencies += ctx.attr.tools_deps + ctx.attr.additional_tools @@ -496,7 +501,15 @@ def cc_external_rule_impl(ctx, attrs): # Gather runfiles transitively as per the documentation in: # https://docs.bazel.build/versions/master/skylark/rules.html#runfiles - runfiles = ctx.runfiles(files = ctx.files.data + outputs.libraries.shared_libraries) + + # Include shared libraries of transitive dependencies in runfiles, facilitating the "runnable_binary" macro + transitive_shared_libraries = [] + for linker_input in out_cc_info.linking_context.linker_inputs.to_list(): + for lib in linker_input.libraries: + if lib.dynamic_library: + transitive_shared_libraries.append(lib.dynamic_library) + + runfiles = ctx.runfiles(files = ctx.files.data + transitive_shared_libraries) for target in [ctx.attr.lib_source] + ctx.attr.deps + ctx.attr.data: runfiles = runfiles.merge(target[DefaultInfo].default_runfiles) diff --git a/foreign_cc/private/framework/toolchains/freebsd_commands.bzl b/foreign_cc/private/framework/toolchains/freebsd_commands.bzl index 4021ee8b8..4672b9495 100644 --- a/foreign_cc/private/framework/toolchains/freebsd_commands.bzl +++ b/foreign_cc/private/framework/toolchains/freebsd_commands.bzl @@ -229,7 +229,7 @@ if [ -d {dir_} ]; then for tool in $tools; do if [[ -d \"$tool\" ]] || [[ -L \"$tool\" ]]; then - export PATH=$PATH:$tool + export PATH=$tool:$PATH fi done fi""".format(dir_ = dir_) diff --git a/foreign_cc/private/framework/toolchains/linux_commands.bzl b/foreign_cc/private/framework/toolchains/linux_commands.bzl index 7770a20a8..138c3f92d 100644 --- a/foreign_cc/private/framework/toolchains/linux_commands.bzl +++ b/foreign_cc/private/framework/toolchains/linux_commands.bzl @@ -211,7 +211,7 @@ if [ -d {dir_} ]; then for tool in $tools; do if [[ -d \"$tool\" ]] || [[ -L \"$tool\" ]]; then - export PATH=$PATH:$tool + export PATH=$tool:$PATH fi done fi""".format(dir_ = dir_) diff --git a/foreign_cc/private/framework/toolchains/macos_commands.bzl b/foreign_cc/private/framework/toolchains/macos_commands.bzl index 15c3de9f8..9138009e1 100644 --- a/foreign_cc/private/framework/toolchains/macos_commands.bzl +++ b/foreign_cc/private/framework/toolchains/macos_commands.bzl @@ -220,7 +220,7 @@ if [ -d {dir_} ]; then for tool in $tools; do if [[ -d \"$tool\" ]] || [[ -L \"$tool\" ]]; then - export PATH=$PATH:$tool + export PATH=$tool:$PATH fi done fi""".format(dir_ = dir_) diff --git a/foreign_cc/private/framework/toolchains/windows_commands.bzl b/foreign_cc/private/framework/toolchains/windows_commands.bzl index 7a6861ebb..6ca1e02cd 100644 --- a/foreign_cc/private/framework/toolchains/windows_commands.bzl +++ b/foreign_cc/private/framework/toolchains/windows_commands.bzl @@ -225,7 +225,7 @@ if [ -d {dir_} ]; then for tool in $tools; do if [[ -d \"$tool\" ]] || [[ -L \"$tool\" ]]; then - export PATH=$PATH:$tool + export PATH=$tool:$PATH fi done fi""".format(dir_ = dir_) diff --git a/foreign_cc/private/runnable_binary_wrapper.sh b/foreign_cc/private/runnable_binary_wrapper.sh index e5cbb0e89..5d5878e35 100644 --- a/foreign_cc/private/runnable_binary_wrapper.sh +++ b/foreign_cc/private/runnable_binary_wrapper.sh @@ -40,7 +40,7 @@ IFS=" " read -r -a SHARED_LIBS_DIRS_ARRAY <<< "$(tr ' ' '\n' <<< "${SHARED_LIBS_ # Allow unbound variable here, in case LD_LIBRARY_PATH or similar is not already set set +u for dir in "${SHARED_LIBS_DIRS_ARRAY[@]}"; do - export ${LIB_PATH_VAR}="${!LIB_PATH_VAR}":"$dir" + export ${LIB_PATH_VAR}="$dir":"${!LIB_PATH_VAR}" done set -u diff --git a/foreign_cc/repositories.bzl b/foreign_cc/repositories.bzl index 1287e1b46..c2904fb13 100644 --- a/foreign_cc/repositories.bzl +++ b/foreign_cc/repositories.bzl @@ -12,9 +12,11 @@ def rules_foreign_cc_dependencies( cmake_version = "3.23.2", make_version = "4.4", ninja_version = "1.11.0", + pkgconfig_version = "0.29.2", register_preinstalled_tools = True, register_built_tools = True, - register_toolchains = True): + register_toolchains = True, + register_built_pkgconfig_toolchain = False): """Call this function from the WORKSPACE file to initialize rules_foreign_cc \ dependencies and let neccesary code generation happen \ (Code generation is needed to support different variants of the C++ Starlark API.). @@ -38,12 +40,22 @@ def rules_foreign_cc_dependencies( ninja_version: The target version of the ninja toolchain if `register_default_tools` or `register_built_tools` is set to `True`. + pkgconfig_version: The target version of the pkg_config toolchain if `register_built_tools` is set to `True`. + register_preinstalled_tools: If true, toolchains will be registered for the native built tools installed on the exec host register_built_tools: If true, toolchains that build the tools from source are registered register_toolchains: If true, registers the toolchains via native.register_toolchains. Used by bzlmod + + register_built_pkgconfig_toolchain: If true, the built pkgconfig toolchain will be registered. On Windows it may be preferrable to set this to False, as + this requires the --enable_runfiles bazel option. Also note that building pkgconfig from source under bazel results in paths that are more + than 256 characters long, which will not work on Windows unless the following options are added to the .bazelrc and symlinks are enabled in Windows. + + startup --windows_enable_symlinks -> This is required to enable symlinking to avoid long runfile paths + build --action_env=MSYS=winsymlinks:nativestrict -> This is required to enable symlinking to avoid long runfile paths + startup --output_user_root=C:/b -> This is required to keep paths as short as possible """ register_framework_toolchains(register_toolchains = register_toolchains) @@ -51,13 +63,6 @@ def rules_foreign_cc_dependencies( if register_toolchains: native.register_toolchains(*native_tools_toolchains) - native.register_toolchains( - "@rules_foreign_cc//toolchains:preinstalled_autoconf_toolchain", - "@rules_foreign_cc//toolchains:preinstalled_automake_toolchain", - "@rules_foreign_cc//toolchains:preinstalled_m4_toolchain", - "@rules_foreign_cc//toolchains:preinstalled_pkgconfig_toolchain", - ) - if register_default_tools: prebuilt_toolchains(cmake_version, ninja_version, register_toolchains) @@ -66,7 +71,9 @@ def rules_foreign_cc_dependencies( cmake_version = cmake_version, make_version = make_version, ninja_version = ninja_version, + pkgconfig_version = pkgconfig_version, register_toolchains = register_toolchains, + register_built_pkgconfig_toolchain = register_built_pkgconfig_toolchain, ) if register_preinstalled_tools: diff --git a/foreign_cc/utils.bzl b/foreign_cc/utils.bzl index 09fe71444..08296e237 100644 --- a/foreign_cc/utils.bzl +++ b/foreign_cc/utils.bzl @@ -3,7 +3,7 @@ def _full_label(label): return native.repository_name() + "//" + native.package_name() + ":" + label -def runnable_binary(name, binary, foreign_cc_target, **kwargs): +def runnable_binary(name, binary, foreign_cc_target, match_binary_name = False, **kwargs): """ Macro that provides a wrapper script around a binary generated by a rules_foreign_cc rule that can be run using "bazel run". @@ -14,18 +14,30 @@ def runnable_binary(name, binary, foreign_cc_target, **kwargs): Args: name: The target name - binary: The name of the binary generated by rules_foreign_cc + binary: The name of the binary generated by rules_foreign_cc, should not include .exe extension foreign_cc_target: The target that generates the binary + match_binary_name: True if the generated runnable file should have the same name as the provided "binary" argument. This is useful when the runnable_binary is used with tools that expect a certain filename, e.g tools like CMake and Meson expect "pkg-config" to be on the PATH **kwargs: Remaining keyword arguments """ tags = kwargs.pop("tags", []) + # filegroups cannot select on constraint_values in before Bazel 5.1. Add this config_setting as a workaround. See https://github.com/bazelbuild/bazel/issues/13047 + native.config_setting( + name = "windows_config_setting", + constraint_values = [ + "@platforms//os:windows", + ], + ) + native.filegroup( name = name + "_fg", srcs = [foreign_cc_target], tags = tags + ["manual"], - output_group = binary, + output_group = select({ + ":windows_config_setting": binary + ".exe", + "//conditions:default": binary, + }), ) native.genrule( @@ -37,12 +49,18 @@ def runnable_binary(name, binary, foreign_cc_target, **kwargs): ) native.sh_binary( - name = name, + name = binary if match_binary_name else name, deps = ["@bazel_tools//tools/bash/runfiles"], + data = [name + "_fg", foreign_cc_target], srcs = [name + "_wrapper"], - data = [ - name + "_fg", - foreign_cc_target, - ], + tags = tags + ["manual"], **kwargs ) + + if match_binary_name: + native.alias( + name = name, + actual = binary, + tags = tags, + **kwargs + ) diff --git a/toolchains/BUILD.bazel b/toolchains/BUILD.bazel index c25679574..cf8d4f8d7 100644 --- a/toolchains/BUILD.bazel +++ b/toolchains/BUILD.bazel @@ -2,6 +2,7 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("//foreign_cc/built_tools:cmake_build.bzl", "cmake_tool") load("//foreign_cc/built_tools:make_build.bzl", "make_tool") load("//foreign_cc/built_tools:ninja_build.bzl", "ninja_tool") +load("//foreign_cc/built_tools:pkgconfig_build.bzl", "pkgconfig_tool") load("//toolchains:toolchains.bzl", "current_autoconf_toolchain", "current_automake_toolchain", "current_cmake_toolchain", "current_m4_toolchain", "current_make_toolchain", "current_ninja_toolchain", "current_pkgconfig_toolchain") load("//toolchains/native_tools:native_tools_toolchain.bzl", "native_tool_toolchain") @@ -81,6 +82,12 @@ toolchain( toolchain_type = ":make_toolchain", ) +toolchain( + name = "built_pkgconfig_toolchain", + toolchain = ":built_pkgconfig", + toolchain_type = ":pkgconfig_toolchain", +) + # Preinstalled cmake will always be the default, if toolchain with more exact constraints # is not defined before; registered from workspace_definitions.bzl#rules_foreign_cc_dependencies toolchain( @@ -264,6 +271,25 @@ native_tool_toolchain( }), ) +pkgconfig_tool( + name = "pkgconfig_tool", + srcs = "@pkgconfig_src//:all_srcs", + tags = ["manual"], +) + +native_tool_toolchain( + name = "built_pkgconfig", + env = select({ + "@platforms//os:windows": {"PKG_CONFIG": "$(execpath :pkgconfig_tool)"}, + "//conditions:default": {"PKG_CONFIG": "$(execpath :pkgconfig_tool)/bin/pkg-config"}, + }), + path = select({ + "@platforms//os:windows": "$(execpath :pkgconfig_tool)", + "//conditions:default": "$(execpath :pkgconfig_tool)/bin/pkg-config", + }), + target = ":pkgconfig_tool", +) + bzl_library( name = "bzl_srcs", srcs = glob(["**/*.bzl"]), diff --git a/toolchains/built_toolchains.bzl b/toolchains/built_toolchains.bzl index 6bca5031f..c32fc5f64 100644 --- a/toolchains/built_toolchains.bzl +++ b/toolchains/built_toolchains.bzl @@ -31,12 +31,31 @@ _CMAKE_SRCS = { } # buildifier: disable=unnamed-macro -def built_toolchains(cmake_version, make_version, ninja_version, register_toolchains): - """Register toolchains for built tools that will be built from source""" +def built_toolchains(cmake_version, make_version, ninja_version, pkgconfig_version, register_toolchains, register_built_pkgconfig_toolchain): + """ + Register toolchains for built tools that will be built from source + + + Args: + cmake_version: The CMake version to build + + make_version: The Make version to build + + ninja_version: The Ninja version to build + + pkgconfig_version: The pkg-config version to build + + register_toolchains: If true, registers the toolchains via native.register_toolchains. Used by bzlmod + + register_built_pkgconfig_toolchain: If true, the built pkgconfig toolchain will be registered. + """ _cmake_toolchain(cmake_version, register_toolchains) _make_toolchain(make_version, register_toolchains) _ninja_toolchain(ninja_version, register_toolchains) + if register_built_pkgconfig_toolchain: + _pkgconfig_toolchain(pkgconfig_version, register_toolchains) + def _cmake_toolchain(version, register_toolchains): if register_toolchains: native.register_toolchains( @@ -477,3 +496,104 @@ def _ninja_toolchain(version, register_toolchains): return fail("Unsupported ninja version: " + str(version)) + +def _pkgconfig_toolchain(version, register_toolchains): + if register_toolchains: + native.register_toolchains( + "@rules_foreign_cc//toolchains:built_pkgconfig_toolchain", + ) + + maybe( + http_archive, + name = "glib_dev", + build_file_content = ''' +load("@rules_cc//cc:defs.bzl", "cc_library") + +cc_import( + name = "glib_dev", + hdrs = glob(["include/**"]), + shared_library = "@glib_runtime//:bin/libglib-2.0-0.dll", + visibility = ["//visibility:public"], +) + ''', + sha256 = "bdf18506df304d38be98a4b3f18055b8b8cca81beabecad0eece6ce95319c369", + urls = [ + "https://download.gnome.org/binaries/win64/glib/2.26/glib-dev_2.26.1-1_win64.zip", + ], + ) + + maybe( + http_archive, + name = "glib_src", + build_file_content = ''' +cc_import( + name = "msvc_hdr", + hdrs = ["msvc_recommended_pragmas.h"], + visibility = ["//visibility:public"], +) + ''', + sha256 = "bc96f63112823b7d6c9f06572d2ad626ddac7eb452c04d762592197f6e07898e", + strip_prefix = "glib-2.26.1", + urls = [ + "https://download.gnome.org/sources/glib/2.26/glib-2.26.1.tar.gz", + ], + ) + + maybe( + http_archive, + name = "glib_runtime", + build_file_content = ''' +exports_files( + [ + "bin/libgio-2.0-0.dll", + "bin/libglib-2.0-0.dll", + "bin/libgmodule-2.0-0.dll", + "bin/libgobject-2.0-0.dll", + "bin/libgthread-2.0-0.dll", + ], + visibility = ["//visibility:public"], +) + ''', + sha256 = "88d857087e86f16a9be651ee7021880b3f7ba050d34a1ed9f06113b8799cb973", + urls = [ + "https://download.gnome.org/binaries/win64/glib/2.26/glib_2.26.1-1_win64.zip", + ], + ) + + maybe( + http_archive, + name = "gettext_runtime", + build_file_content = ''' +cc_import( + name = "gettext_runtime", + shared_library = "bin/libintl-8.dll", + visibility = ["//visibility:public"], +) + ''', + sha256 = "1f4269c0e021076d60a54e98da6f978a3195013f6de21674ba0edbc339c5b079", + urls = [ + "https://download.gnome.org/binaries/win64/dependencies/gettext-runtime_0.18.1.1-2_win64.zip", + ], + ) + if version == "0.29.2": + maybe( + http_archive, + name = "pkgconfig_src", + build_file_content = _ALL_CONTENT, + sha256 = "6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591", + strip_prefix = "pkg-config-0.29.2", + # The patch is required as bazel does not provide the VCINSTALLDIR or WINDOWSSDKDIR vars + patches = [ + # This patch is required as bazel does not provide the VCINSTALLDIR or WINDOWSSDKDIR vars + Label("//toolchains:pkgconfig-detectenv.patch"), + + # This patch is required as rules_foreign_cc runs in MSYS2 on Windows and MSYS2's "mkdir" is used + Label("//toolchains:pkgconfig-makefile-vc.patch"), + ], + urls = [ + "https://pkgconfig.freedesktop.org/releases/pkg-config-0.29.2.tar.gz", + ], + ) + return + + fail("Unsupported pkgconfig version: " + str(version)) diff --git a/toolchains/native_tools/native_tools_toolchain.bzl b/toolchains/native_tools/native_tools_toolchain.bzl index 620c2d5a9..4613b3ee6 100644 --- a/toolchains/native_tools/native_tools_toolchain.bzl +++ b/toolchains/native_tools/native_tools_toolchain.bzl @@ -19,13 +19,35 @@ ToolInfo = provider( }, ) +def _resolve_tool_path(ctx, path, target): + """ + Resolve the path to a tool. + + Note that ctx.resolve_command is used instead of ctx.expand_location as the + latter cannot be used with py_binary and sh_binary targets as they both produce multiple files in some contexts, meaning + that the plural make variables must be used, e.g. $(execpaths) must be used. See https://github.com/bazelbuild/bazel/issues/11820. + + The usage of ctx.resolve_command facilitates the usage of the singular make variables, e.g $(execpath), with py_binary and sh_binary targets + """ + _, resolved_bash_command, _ = ctx.resolve_command( + command = path, + expand_locations = True, + tools = [target], + ) + + return resolved_bash_command[-1] + def _native_tool_toolchain_impl(ctx): if not ctx.attr.path and not ctx.attr.target: fail("Either path or target (and path) should be defined for the tool.") path = None + env = {} if ctx.attr.target: - path = ctx.expand_location(ctx.attr.path, targets = [ctx.attr.target]) - env = {k: ctx.expand_location(v, targets = [ctx.attr.target]) for (k, v) in ctx.attr.env.items()} + path = _resolve_tool_path(ctx, ctx.attr.path, ctx.attr.target) + + for k, v in ctx.attr.env.items(): + env[k] = _resolve_tool_path(ctx, v, ctx.attr.target) + else: path = ctx.expand_location(ctx.attr.path) env = {k: ctx.expand_location(v) for (k, v) in ctx.attr.env.items()} diff --git a/toolchains/pkgconfig-detectenv.patch b/toolchains/pkgconfig-detectenv.patch new file mode 100644 index 000000000..1dd4cf6e1 --- /dev/null +++ b/toolchains/pkgconfig-detectenv.patch @@ -0,0 +1,16 @@ +--- detectenv-msvc.mak 2016-04-11 22:39:26.000000000 +0100 ++++ detectenv-msvc.mak 2016-04-11 22:39:26.000000000 +0100 +@@ -1,12 +1,6 @@ + # Check to see we are configured to build with MSVC (MSDEVDIR, MSVCDIR or + # VCINSTALLDIR) or with the MS Platform SDK (MSSDK or WindowsSDKDir) +-!if !defined(VCINSTALLDIR) && !defined(WINDOWSSDKDIR) +-MSG = ^ +-This Makefile is only for Visual Studio 2008 and later.^ +-You need to ensure that the Visual Studio Environment is properly set up^ +-before running this Makefile. +-!error $(MSG) +-!endif ++ + + ERRNUL = 2>NUL + _HASH=^# diff --git a/toolchains/pkgconfig-makefile-vc.patch b/toolchains/pkgconfig-makefile-vc.patch new file mode 100644 index 000000000..c3cf00d9b --- /dev/null +++ b/toolchains/pkgconfig-makefile-vc.patch @@ -0,0 +1,11 @@ +--- Makefile.vc 2016-04-11 22:39:26.000000000 +0100 ++++ Makefile.vc.new 2022-08-19 17:46:52.031979100 +0100 +@@ -73,7 +73,7 @@ + @-if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;1 + + $(CFG)\$(PLAT)\pkg-config: +- @-mkdir $@ ++ @-mkdir -p $@ + + config.h: config.h.win32 + @-copy $@.win32 $@ diff --git a/toolchains/toolchains.bzl b/toolchains/toolchains.bzl index dafcf5a21..85b9c364e 100644 --- a/toolchains/toolchains.bzl +++ b/toolchains/toolchains.bzl @@ -16,6 +16,10 @@ def preinstalled_toolchains(): "@rules_foreign_cc//toolchains:preinstalled_cmake_toolchain", "@rules_foreign_cc//toolchains:preinstalled_make_toolchain", "@rules_foreign_cc//toolchains:preinstalled_ninja_toolchain", + "@rules_foreign_cc//toolchains:preinstalled_autoconf_toolchain", + "@rules_foreign_cc//toolchains:preinstalled_automake_toolchain", + "@rules_foreign_cc//toolchains:preinstalled_m4_toolchain", + "@rules_foreign_cc//toolchains:preinstalled_pkgconfig_toolchain", ) def _current_toolchain_impl(ctx):