Hermetic pkg config (#979)

This commit is contained in:
jheaff1 2022-11-09 11:54:39 +00:00 committed by GitHub
parent 6425a21252
commit 2c6262f8f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 408 additions and 42 deletions

View File

@ -131,8 +131,6 @@ tasks:
- "-//cmake_with_data/..." - "-//cmake_with_data/..."
build_targets: *windows_targets build_targets: *windows_targets
test_targets: *windows_targets test_targets: *windows_targets
test_flags:
- "--enable_runfiles"
rbe_ubuntu1604_flags: rbe_ubuntu1604_flags:
name: Flags name: Flags
platform: rbe_ubuntu1604 platform: rbe_ubuntu1604
@ -193,8 +191,14 @@ tasks:
platform: ubuntu1804 platform: ubuntu1804
build_targets: 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_targets:
- "//..." - "//..."
test_flags:
- "--experimental_enable_aggregating_middleman=False"
min_supported_version_examples: min_supported_version_examples:
name: "Minimum Supported Version Examples" name: "Minimum Supported Version Examples"
bazel: "4.0.0" bazel: "4.0.0"
@ -203,7 +207,12 @@ tasks:
min_supported_targets: &min_supported_targets min_supported_targets: &min_supported_targets
- "//..." - "//..."
build_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_targets: *min_supported_targets
test_flags:
- "--experimental_enable_aggregating_middleman=False"
buildifier: buildifier:
version: "4.2.5" version: "4.2.5"

View File

@ -13,7 +13,11 @@ Documentation for all rules and providers are available at: https://bazelbuild.g
## Bazel versions compatibility ## 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 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. in future changes as these older versions are not tested.

View File

@ -3,7 +3,7 @@ workspace(name = "rules_foreign_cc")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies") load("//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies")
rules_foreign_cc_dependencies() rules_foreign_cc_dependencies(register_built_pkgconfig_toolchain = True)
local_repository( local_repository(
name = "rules_foreign_cc_examples", name = "rules_foreign_cc_examples",

8
examples/.bazelrc Normal file
View File

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

View File

@ -7,8 +7,7 @@ local_repository(
load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies") 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_built_pkgconfig_toolchain = True)
rules_foreign_cc_dependencies(register_preinstalled_tools = False)
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")

View File

@ -7,7 +7,7 @@ local_repository(
load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies") 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( local_repository(
name = "rules_foreign_cc_examples", name = "rules_foreign_cc_examples",

View File

@ -125,10 +125,7 @@ filegroup(
runnable_binary( runnable_binary(
name = "runnable_openssl", name = "runnable_openssl",
binary = select({ binary = "openssl",
"@platforms//os:windows": "openssl.exe",
"//conditions:default": "openssl",
}),
foreign_cc_target = "@openssl//:openssl", foreign_cc_target = "@openssl//:openssl",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )

View File

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

View File

@ -20,12 +20,13 @@ load(
) )
load("//foreign_cc/private:transitions.bzl", "make_variant") load("//foreign_cc/private:transitions.bzl", "make_variant")
load("//foreign_cc/private/framework:platform.bzl", "os_name") 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): def _configure_make(ctx):
make_data = get_make_data(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: if ctx.attr.autogen and not ctx.attr.configure_in_place:
fail("`autogen` requires `configure_in_place = True`. Please update {}".format( fail("`autogen` requires `configure_in_place = True`. Please update {}".format(

View File

@ -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): def get_env_prelude(ctx, lib_name, data_dependencies, target_root):
"""Generate a bash snippet containing environment variable definitions """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 # 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: for user_var in user_vars:
if "PATH" in user_var and cc_env.get(user_var): is_existing_var = "PATH" in user_var or _is_msvc_var(user_var)
env.update({user_var: user_vars.get(user_var) + ":" + cc_env.get(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) cc_toolchain = find_cpp_toolchain(ctx)
if cc_toolchain.compiler == "msvc-cl": 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)) installdir_copy = copy_directory(ctx.actions, "$$INSTALLDIR$$", "copy_{}/{}".format(lib_name, lib_name))
target_root = paths.dirname(installdir_copy.file.dirname) 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 # Also add legacy dependencies while they're still available
data_dependencies += ctx.attr.tools_deps + ctx.attr.additional_tools 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: # Gather runfiles transitively as per the documentation in:
# https://docs.bazel.build/versions/master/skylark/rules.html#runfiles # 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: for target in [ctx.attr.lib_source] + ctx.attr.deps + ctx.attr.data:
runfiles = runfiles.merge(target[DefaultInfo].default_runfiles) runfiles = runfiles.merge(target[DefaultInfo].default_runfiles)

View File

@ -229,7 +229,7 @@ if [ -d {dir_} ]; then
for tool in $tools; for tool in $tools;
do do
if [[ -d \"$tool\" ]] || [[ -L \"$tool\" ]]; then if [[ -d \"$tool\" ]] || [[ -L \"$tool\" ]]; then
export PATH=$PATH:$tool export PATH=$tool:$PATH
fi fi
done done
fi""".format(dir_ = dir_) fi""".format(dir_ = dir_)

View File

@ -211,7 +211,7 @@ if [ -d {dir_} ]; then
for tool in $tools; for tool in $tools;
do do
if [[ -d \"$tool\" ]] || [[ -L \"$tool\" ]]; then if [[ -d \"$tool\" ]] || [[ -L \"$tool\" ]]; then
export PATH=$PATH:$tool export PATH=$tool:$PATH
fi fi
done done
fi""".format(dir_ = dir_) fi""".format(dir_ = dir_)

View File

@ -220,7 +220,7 @@ if [ -d {dir_} ]; then
for tool in $tools; for tool in $tools;
do do
if [[ -d \"$tool\" ]] || [[ -L \"$tool\" ]]; then if [[ -d \"$tool\" ]] || [[ -L \"$tool\" ]]; then
export PATH=$PATH:$tool export PATH=$tool:$PATH
fi fi
done done
fi""".format(dir_ = dir_) fi""".format(dir_ = dir_)

View File

@ -225,7 +225,7 @@ if [ -d {dir_} ]; then
for tool in $tools; for tool in $tools;
do do
if [[ -d \"$tool\" ]] || [[ -L \"$tool\" ]]; then if [[ -d \"$tool\" ]] || [[ -L \"$tool\" ]]; then
export PATH=$PATH:$tool export PATH=$tool:$PATH
fi fi
done done
fi""".format(dir_ = dir_) fi""".format(dir_ = dir_)

View File

@ -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 # Allow unbound variable here, in case LD_LIBRARY_PATH or similar is not already set
set +u set +u
for dir in "${SHARED_LIBS_DIRS_ARRAY[@]}"; do 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 done
set -u set -u

View File

@ -12,9 +12,11 @@ def rules_foreign_cc_dependencies(
cmake_version = "3.23.2", cmake_version = "3.23.2",
make_version = "4.4", make_version = "4.4",
ninja_version = "1.11.0", ninja_version = "1.11.0",
pkgconfig_version = "0.29.2",
register_preinstalled_tools = True, register_preinstalled_tools = True,
register_built_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 \ """Call this function from the WORKSPACE file to initialize rules_foreign_cc \
dependencies and let neccesary code generation happen \ dependencies and let neccesary code generation happen \
(Code generation is needed to support different variants of the C++ Starlark API.). (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` ninja_version: The target version of the ninja toolchain if `register_default_tools`
or `register_built_tools` is set to `True`. 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 register_preinstalled_tools: If true, toolchains will be registered for the native built tools
installed on the exec host installed on the exec host
register_built_tools: If true, toolchains that build the tools from source are registered 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_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) register_framework_toolchains(register_toolchains = register_toolchains)
@ -51,13 +63,6 @@ def rules_foreign_cc_dependencies(
if register_toolchains: if register_toolchains:
native.register_toolchains(*native_tools_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: if register_default_tools:
prebuilt_toolchains(cmake_version, ninja_version, register_toolchains) prebuilt_toolchains(cmake_version, ninja_version, register_toolchains)
@ -66,7 +71,9 @@ def rules_foreign_cc_dependencies(
cmake_version = cmake_version, cmake_version = cmake_version,
make_version = make_version, make_version = make_version,
ninja_version = ninja_version, ninja_version = ninja_version,
pkgconfig_version = pkgconfig_version,
register_toolchains = register_toolchains, register_toolchains = register_toolchains,
register_built_pkgconfig_toolchain = register_built_pkgconfig_toolchain,
) )
if register_preinstalled_tools: if register_preinstalled_tools:

View File

@ -3,7 +3,7 @@
def _full_label(label): def _full_label(label):
return native.repository_name() + "//" + native.package_name() + ":" + 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". 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: Args:
name: The target name 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 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 **kwargs: Remaining keyword arguments
""" """
tags = kwargs.pop("tags", []) 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( native.filegroup(
name = name + "_fg", name = name + "_fg",
srcs = [foreign_cc_target], srcs = [foreign_cc_target],
tags = tags + ["manual"], tags = tags + ["manual"],
output_group = binary, output_group = select({
":windows_config_setting": binary + ".exe",
"//conditions:default": binary,
}),
) )
native.genrule( native.genrule(
@ -37,12 +49,18 @@ def runnable_binary(name, binary, foreign_cc_target, **kwargs):
) )
native.sh_binary( native.sh_binary(
name = name, name = binary if match_binary_name else name,
deps = ["@bazel_tools//tools/bash/runfiles"], deps = ["@bazel_tools//tools/bash/runfiles"],
data = [name + "_fg", foreign_cc_target],
srcs = [name + "_wrapper"], srcs = [name + "_wrapper"],
data = [ tags = tags + ["manual"],
name + "_fg",
foreign_cc_target,
],
**kwargs **kwargs
) )
if match_binary_name:
native.alias(
name = name,
actual = binary,
tags = tags,
**kwargs
)

View File

@ -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:cmake_build.bzl", "cmake_tool")
load("//foreign_cc/built_tools:make_build.bzl", "make_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: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: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") load("//toolchains/native_tools:native_tools_toolchain.bzl", "native_tool_toolchain")
@ -81,6 +82,12 @@ toolchain(
toolchain_type = ":make_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 # 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 # is not defined before; registered from workspace_definitions.bzl#rules_foreign_cc_dependencies
toolchain( 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( bzl_library(
name = "bzl_srcs", name = "bzl_srcs",
srcs = glob(["**/*.bzl"]), srcs = glob(["**/*.bzl"]),

View File

@ -31,12 +31,31 @@ _CMAKE_SRCS = {
} }
# buildifier: disable=unnamed-macro # buildifier: disable=unnamed-macro
def built_toolchains(cmake_version, make_version, ninja_version, register_toolchains): 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""" """
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) _cmake_toolchain(cmake_version, register_toolchains)
_make_toolchain(make_version, register_toolchains) _make_toolchain(make_version, register_toolchains)
_ninja_toolchain(ninja_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): def _cmake_toolchain(version, register_toolchains):
if register_toolchains: if register_toolchains:
native.register_toolchains( native.register_toolchains(
@ -477,3 +496,104 @@ def _ninja_toolchain(version, register_toolchains):
return return
fail("Unsupported ninja version: " + str(version)) 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))

View File

@ -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): def _native_tool_toolchain_impl(ctx):
if not ctx.attr.path and not ctx.attr.target: if not ctx.attr.path and not ctx.attr.target:
fail("Either path or target (and path) should be defined for the tool.") fail("Either path or target (and path) should be defined for the tool.")
path = None path = None
env = {}
if ctx.attr.target: if ctx.attr.target:
path = ctx.expand_location(ctx.attr.path, targets = [ctx.attr.target]) path = _resolve_tool_path(ctx, ctx.attr.path, ctx.attr.target)
env = {k: ctx.expand_location(v, targets = [ctx.attr.target]) for (k, v) in ctx.attr.env.items()}
for k, v in ctx.attr.env.items():
env[k] = _resolve_tool_path(ctx, v, ctx.attr.target)
else: else:
path = ctx.expand_location(ctx.attr.path) path = ctx.expand_location(ctx.attr.path)
env = {k: ctx.expand_location(v) for (k, v) in ctx.attr.env.items()} env = {k: ctx.expand_location(v) for (k, v) in ctx.attr.env.items()}

View File

@ -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=^#

View File

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

View File

@ -16,6 +16,10 @@ def preinstalled_toolchains():
"@rules_foreign_cc//toolchains:preinstalled_cmake_toolchain", "@rules_foreign_cc//toolchains:preinstalled_cmake_toolchain",
"@rules_foreign_cc//toolchains:preinstalled_make_toolchain", "@rules_foreign_cc//toolchains:preinstalled_make_toolchain",
"@rules_foreign_cc//toolchains:preinstalled_ninja_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): def _current_toolchain_impl(ctx):