Add flag for linux backend Adds a --@rules_libusb//:linux_backend flag to allow selection of udev/netlink as the backend for libusb. This prevents header-based autodetection, which isn't really hermetic, and also ensures -ludev is passed to the linker when the udev backend is enabled. Bug: b/358095928 Change-Id: Id27911b2587c94bd457fd5e68ecc27c87a2c9f1c Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/rules_libusb/+/275954 Reviewed-by: Ted Pudlik <tpudlik@google.com> Presubmit-Verified: CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com> Lint: Lint 🤖 <android-build-ayeaye@system.gserviceaccount.com> Commit-Queue: Auto-Submit <auto-submit@pigweed-service-accounts.iam.gserviceaccount.com> Pigweed-Auto-Submit: Armando Montanez <amontanez@google.com>
diff --git a/BUILD.bazel b/BUILD.bazel index ccfcf72..fd2d929 100644 --- a/BUILD.bazel +++ b/BUILD.bazel
@@ -12,13 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("@bazel_skylib//rules:common_settings.bzl", "bool_flag") +load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "string_flag") +load("@rules_cc//cc:cc_library.bzl", "cc_library") package(default_visibility = ["//visibility:public"]) cc_library( name = "libusb_linux_config", hdrs = ["linux/config.h"], + defines = select({ + ":use_udev": ["_RULES_LIBUSB_USE_UDEV=1"], + "//conditions:default": [], + }), ) cc_library( @@ -45,3 +50,22 @@ name = "force_dynamic_linkage_enabled", flag_values = {":force_dynamic_linkage": "True"}, ) + +string_flag( + name = "linux_backend", + build_setting_default = "netlink", + values = [ + "udev", + "netlink", + ], +) + +config_setting( + name = "use_udev", + flag_values = {":linux_backend": "udev"}, +) + +config_setting( + name = "use_netlink", + flag_values = {":linux_backend": "netlink"}, +)
diff --git a/MODULE.bazel b/MODULE.bazel index 8cdba89..8d2aea9 100644 --- a/MODULE.bazel +++ b/MODULE.bazel
@@ -4,6 +4,7 @@ ) bazel_dep(name = "platforms", version = "0.0.8") +bazel_dep(name = "rules_cc", version = "0.0.9") bazel_dep(name = "rules_license", version = "0.0.8") bazel_dep(name = "bazel_skylib", version = "1.5.0")
diff --git a/examples/basic_usage/BUILD.bazel b/examples/basic_usage/BUILD.bazel index 6517265..a33f914 100644 --- a/examples/basic_usage/BUILD.bazel +++ b/examples/basic_usage/BUILD.bazel
@@ -12,9 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +load("@rules_cc//cc:cc_test.bzl", "cc_test") + # This is enumerated as a test to ensure it is run and doesn't crash/fail. cc_test( name = "example", srcs = ["main.cc"], - deps = ["@libusb//:libusb"], + deps = ["@libusb"], )
diff --git a/examples/basic_usage/MODULE.bazel b/examples/basic_usage/MODULE.bazel index f98ebee..ce4337c 100644 --- a/examples/basic_usage/MODULE.bazel +++ b/examples/basic_usage/MODULE.bazel
@@ -1,5 +1,7 @@ module(name = "rules_libusb_basic_example") +bazel_dep(name = "rules_cc", version = "0.0.9") + bazel_dep(name = "rules_libusb") # DO NOT copy this into your project. This allows this repository to reference
diff --git a/libusb.BUILD b/libusb.BUILD index 87bd2e0..7a20766 100644 --- a/libusb.BUILD +++ b/libusb.BUILD
@@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_shared_library.bzl", "cc_shared_library") load("@rules_license//rules:license.bzl", "license") package( @@ -65,13 +67,17 @@ cc_library( name = "libusb_core", srcs = glob(["libusb/*.c"]), - visibility = ["//visibility:private"], + linkopts = select({ + "@platforms//os:windows": ["-DEFAULTLIB:AdvAPI32.Lib"], + "//conditions:default": [], + }), target_compatible_with = select({ "@platforms//os:linux": [], "@platforms//os:macos": [], "@platforms//os:windows": [], "//conditions:default": ["@platforms//:incompatible"], }), + visibility = ["//visibility:private"], deps = select({ "@platforms//os:linux": [":libusb_linux"], "@platforms//os:macos": [":libusb_macos"], @@ -81,10 +87,6 @@ ":libusb_config", ":libusb_headers", ], - linkopts = select({ - "@platforms//os:windows": ["-DEFAULTLIB:AdvAPI32.Lib"], - "//conditions:default": [], - }), ) label_flag( @@ -144,24 +146,6 @@ ], ) -# TODO: Consider upstreaming a build-system-independent method for detecting -# udev vs netlink. -_GENERATED_UDEV_OR_NETLINK = """ -#include "config.h" - -#if HAVE_LIBUDEV -#include "libusb/os/linux_udev.c" -#else -#include "libusb/os/linux_netlink.c" -#endif // HAVE_LIBUDEV -""" - -genrule( - name = "autodetect_udev", - outs = ["udev_or_netlink.c"], - cmd = "echo '{}' > $@".format(_GENERATED_UDEV_OR_NETLINK), -) - cc_library( name = "libusb_linux", srcs = glob( @@ -170,24 +154,26 @@ "libusb/os/linux_netlink.c", "libusb/os/linux_udev.c", ], - ) + [ - "udev_or_netlink.c", - ], - hdrs = glob(["libusb/os/linux_*.h"]) + [ - # These are listed as `hdrs` because they're selected by - # an `#include` in the generated `udev_or_netlink.c`. - "libusb/os/linux_netlink.c", - "libusb/os/linux_udev.c", - ], + ) + select({ + "@rules_libusb//:use_udev": ["libusb/os/linux_udev.c"], + "@rules_libusb//:use_netlink": ["libusb/os/linux_netlink.c"], + }), + hdrs = glob(["libusb/os/linux_*.h"]), + # linux_netlink.c passes a buffer pointer (`unsigned char*`) to a function + # expecting `char*`. + copts = ["-Wno-pointer-sign"], + linkopts = select({ + "@rules_libusb//:use_udev": ["-ludev"], + # When using netlink, `-lnl` doesn't appear to be necessary (adding it + # makes gcc complain the library can't be found). + "//conditions:default": [], + }), visibility = ["//visibility:private"], deps = [ ":libusb_config", ":libusb_headers", ":libusb_posix", ], - # linux_netlink.c passes a buffer pointer (`unsigned char*`) to a function - # expecting `char*`. - copts = ["-Wno-pointer-sign"], ) cc_library(
diff --git a/linux/config.h b/linux/config.h index 6fdfa0d..6a6bb72 100644 --- a/linux/config.h +++ b/linux/config.h
@@ -40,7 +40,7 @@ #define PLATFORM_POSIX 1 -/* Required for libusb < 1.0.24. */ +// Required for libusb < 1.0.24. #define THREADS_POSIX 1 #define POLL_NFDS_TYPE nfds_t #define USBI_TIMERFD_AVAILABLE 1 @@ -58,10 +58,20 @@ #define _GNU_SOURCE 1 -// Explicitly define HAVE_LIBUDEV to prevent auto-detection. -#ifndef HAVE_LIBUDEV -#if __has_include(<libudev.h>) +// Infer UDEV support from the Bazel build defines. +#if defined(_RULES_LIBUSB_USE_UDEV) && _RULES_LIBUSB_USE_UDEV #define HAVE_LIBUDEV 1 #define USE_UDEV 1 -#endif // __has_include(<libudev.h>) -#endif // HAVE_LIBUDEV +#endif // defined(_RULES_LIBUSB_USE_UDEV) && _RULES_LIBUSB_USE_UDEV + +#if defined(HAVE_LIBUDEV) && HAVE_LIBUDEV +// Check that libudev header can be found. +#if !__has_include(<libudev.h>) +#error "--@rules_libusb//:linux_backend=udev enabled, but no <libudev.h> header found." +#endif // !__has_include(<libudev.h>) +#else +// Check that netlink header can be found. +#if !__has_include(<linux/netlink.h>) +#error "--@rules_libusb//:linux_backend=netlink enabled, but no <linux/netlink.h> header found." +#endif // !__has_include(<libudev.h>) +#endif // defined(HAVE_LIBUDEV) && HAVE_LIBUDEV