Add rules_license and improve link flexibility

Change-Id: If4eb2b6851187ecf2c5e5cb974304f95656e40c7
diff --git a/BUILD.bazel b/BUILD.bazel
index 6084c64..ccfcf72 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -12,6 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
+
 package(default_visibility = ["//visibility:public"])
 
 cc_library(
@@ -30,3 +32,16 @@
         "//conditions:default": [],
     }),
 )
+
+# Forces libusb to always be dynamically linked. This defaults to True since
+# libusb is LGPL and that is usually the right thing. Be cautious when
+# statically linking and distributing binaries, as libusb is LGPL.
+bool_flag(
+    name = "force_dynamic_linkage",
+    build_setting_default = True,
+)
+
+config_setting(
+    name = "force_dynamic_linkage_enabled",
+    flag_values = {":force_dynamic_linkage": "True"},
+)
diff --git a/MODULE.bazel b/MODULE.bazel
index 9896d23..8cdba89 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -4,6 +4,8 @@
 )
 
 bazel_dep(name = "platforms", version = "0.0.8")
+bazel_dep(name = "rules_license", version = "0.0.8")
+bazel_dep(name = "bazel_skylib", version = "1.5.0")
 
 # If your project has versioning requirements for libusb, you'll need to specify
 # this in your project's MODULE.bazel.
diff --git a/README.md b/README.md
index 8a15f5d..a4d428c 100644
--- a/README.md
+++ b/README.md
@@ -20,18 +20,45 @@
 use_repo(libusb, "libusb")
 ```
 
+Note: `source_release` constraints follow bzlmod behavior of minimal version
+selection.
+
 Then add to the tool that requires libusb:
 ```
 cc_binary(
     name = "my_tool",
     srcs = ["main.cpp"],
-    deps = ["@libusb//:libusb_core"],  # Required for headers.
-    dynamic_deps = ["@libusb//:libusb"],  # Link against shared lib.
+    deps = ["@libusb//:libusb"],
 )
 ```
 
-Note: `source_release` constraints follow bzlmod behavior of minimal version
-selection.
+## Linking libusb
+
+The libusb build file offers two targets to help guide link behavior:
+
+* `//:libusb`: The generic `cc_library` for libusb. Most build targets should
+  just use this.
+* `//:libusb_dynamic`: The actual libusb dynamic/shared library (e.g.
+  `libusb-1.0.so`).
+
+By default, `@libusb//:libusb` will always dynamically link. This can be
+disabled by toggling the flag that controls this:
+```
+bazel build //... --@rules_libusb//:force_dynamic_linkage=False
+```
+
+When `@rules_libusb//:force_dynamic_linkage` is disabled, the link behavior is
+fully controlled by your build system, and can be controlled on a per-binary
+basis by specifying `dynamic_deps` on build targets that require dynamic
+linkage of libusb:
+```
+cc_binary(
+    name = "my_tool",
+    srcs = ["main.cpp"],
+    deps = ["@libusb//:libusb"],
+    dynamic_deps = ["@libusb//:libusb_dynamic"],
+)
+```
 
 ## Building this repo
 
diff --git a/libusb.BUILD b/libusb.BUILD
index 318c468..1c8c60b 100644
--- a/libusb.BUILD
+++ b/libusb.BUILD
@@ -12,26 +12,32 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Be careful about only depending on :libusb_core without specifying
-# :libusb in dynamic_deps! If you forget, libusb will be statically linked.
-cc_library(
-    name = "libusb_core",
-    srcs = glob(["libusb/*.c"]),
+load("@rules_license//rules:license.bzl", "license")
+
+package(
+    default_applicable_licenses = [":license"],
+    default_visibility = ["//visibility:private"],
+)
+
+license(
+    name = "license",
+    package_name = "libusb",
+    license_kinds = ["@rules_license//licenses/spdx:LGPL-2.1"],
+    license_text = "COPYING",
+)
+
+alias(
+    name = "libusb",
+    actual = select({
+        "@rules_libusb//:force_dynamic_linkage_enabled": ":libusb_force_dynamic",
+        "//conditions:default": ":libusb_core",
+    }),
     visibility = ["//visibility:public"],
-    deps = select({
-        "@platforms//os:linux": [":libusb_linux"],
-        "@platforms//os:macos": [":libusb_macos"],
-        "@platforms//os:windows": [":libusb_windows"],
-        "//conditions:default": ["@platforms//:incompatible"],
-    }) + [
-        ":libusb_config",
-        ":libusb_headers",
-    ],
 )
 
 cc_shared_library(
-    name = "libusb",
-    # Always use exactly this name.
+    name = "libusb_dynamic",
+    # Always use exactly these names.
     shared_lib_name = select({
         "@platforms//os:macos": "libusb-1.0.dylib",
         "@platforms//os:windows": "libusb-1.0.dll",
@@ -45,6 +51,32 @@
     deps = [":libusb_core"],
 )
 
+# This intermediate helper forces libusb to be dynamically linked.
+cc_library(
+    name = "libusb_force_dynamic",
+    srcs = [":libusb_dynamic"],
+    visibility = ["//visibility:private"],
+    deps = [
+        ":libusb_config",
+        ":libusb_headers",
+    ],
+)
+
+cc_library(
+    name = "libusb_core",
+    srcs = glob(["libusb/*.c"]),
+    visibility = ["//visibility:private"],
+    deps = select({
+        "@platforms//os:linux": [":libusb_linux"],
+        "@platforms//os:macos": [":libusb_macos"],
+        "@platforms//os:windows": [":libusb_windows"],
+        "//conditions:default": ["@platforms//:incompatible"],
+    }) + [
+        ":libusb_config",
+        ":libusb_headers",
+    ],
+)
+
 label_flag(
     name = "libusb_config",
     build_setting_default = "@rules_libusb//:default_libusb_config",