diff --git a/MODULE.bazel b/MODULE.bazel index b9da631..61b07e7 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -6,6 +6,7 @@ module( compatibility_level = 1, ) +bazel_dep(name = "bazel_features", version = "1.15.0") bazel_dep(name = "bazel_skylib", version = "1.3.0") bazel_dep(name = "platforms", version = "0.0.5") bazel_dep(name = "rules_python", version = "0.23.1") diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel index 7079c0a..820d376 100644 --- a/WORKSPACE.bazel +++ b/WORKSPACE.bazel @@ -10,6 +10,10 @@ local_repository( path = "examples", ) +load("@bazel_features//:deps.bzl", "bazel_features_deps") + +bazel_features_deps() + load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") bazel_skylib_workspace() diff --git a/docs/WORKSPACE.bazel b/docs/WORKSPACE.bazel index 5fba825..3c31c91 100644 --- a/docs/WORKSPACE.bazel +++ b/docs/WORKSPACE.bazel @@ -9,6 +9,10 @@ load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_depende rules_foreign_cc_dependencies() +load("@bazel_features//:deps.bzl", "bazel_features_deps") + +bazel_features_deps() + load("//:stardoc_repository.bzl", "stardoc_repository") stardoc_repository() diff --git a/examples/third_party/zlib/BUILD.bazel b/examples/third_party/zlib/BUILD.bazel index 825e552..23d0122 100644 --- a/examples/third_party/zlib/BUILD.bazel +++ b/examples/third_party/zlib/BUILD.bazel @@ -1,4 +1,5 @@ load("@rules_cc//cc:defs.bzl", "cc_binary") +load("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake", "runnable_binary") exports_files( [ @@ -7,6 +8,15 @@ exports_files( visibility = ["//visibility:public"], ) +filegroup( + name = "shared_usage_srcs", + srcs = [ + "CMakeLists.txt", + "zlib-example.cpp", + ], + visibility = ["//visibility:public"], +) + cc_binary( name = "zlib_usage_example", srcs = ["zlib-example.cpp"], @@ -19,3 +29,24 @@ sh_test( data = [":zlib_usage_example"], visibility = ["//:__pkg__"], ) + +cmake( + name = "zlib_shared_usage_example", + dynamic_deps = ["@zlib//:zlib_shared"], + lib_source = "shared_usage_srcs", + out_binaries = ["zlib-example"], + deps = ["@zlib//:zlib_static"], +) + +runnable_binary( + name = "run-zlib-example", + binary = "zlib-example", + foreign_cc_target = ":zlib_shared_usage_example", +) + +sh_test( + name = "test_shared_zlib", + srcs = ["test_shared_zlib.sh"], + data = [":run-zlib-example"], + visibility = ["//:__pkg__"], +) diff --git a/examples/third_party/zlib/BUILD.zlib.bazel b/examples/third_party/zlib/BUILD.zlib.bazel index 38dce27..a6a7ac0 100644 --- a/examples/third_party/zlib/BUILD.zlib.bazel +++ b/examples/third_party/zlib/BUILD.zlib.bazel @@ -1,3 +1,4 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") load("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake") package(default_visibility = ["//visibility:public"]) @@ -28,3 +29,53 @@ cmake( "//conditions:default": ["libz.a"], }), ) + +cc_library( + name = "zlib_static", + srcs = [ + "adler32.c", + "compress.c", + "crc32.c", + "deflate.c", + "gzclose.c", + "gzlib.c", + "gzread.c", + "gzwrite.c", + "infback.c", + "inffast.c", + "inflate.c", + "inftrees.c", + "trees.c", + "uncompr.c", + "zutil.c", + ], + hdrs = [ + "crc32.h", + "deflate.h", + "gzguts.h", + "inffast.h", + "inffixed.h", + "inflate.h", + "inftrees.h", + "trees.h", + "zconf.h", + "zlib.h", + "zutil.h", + ], + copts = select({ + "@platforms//os:windows": [], + "//conditions:default": [ + "-Wno-deprecated-non-prototype", + "-Wno-unused-variable", + "-Wno-implicit-function-declaration", + ], + }), + includes = ["."], + linkstatic = True, +) + +cc_shared_library( + name = "zlib_shared", + shared_lib_name = "libz.so", + deps = ["zlib_static"], +) diff --git a/examples/third_party/zlib/CMakeLists.txt b/examples/third_party/zlib/CMakeLists.txt new file mode 100644 index 0000000..3031b74 --- /dev/null +++ b/examples/third_party/zlib/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.15) + +project(zlib-example) + +find_package(ZLIB REQUIRED) + +set(SRCS zlib-example.cpp) + +add_executable(${PROJECT_NAME} ${SRCS}) + +target_link_libraries(${PROJECT_NAME} ZLIB::ZLIB) + +install(TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/examples/third_party/zlib/test_shared_zlib.sh b/examples/third_party/zlib/test_shared_zlib.sh new file mode 100755 index 0000000..c1b52f5 --- /dev/null +++ b/examples/third_party/zlib/test_shared_zlib.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +$(rlocation rules_foreign_cc/examples/cmake/zlib_shared_usage_example) \ No newline at end of file diff --git a/foreign_cc/private/BUILD.bazel b/foreign_cc/private/BUILD.bazel index d08851b..bb33184 100644 --- a/foreign_cc/private/BUILD.bazel +++ b/foreign_cc/private/BUILD.bazel @@ -44,6 +44,7 @@ bzl_library( "//foreign_cc:providers", "//foreign_cc/private/framework:helpers", "//foreign_cc/private/framework:platform", + "@bazel_features//:features", "@bazel_skylib//lib:collections", "@bazel_skylib//lib:paths", "@bazel_tools//tools/cpp:toolchain_utils.bzl", diff --git a/foreign_cc/private/framework.bzl b/foreign_cc/private/framework.bzl index b4b8d63..892467e 100644 --- a/foreign_cc/private/framework.bzl +++ b/foreign_cc/private/framework.bzl @@ -2,6 +2,7 @@ with CMake, configure/make, autotools) """ +load("@bazel_features//:features.bzl", "bazel_features") load("@bazel_skylib//lib:collections.bzl", "collections") load("@bazel_skylib//lib:paths.bzl", "paths") load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") @@ -98,6 +99,14 @@ CC_EXTERNAL_RULE_ATTRIBUTES = { default = [], providers = [CcInfo], ), + "dynamic_deps": attr.label_list( + doc = ( + "Same as deps but for cc_shared_library." + ), + mandatory = False, + default = [], + # providers = [CcSharedLibraryInfo], + ), "env": attr.string_dict( doc = ( "Environment variables to set during the build. " + @@ -866,6 +875,19 @@ def _define_inputs(attrs): bazel_system_includes += headers_info.include_dirs bazel_libs += _collect_libs(dep[CcInfo].linking_context) + for dynamic_dep in attrs.dynamic_deps: + if not bazel_features.globals.CcSharedLibraryInfo: + fail("CcSharedLibraryInfo is only available in Bazel 7 or greater") + + linker_input = dynamic_dep[bazel_features.globals.CcSharedLibraryInfo].linker_input + bazel_libs += _collect_shared_libs(linker_input) + linking_context = cc_common.create_linking_context( + linker_inputs = depset(direct = [linker_input]), + ) + + # create a new CcInfo from the CcSharedLibraryInfo linker_input + cc_infos.append(CcInfo(linking_context = linking_context)) + # Keep the order of the transitive foreign dependencies # (the order is important for the correct linking), # but filter out repeating directories @@ -989,6 +1011,14 @@ def _collect_libs(cc_linking): libs.append(library) return collections.uniq(libs) +def _collect_shared_libs(cc_linker_input): + libs = [] + for library_to_link in cc_linker_input.libraries: + for library in _extract_libraries(library_to_link): + if library: + libs.append(library) + return collections.uniq(libs) + def expand_locations_and_make_variables(ctx, unexpanded, attr_name, data): """Expand locations and make variables while ensuring that `execpath` is always set to an absolute path diff --git a/foreign_cc/repositories.bzl b/foreign_cc/repositories.bzl index b62df75..6381c4e 100644 --- a/foreign_cc/repositories.bzl +++ b/foreign_cc/repositories.bzl @@ -83,6 +83,14 @@ def rules_foreign_cc_dependencies( if register_preinstalled_tools: preinstalled_toolchains() + maybe( + http_archive, + name = "bazel_features", + sha256 = "ba1282c1aa1d1fffdcf994ab32131d7c7551a9bc960fbf05f42d55a1b930cbfb", + strip_prefix = "bazel_features-1.15.0", + url = "https://github.com/bazel-contrib/bazel_features/releases/download/v1.15.0/bazel_features-v1.15.0.tar.gz", + ) + maybe( http_archive, name = "bazel_skylib",