load(":cc_library_static.bzl", "cc_library_static") load("@rules_cc//examples:experimental_cc_shared_library.bzl", "CcSharedLibraryInfo", "cc_shared_library") def cc_library( name, # attributes for both targets srcs = [], hdrs = [], deps = [], whole_archive_deps = [], dynamic_deps = [], copts = [], includes = [], linkopts = [], # attributes for the shared target dynamic_deps_for_shared = [], shared_copts = [], shared_srcs = [], static_deps_for_shared = [], whole_archive_deps_for_shared = [], user_link_flags = [], version_script = None, # attributes for the static target dynamic_deps_for_static = [], static_copts = [], static_srcs = [], static_deps_for_static = [], whole_archive_deps_for_static = [], **kwargs): static_name = name + "_bp2build_cc_library_static" shared_name = name + "_bp2build_cc_library_shared" shared_root_name = name + "_bp2build_cc_library_shared_root" _cc_library_proxy( name = name, static = static_name, shared = shared_name, ) # The static version of the library. cc_library_static( name = static_name, hdrs = hdrs, srcs = srcs + static_srcs, copts = copts + static_copts, includes = includes, linkopts = linkopts, # TODO(b/187533117): Handle whole_archive_deps differently than other deps. deps = deps + static_deps_for_static + whole_archive_deps + whole_archive_deps_for_static, # TODO(b/187746106): Handle dynamic_deps_for_static. ) # The static library at the root of the shared library. # This may be distinct from the static library if, for example, # the static-variant srcs are different than the shared-variant srcs. cc_library_static( name = shared_root_name, hdrs = hdrs, srcs = srcs + shared_srcs, copts = copts + shared_copts, includes = includes, linkopts = linkopts, deps = deps + static_deps_for_shared + whole_archive_deps + whole_archive_deps_for_shared, ) cc_shared_library( name = shared_name, user_link_flags = user_link_flags, # b/184806113: Note this is a pretty a workaround so users don't have to # declare all transitive static deps used by this target. It'd be great # if a shared library could declare a transitive exported static dep # instead of needing to declare each target transitively. static_deps = ["//:__subpackages__"] + [shared_root_name], dynamic_deps = dynamic_deps + dynamic_deps_for_shared, version_script = version_script, roots = [shared_root_name] + whole_archive_deps + whole_archive_deps_for_shared, ) def _cc_library_proxy_impl(ctx): static_files = ctx.attr.static[DefaultInfo].files.to_list() shared_files = ctx.attr.shared[DefaultInfo].files.to_list() files = static_files + shared_files return [ ctx.attr.shared[CcSharedLibraryInfo], ctx.attr.static[CcInfo], DefaultInfo( files = depset(direct = files), runfiles = ctx.runfiles(files = files), ), ] _cc_library_proxy = rule( implementation = _cc_library_proxy_impl, attrs = { "shared": attr.label(mandatory = True, providers = [CcSharedLibraryInfo]), "static": attr.label(mandatory = True, providers = [CcInfo]), }, )