pax_global_header00006660000000000000000000000064144431466660014530gustar00rootroot0000000000000052 comment=e160ce519a3ab82d407bc57a0f0b0510d61a3a59 rules_license-0.0.7/000077500000000000000000000000001444314666600143705ustar00rootroot00000000000000rules_license-0.0.7/.bazelci/000077500000000000000000000000001444314666600160575ustar00rootroot00000000000000rules_license-0.0.7/.bazelci/postsubmit.yml000066400000000000000000000000251444314666600210100ustar00rootroot00000000000000imports: - tests.yml rules_license-0.0.7/.bazelci/presubmit.yml000066400000000000000000000000251444314666600206110ustar00rootroot00000000000000imports: - tests.yml rules_license-0.0.7/.bazelci/tests.yml000066400000000000000000000024761444314666600177550ustar00rootroot00000000000000 default_tests: &default_tests test_targets: - "//tests/..." - "//examples/..." - "-//examples/manifest/..." # # Bazel releases # lts: <s bazel: latest rolling: &rolling bazel: rolling # # Commmon features by platform # ubuntu2004: &ubuntu platform: ubuntu2004 <<: *default_tests build_targets: - "//distro:distro" - "//distro:relnotes" macos: &macos platform: macos <<: *default_tests windows: &windows platform: windows test_targets: - "//tests/..." - "//examples/..." - "-//examples/manifest/..." # The cross product of bazel releases X platforms # tasks: lts_ubuntu: name: lts_ubuntu <<: *ubuntu <<: *lts rolling_ubuntu: name: rolling_ubuntu <<: *ubuntu <<: *rolling lts_macos: name: lts_macos <<: *macos <<: *lts rolling_macos: name: rolling_macos <<: *macos # It seems there is no rolling Bazel for macos. bazel: last_green lts_windows: name: lts_windows <<: *windows <<: *lts rolling_windows: name: rolling_windows <<: *windows <<: *rolling # # Smoke test with bzlmod # bzlmod_rolling_ubuntu: name: bzlmod_rolling_ubuntu <<: *ubuntu <<: *rolling build_flags: - "--enable_bzlmod" build_targets: - "//distro:distro" - "//distro:relnotes" rules_license-0.0.7/.github/000077500000000000000000000000001444314666600157305ustar00rootroot00000000000000rules_license-0.0.7/.github/ISSUE_TEMPLATE.md000066400000000000000000000002021444314666600204270ustar00rootroot00000000000000## Expected Behavior ## Actual Behavior ## Steps to Reproduce the Problem 1. 1. 1. ## Specifications - Version: - Platform:rules_license-0.0.7/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000003231444314666600215270ustar00rootroot00000000000000Fixes # > It's a good idea to open an issue first for discussion. - [ ] Tests pass - [ ] Tests and examples for any new features. - [ ] Appropriate changes to README are included in PR rules_license-0.0.7/.gitignore000066400000000000000000000001301444314666600163520ustar00rootroot00000000000000admin/refresh_spdx/licenses.json bazel-bin bazel-out bazel-rules_license bazel-testlogs rules_license-0.0.7/BUILD000066400000000000000000000030771444314666600151610ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. load("@rules_license//rules:license.bzl", "license") load("@rules_license//rules:package_info.bzl", "package_info") load("@rules_license//:version.bzl", "version") package( default_applicable_licenses = [":license", ":package_info"], default_visibility = ["//visibility:public"], ) licenses(["notice"]) license( name = "license", license_kinds = [ "@rules_license//licenses/spdx:Apache-2.0", ], license_text = "LICENSE", ) package_info( name = "package_info", package_name = "rules_license", package_version = version, ) exports_files( ["LICENSE", "WORKSPACE"], visibility = ["//visibility:public"], ) exports_files( glob([ "*.bzl", ]), visibility = ["//visibility:public"], ) filegroup( name = "standard_package", srcs = glob([ "*.bzl", "*.md", ]) + [ "MODULE.bazel", "BUILD", "LICENSE", "WORKSPACE.bzlmod", ], visibility = ["//distro:__pkg__"], ) rules_license-0.0.7/CODEOWNERS000066400000000000000000000000111444314666600157530ustar00rootroot00000000000000* @aiuto rules_license-0.0.7/LICENSE000066400000000000000000000261361444314666600154050ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. rules_license-0.0.7/MODULE.bazel000066400000000000000000000012461444314666600163770ustar00rootroot00000000000000module( name = "rules_license", version = "0.0.7", # Keep in sync with version.bzl compatibility_level = 1, ) # NOTE: rules_license must not depend on any other repositories if you are # just using basic rules under //rules/... and //licenses/... # TODO(aiuto): Create an extension to enable the rules under //tools/... # That will require rules_python, which we do not want to force on people who # do not need //tools. # Only for development bazel_dep(name = "rules_pkg", version = "0.7.0", dev_dependency = True) bazel_dep(name = "rules_python", version = "0.23.0", dev_dependency = True) bazel_dep(name = "stardoc", version = "0.5.3", dev_dependency = True) rules_license-0.0.7/README.md000066400000000000000000000032411444314666600156470ustar00rootroot00000000000000# rules_license CI: [![Build status](https://badge.buildkite.com/e12f23186aa579f1e20fcb612a22cd799239c3134bc38e1aff.svg)](https://buildkite.com/bazel/rules-license) This repository contains a set of rules and tools for - declaring metadata about packages, such as - the licenses the package is available under - the canonical package name and version - copyright information - ... and more TBD in the future - gathering those license declarations into artifacts to ship with code - applying organization specific compliance constriants against the set of packages used by a target. - (eventually) producing SBOMs for built artifacts. WARNING: The code here is still in active initial development and will churn a lot. If you want to follow along: - Mailing list: [bazel-ssc@bazel.build](https://groups.google.com/a/bazel.build/g/bazel-ssc) - Monthly eng meeting: [calendar link](MjAyMjA4MjJUMTYwMDAwWiBjXzUzcHBwZzFudWthZXRmb3E5NzhxaXViNmxzQGc&tmsrc=c_53pppg1nukaetfoq978qiub6ls%40group.calendar.google.com&scp=ALL) - [Latest docs](https://bazelbuild.github.io/rules_license/latest.html) Background reading: These is for learning about the problem space, and our approach to solutions. Concrete specifications will always appear in checked in code rather than documents. - [License Checking with Bazel](https://docs.google.com/document/d/1uwBuhAoBNrw8tmFs-NxlssI6VRolidGYdYqagLqHWt8/edit#). - [OSS Licenses and Bazel Dependency Management](https://docs.google.com/document/d/1oY53dQ0pOPEbEvIvQ3TvHcFKClkimlF9AtN89EPiVJU/edit#) - [Adding OSS license declarations to Bazel](https://docs.google.com/document/d/1XszGbpMYNHk_FGRxKJ9IXW10KxMPdQpF5wWbZFpA4C8/edit#heading=h.5mcn15i0e1ch) rules_license-0.0.7/WORKSPACE000066400000000000000000000042671444314666600156620ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. workspace(name = "rules_license") # rules_license has no dependencies for basic license and package_info # declarations. # # If you want to use any of the reporting or SBOM tools, and you are using a # WORKSPACE file instead of bzlmod, they you must explicitly depend on # rules_python in your WORKSPACE. ### INTERNAL ONLY - lines after this are not included in the release packaging. load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "rules_python", sha256 = "ffc7b877c95413c82bfd5482c017edcf759a6250d8b24e82f41f3c8b8d9e287e", strip_prefix = "rules_python-0.19.0", urls = [ "https://github.com/bazelbuild/rules_python/releases/download/0.19.0/rules_python-0.19.0.tar.gz", ], ) http_archive( name = "rules_pkg", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/rules_pkg/releases/download/0.8.0/rules_pkg-0.8.0.tar.gz", "https://github.com/bazelbuild/rules_pkg/releases/download/0.8.0/rules_pkg-0.8.0.tar.gz", ], sha256 = "eea0f59c28a9241156a47d7a8e32db9122f3d50b505fae0f33de6ce4d9b61834", ) load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies") rules_pkg_dependencies() http_archive( name = "io_bazel_stardoc", sha256 = "3fd8fec4ddec3c670bd810904e2e33170bedfe12f90adf943508184be458c8bb", urls = [ "https://mirror.bazel.build/github.com/bazelbuild/stardoc/releases/download/0.5.3/stardoc-0.5.3.tar.gz", "https://github.com/bazelbuild/stardoc/releases/download/0.5.3/stardoc-0.5.3.tar.gz", ], ) load("@io_bazel_stardoc//:setup.bzl", "stardoc_repositories") stardoc_repositories() rules_license-0.0.7/WORKSPACE.bzlmod000066400000000000000000000006511444314666600171410ustar00rootroot00000000000000load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") # This is needed for tools maybe( http_archive, name = "rules_python", sha256 = "b593d13bb43c94ce94b483c2858e53a9b811f6f10e1e0eedc61073bd90e58d9c", strip_prefix = "rules_python-0.12.0", url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.12.0.tar.gz", ) rules_license-0.0.7/admin/000077500000000000000000000000001444314666600154605ustar00rootroot00000000000000rules_license-0.0.7/admin/refresh_spdx/000077500000000000000000000000001444314666600201545ustar00rootroot00000000000000rules_license-0.0.7/admin/refresh_spdx/README.md000066400000000000000000000007771444314666600214460ustar00rootroot00000000000000# Tools to refresh SPDX license list ## Update //licenses/spdx This pulls in the authoritative list of licenses from the SPDX project and updates our copy of it to include any new license identifiers. It does not attempt to classify them in any way. NOTE: You must run this from //admin/refresh_spdx 1. Fetch the license list from the SPDX project. ```bash wget https://github.com/spdx/license-list-data/raw/master/json/licenses.json ``` 1. Run the refresh tool python add_licenses.py rules_license-0.0.7/admin/refresh_spdx/add_licenses.py000077500000000000000000000075611444314666600231570ustar00rootroot00000000000000#!/usr/bin/env python3 """Refresh the BUILD file of SPDX license_kinds with new ones from licenses.json. Usage: wget https://github.com/spdx/license-list-data/raw/master/json/licenses.json LC_ALL="en_US.UTF-8" admin/refresh_spdx/add_licenses.py git diff git commit """ import json import os from string import Template import re import sys def load_json(path: str): """Loads a JSON file and returns the data. Args: path: (str) a file path. Returns: (dict) the parsed data. """ with open(path, 'r') as fp: ret = json.load(fp) return ret def parse_build_file(text: str): """Parse a BUILD file of license declaration. Parses a build file and returns all the text that is not licenese_kind declarations and a map of license kind names to the text which declared them license_kind( name = "0BSD", conditions = [], url = "https://spdx.org/licenses/0BSD.html", ) Returns: preamble: str targets: map """ target_start = re.compile(r'^([a-zA-Z0-9_]+)\(') # ) to fix autoindent name_match = re.compile(r'^ *name *= *"([^"]*)"') targets = {} preamble = [] collecting_rule = None for line in text.split('\n'): if collecting_rule: collecting_rule.append(line) if line.startswith(')'): assert cur_name targets[cur_name] = '\n'.join(collecting_rule) # print(cur_name, "=====", targets[cur_name]) collecting_rule = None cur_name = None else: m = name_match.match(line) if m: cur_name = m.group(1) continue # not collecting a rule m = target_start.match(line) if m: cur_rule = m.group(1) if cur_rule == 'license_kind': collecting_rule = [line] continue if line or preamble[-1]: preamble.append(line) return '\n'.join(preamble), targets # Sample JSON formate license declaration. """ { "licenseListVersion": "3.8-57-gca4f142", "licenses": [ { "reference": "./0BSD.html", "isDeprecatedLicenseId": false, "detailsUrl": "http://spdx.org/licenses/0BSD.json", "referenceNumber": "232", "name": "BSD Zero Clause License", "licenseId": "0BSD", "seeAlso": [ "http://landley.net/toybox/license.html" ], "isOsiApproved": true }, """ def insert_new(already_declared, licenses): template = Template(( 'license_kind(\n' ' name = "${licenseId}",\n' ' conditions = [],\n' ' url = "https://spdx.org/licenses/${licenseId}.html",\n' ')')) for license in licenses: id = license['licenseId'] old = already_declared.get(id) if not old: print('Adding:', id) already_declared[id] = template.substitute(license) def update_spdx_build(): """Update //licenses/spdx/BUILD with new license kinds.""" license_json = load_json('licenses.json') # Find workspace root build_path = 'licenses/spdx/BUILD' found_spdx_build = False for i in range(5): # Simple regression failure limiter if os.access('WORKSPACE', os.R_OK) and os.access(build_path, os.R_OK): found_spdx_build = True break os.chdir('..') if not found_spdx_build: print('Could not find', build_path) return 1 with open(build_path, 'r') as fp: current_file_content = fp.read() preamble, kinds = parse_build_file(current_file_content) insert_new(kinds, license_json['licenses']) with open(build_path, 'w') as fp: fp.write(preamble) for license in sorted(kinds.keys(), key=lambda x: x.lower()): fp.write('\n') fp.write(kinds[license]) fp.write('\n') def main(): lc_all = os.environ.get('LC_ALL') if lc_all != 'en_US.UTF-8': print('Your environment settings will reorder the file badly.') print('Please rerun as:') print(' LC_ALL="en_US.UTF-8"', ' '.join(sys.argv)) sys.exit(1) update_spdx_build() if __name__ == '__main__': main() rules_license-0.0.7/deps.bzl000066400000000000000000000012751444314666600160410ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Workspace dependencies for rules_license/rules.""" def rules_license_dependencies(): pass rules_license-0.0.7/distro/000077500000000000000000000000001444314666600156745ustar00rootroot00000000000000rules_license-0.0.7/distro/BUILD000066400000000000000000000041021444314666600164530ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. load("//:version.bzl", "version") load("@rules_pkg//pkg:pkg.bzl", "pkg_tar") load("@rules_pkg//pkg/releasing:defs.bzl", "print_rel_notes") package( default_visibility = ["//visibility:public"], default_applicable_licenses = ["//:license"], ) licenses(["notice"]) alias( name = "distro", actual = "rules_license-%s" % version, ) # Build the artifact to put on the github release page. pkg_tar( name = "rules_license-%s" % version, srcs = [ ":small_workspace", "//:standard_package", "//licenses/generic:standard_package", "//licenses/spdx:standard_package", "//rules:standard_package", "//rules_gathering:standard_package", "//rules/private:standard_package", "//sample_reports:standard_package", "//tools:standard_package", ], extension = "tar.gz", # It is all source code, so make it read-only. mode = "0444", # Make it owned by root so it does not have the uid of the CI robot. owner = "0.0", package_dir = ".", strip_prefix = ".", tags = [ "no_windows", ], ) genrule( name = "small_workspace", srcs = ["//:WORKSPACE"], outs = ["WORKSPACE"], cmd = "sed -e '/### INTERNAL ONLY/,$$d' $(location //:WORKSPACE) >$@", tags = [ "no_windows", ], ) print_rel_notes( name = "relnotes", outs = ["relnotes.txt"], mirror_host = "mirror.bazel.build", org = "bazelbuild", repo = "rules_license", version = version, ) rules_license-0.0.7/distro/check_build.sh000077500000000000000000000025641444314666600204760ustar00rootroot00000000000000#!/bin/bash -ef # # This is a temporary hack to verify the distribution archive is sound. # # The intent is to create a rule which does this and add to # rules_pkg. Comments within it are mostly for future me # while writing that. TARBALL=$(bazel build //distro:distro 2>&1 | grep 'rules_license-.*\.tar\.gz' | sed -e 's/ //g') REPO_NAME='rules_license' # This part can be standard from the rule TARNAME=$(basename "$TARBALL") TMP=$(mktemp -d) trap '/bin/rm -rf "$TMP"; exit 0' 0 1 2 3 15 cp "$TARBALL" "$TMP" cd "$TMP" cat >WORKSPACE <BUILD <LICENSE # Then a list of commands to run. This can be a template # too so we can substitute the path to bazel. bazel build ... bazel build @rules_license//rules/... bazel build @rules_license//licenses/... bazel query @rules_license//licenses/generic/... bazel query ... rules_license-0.0.7/doc_build/000077500000000000000000000000001444314666600163145ustar00rootroot00000000000000rules_license-0.0.7/doc_build/BUILD000066400000000000000000000060541444314666600171030ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Generate the reference documentation. How to: bazel build //doc_build:reference cp bazel-bin/doc_build/reference.md docs/latest.md git commit -m 'update docs' docs/latest.md """ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("@io_bazel_stardoc//stardoc:stardoc.bzl", "stardoc") load("@rules_python//python:defs.bzl", "py_library") load("//:version.bzl", "version") package(default_package_metadata = ["//:license", "//:package_info"]) filegroup( name = "standard_package", srcs = [ "BUILD", ] + glob([ "*.bzl", "*.py", ]), visibility = ["//distro:__pkg__"], ) exports_files( glob([ "*.bzl", ]), visibility = [ "//distro:__pkg__", ], ) # pairs of rule name and the source file to get it from # Must put macro wrapped rules after their wrapper # buildifier: leave-alone, do not sort ORDER = [ ("license", "//rules:license.bzl"), ("_license", "//rules:license.bzl"), ("license_kind", "//rules:license_kind.bzl"), ("_license_kind", "//rules:license_kind.bzl"), ("package_info", "//rules:package_info.bzl"), ("_package_info", "//rules:package_info.bzl"), ("LicenseInfo", "//rules:providers.bzl"), ("LicenseKindInfo", "//rules:providers.bzl"), ("PackageInfo", "//rules:providers.bzl"), ("gather_metadata_info", "//rules_gathering:gather_metadata.bzl"), ("gather_metadata_info_and_write", "//rules_gathering:gather_metadata.bzl"), ("trace", "//rules_gathering:trace.bzl"), ] genrule( name = "reference", srcs = ["%s.md" % rule for rule, _ in ORDER], outs = ["reference.md"], cmd = "$(location :merge) $(SRCS) >$@", tools = [":merge"], ) [ stardoc( name = "%s_gen" % rule, out = "%s.md" % rule, input = src, symbol_names = [ rule, ], deps = [":lib_of_everything"], ) for rule, src in ORDER if src ] # gather all rules that should be documented bzl_library( name = "lib_of_everything", srcs = [ "//:version.bzl", "//rules:standard_package", "//rules_gathering:standard_package", ], visibility = ["//visibility:public"], ) # This is experimental. We are waiting for stardoc to get the features which # are done in merge. py_binary( name = "merge", srcs = ["merge.py"], python_version = "PY3", srcs_version = "PY3", visibility = ["//visibility:private"], ) rules_license-0.0.7/doc_build/merge.py000077500000000000000000000052441444314666600177750ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """merge stardoc output into a single page. - concatenates files - corrects things that stardoc botches """ import re import sys import typing # I think stardoc changed the format of the id strings. Sigh. ID_RE = re.compile(r'') ID_OLD_RE = re.compile(r'') WRAPS_RE = re.compile(r'@wraps\((.*)\)') SINCE_RE = re.compile(r'@since\(([^)]*)\)') CENTER_RE = re.compile(r'

([^<]*)

') def merge_file(file: str, out, wrapper_map:typing.Dict[str, str]) -> None: with open(file, 'r') as inp: content = inp.read() m = ID_RE.search(content) if not m: m = ID_OLD_RE.search(content) this_rule = m.group(1) if m else None m = WRAPS_RE.search(content) if m: # I wrap something, so don't emit me. wrapper_map[m.group(1)] = this_rule return # If something wraps me, rewrite myself with the wrapper name. if this_rule in wrapper_map: content = content.replace(this_rule, wrapper_map[this_rule]) merge_text(content, out) def merge_text(text: str, out) -> None: """Merge a block of text into an output stream. Args: text: block of text produced by Starroc. out: an output file stream. """ for line in text.split('\n'): line = SINCE_RE.sub(r'
Since \1
', line) if line.startswith('| :'): line = fix_stardoc_table_align(line) # Compensate for https://github.com/bazelbuild/stardoc/issues/118. # Convert escaped HTML
  • back to raw text line = line.replace('<li>', '
  • ') line = CENTER_RE.sub(r'\1', line) _ = out.write(line) _ = out.write('\n') def fix_stardoc_table_align(line: str) -> str: """Change centered descriptions to left justified.""" if line.startswith('| :-------------: | :-------------: '): return '| :------------ | :--------------- | :---------: | :---------: | :----------- |' return line def main(argv: typing.Sequence[str]) -> None: wrapper_map = {} for file in argv[1:]: merge_file(file, sys.stdout, wrapper_map) if __name__ == '__main__': main(sys.argv) rules_license-0.0.7/docs/000077500000000000000000000000001444314666600153205ustar00rootroot00000000000000rules_license-0.0.7/docs/CODE_OF_CONDUCT.md000066400000000000000000000106241444314666600201220ustar00rootroot00000000000000# Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. This Code of Conduct also applies outside the project spaces when the Project Steward has a reasonable belief that an individual's behavior may have a negative impact on the project or its community. ## Conflict Resolution We do not believe that all conflict is bad; healthy debate and disagreement often yield positive results. However, it is never okay to be disrespectful or to engage in behavior that violates the project’s code of conduct. If you see someone violating the code of conduct, you are encouraged to address the behavior directly with those involved. Many issues can be resolved quickly and easily, and this gives people more control over the outcome of their dispute. If you are unable to resolve the matter for any reason, or if the behavior is threatening or harassing, report it. We are dedicated to providing an environment where participants feel welcome and safe. Reports should be directed to Tony Aiuto (aiuto@google.com), the Project Steward(s) for bazelbuild/rules_license. It is the Project Steward’s duty to receive and address reported violations of the code of conduct. They will then work with a committee consisting of representatives from the Open Source Programs Office and the Google Open Source Strategy team. If for any reason you are uncomfortable reaching out to the Project Steward, please email opensource@google.com. We will investigate every complaint, but you may not receive a direct response. We will use our discretion in determining when and how to follow up on reported incidents, which may range from not taking action to permanent expulsion from the project and project-sponsored spaces. We will notify the accused of the report and provide them an opportunity to discuss it before any action is taken. The identity of the reporter will be omitted from the details of the report supplied to the accused. In potentially harmful situations, such as ongoing harassment or threats to anyone's safety, we may take action without notice. ## Attribution This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html rules_license-0.0.7/docs/CONTRIBUTING.md000066400000000000000000000023601444314666600175520ustar00rootroot00000000000000# How to Contribute We'd love to accept your patches and contributions to this project. There are just a few small guidelines you need to follow. ## Contributor License Agreement Contributions to this project must be accompanied by a Contributor License Agreement (CLA). You (or your employer) retain the copyright to your contribution; this simply gives us permission to use and redistribute your contributions as part of the project. Head over to to see your current agreements on file or to sign a new one. You generally only need to submit a CLA once, so if you've already submitted one (even if it was for a different project), you probably don't need to do it again. ## Code reviews All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more information on using pull requests. All issues that modify the license rules require a github issue first. We will use that issue for public discussion of the merits and potential implementation. ## Community Guidelines This project follows [Google's Open Source Community Guidelines](https://opensource.google/conduct/). rules_license-0.0.7/docs/_config.yml000066400000000000000000000000321444314666600174420ustar00rootroot00000000000000theme: jekyll-theme-caymanrules_license-0.0.7/docs/_includes/000077500000000000000000000000001444314666600172655ustar00rootroot00000000000000rules_license-0.0.7/docs/_includes/head-custom.html000066400000000000000000000003251444314666600223640ustar00rootroot00000000000000 rules_license-0.0.7/docs/_includes/head.html000066400000000000000000000000631444314666600210530ustar00rootroot00000000000000 rules_license-0.0.7/docs/favicon.ico000077500000000000000000000124661444314666600174550ustar00rootroot00000000000000 h&  (  V3VpC3VppCC3^ pp%{ZCC B 6{3(p%{E@C@ZCa6{36{3GC(%{E@GCGCC@ZaGC6{36{3GCGC4&E@GCGCGCGCC@)x&GCGC6{37VGCGCROiiJFGCGCGCGCJFjiROGCGC7V7VGCROssuvkkJFGCGCJFlluvssROGC7V7VROssuvuvuvkkJFJFlluvuvuvssRO7V2Fssuvuvuvuvuveeeeuvuvuvuvuvss2F8e9zuvuvuvuvno/4/4nouvuvuvuv8e9z8e9zuvuvno/4/4nouvuv8e9z8e9zno/4/4no8e9z    ?( @ 222i?22ipC?22ippCC?22ipppCCC?22ippppCCCC?22ipppppCCCCC?22ippppptJCCCCC?2"23(pppppt?7:7JCCCCC*v("2"2B?7,ppppt?7GCGC:7JCCCC.,B?"2"2B?GC7,pppt?7GCGCGCGC:7JCCC.,GCB?"2"2B?GCGC7,ppt?7GCGCGCGCGCGC:7JCC.,GCGCB?"2"2B?GCGCGC7,pt?7GCGCGCGCGCGCGCGC:7JC.,GCGCGCB?"2"2B?GCGCGCGC7,t?7GCGCGCGCGCGCGCGCGCGC:7J.,GCGCGCGCB?"2"2B?GCGCGCGCGC;1?7GCGCGCGCGCGCGCGCGCGCGCGC:741GCGCGCGCGCB?"20n.GCGCGCGCGCJGkkSPGCGCGCGCGCGCGCGCGCGCGCGCTQkkJGGCGCGCGCGC0n.0n.GCGCGCGCJGmmuvstSPGCGCGCGCGCGCGCGCGCGCTQstuvmmJGGCGCGCGC0n.0n.GCGCGCJGmmuvuvuvstSPGCGCGCGCGCGCGCGCTQstuvuvuvmmJGGCGCGC0n.0n.GCGCJGmmuvuvuvuvuvstSPGCGCGCGCGCGCTQstuvuvuvuvuvmmJGGCGC0n.0n.GCJGmmuvuvuvuvuvuvuvstSPGCGCGCGCTQstuvuvuvuvuvuvuvmmJGGC0n.0n.JGmmuvuvuvuvuvuvuvuvuvstSPGCGCTQstuvuvuvuvuvuvuvuvuvmmJG0n.4r2mmuvuvuvuvuvuvuvuvuvuvuvstSPTQstuvuvuvuvuvuvuvuvuvuvuvmm4r20X0huvuvuvuvuvuvuvuvuvuvuvuvuvZZZ[uvuvuvuvuvuvuvuvuvuvuvuvuv0X0h6b7ruvuvuvuvuvuvuvuvuvuvuv[\    [\uvuvuvuvuvuvuvuvuvuvuv6b7r6b7ruvuvuvuvuvuvuvuvuv[\    [\uvuvuvuvuvuvuvuvuv6b7r6b7ruvuvuvuvuvuvuv[\    [\uvuvuvuvuvuvuv6b7r6b7ruvuvuvuvuv[\    [\uvuvuvuvuv6b7r6b7ruvuvuv[\    [\uvuvuv6b7r6b7ruv[\    [\uv6b7r+M+V    +M+V????rules_license-0.0.7/docs/index.md000066400000000000000000000003071444314666600167510ustar00rootroot00000000000000# bazelbuild/rules_license Bazel rules for defining and using package licensing and other metadata Use bazel-ssc@bazel.build for discussion. ## Reference * [Latest Snapshot at head](latest.md) rules_license-0.0.7/docs/latest.md000077500000000000000000000260431444314666600171460ustar00rootroot00000000000000 Rules for declaring the compliance licenses used by a package. ## license
    license(name, copyright_notice, license_kinds, license_text, package_name, package_url,
             package_version)
    
    **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | copyright_notice | Copyright notice. | String | optional | "" | | license_kinds | License kind(s) of this license. If multiple license kinds are listed in the LICENSE file, and they all apply, then all should be listed here. If the user can choose a single one of many, then only list one here. | List of labels | optional | [] | | license_text | The license file. | Label | optional | LICENSE | | package_name | A human readable name identifying this package. This may be used to produce an index of OSS packages used by an applicatation. | String | optional | "" | | package_url | The URL this instance of the package was download from. This may be used to produce an index of OSS packages used by an applicatation. | String | optional | "" | | package_version | A human readable version string identifying this package. This may be used to produce an index of OSS packages used by an applicatation. It should be a value that increases over time, rather than a commit hash. | String | optional | "" | Proof of concept. License restriction. ## license_kind
    license_kind(name, canonical_text, conditions, long_name, url)
    
    **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | canonical_text | File containing the canonical text for this license. Must be UTF-8 encoded. | Label | optional | None | | conditions | Conditions to be met when using software under this license. Conditions are defined by the organization using this license. | List of strings | required | | | long_name | Human readable long name of license. | String | optional | "" | | url | URL pointing to canonical license definition | String | optional | "" | Rules for declaring metadata about a package. ## package_info
    package_info(name, package_name, package_url, package_version)
    
    **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | | package_name | A human readable name identifying this package. This may be used to produce an index of OSS packages used by an applicatation. | String | optional | "" | | package_url | The URL this instance of the package was download from. This may be used to produce an index of OSS packages used by an applicatation. | String | optional | "" | | package_version | A human readable version string identifying this package. This may be used to produce an index of OSS packages used by an applicatation. It should be a value that increases over time, rather than a commit hash. | String | optional | "" | Basic providers for license rules. This file should only contain the basic providers needed to create license and package_info declarations. Providers needed to gather them are declared in other places. ## LicenseInfo
    LicenseInfo(copyright_notice, label, license_kinds, license_text, package_name, package_url,
                package_version)
    
    Provides information about a license instance. **FIELDS** | Name | Description | | :------------- | :------------- | | copyright_notice | string: Human readable short copyright notice | | label | Label: label of the license rule | | license_kinds | list(LicenseKindInfo): License kinds | | license_text | string: The license file path | | package_name | string: Human readable package name | | package_url | URL from which this package was downloaded. | | package_version | Human readable version string | Basic providers for license rules. This file should only contain the basic providers needed to create license and package_info declarations. Providers needed to gather them are declared in other places. ## LicenseKindInfo
    LicenseKindInfo(conditions, label, long_name, name)
    
    Provides information about a license_kind instance. **FIELDS** | Name | Description | | :------------- | :------------- | | conditions | list(string): List of conditions to be met when using this packages under this license. | | label | Label: The full path to the license kind definition. | | long_name | string: Human readable license name | | name | string: Canonical license name | Basic providers for license rules. This file should only contain the basic providers needed to create license and package_info declarations. Providers needed to gather them are declared in other places. ## PackageInfo
    PackageInfo(type, label, package_name, package_url, package_version)
    
    Provides information about a package. **FIELDS** | Name | Description | | :------------- | :------------- | | type | string: How to interpret data | | label | Label: label of the package_info rule | | package_name | string: Human readable package name | | package_url | string: URL from which this package was downloaded. | | package_version | string: Human readable version string | Rules and macros for collecting LicenseInfo providers. ## gather_metadata_info
    gather_metadata_info(name)
    
    Collects LicenseInfo providers into a single TransitiveMetadataInfo provider. **ASPECT ATTRIBUTES** | Name | Type | | :------------- | :------------- | | *| String | **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | Rules and macros for collecting LicenseInfo providers. ## gather_metadata_info_and_write
    gather_metadata_info_and_write(name)
    
    Collects TransitiveMetadataInfo providers and writes JSON representation to a file. Usage: bazel build //some:target --aspects=@rules_license//rules:gather_metadata_info.bzl%gather_metadata_info_and_write --output_groups=licenses **ASPECT ATTRIBUTES** | Name | Type | | :------------- | :------------- | | *| String | **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | Rules and macros for collecting package metdata providers. ## trace
    trace(name)
    
    Used to allow the specification of a target to trace while collecting license dependencies. **ATTRIBUTES** | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | rules_license-0.0.7/examples/000077500000000000000000000000001444314666600162065ustar00rootroot00000000000000rules_license-0.0.7/examples/BUILD000066400000000000000000000000311444314666600167620ustar00rootroot00000000000000# rules_license examples rules_license-0.0.7/examples/README.md000066400000000000000000000011721444314666600174660ustar00rootroot00000000000000# Examples for rules_license This set of files provides an example of how license rules can be used. Terminology - Organization: A company, organization or other entity that wants to use license rules to enforce their particular compliance needs. These examples use the work organization throughout. - SCM: source code management system. These examples assume that an organization has a SCM that can enforce ownership restrictions on specific folder trees. Targets are divided into BUILD files that are reviewed by engineers vs. those that are reviewed by an organizations compliance team. ## Overview rules_license-0.0.7/examples/manifest/000077500000000000000000000000001444314666600200145ustar00rootroot00000000000000rules_license-0.0.7/examples/manifest/BUILD000066400000000000000000000023201444314666600205730ustar00rootroot00000000000000load(":android_mock.bzl", "android_binary", "android_library") load("@rules_license//tools:test_helpers.bzl", "golden_cmd_test") # These two rules today capture what an android_binary would look like. # This rule represents the Android specific code that displays licenses # on the display. Note that it does not depend on anything to get the # license contents; the implementation of these rules macros handle that # detail. android_library( name = "licenses", srcs = [ "license_display.sh", ], data = [ "@rules_license//distro:distro", ], ) # This captures how the application would be built. The dependencies of this # rule are crawled to identify third-party licenses in use. The macro definition # of this rule creates a graph to capture that process of identifying licenses, # building the licenses target, and finally invoking the "real" android_binary # rule to build the final output with the injected license content. android_binary( name = "main", srcs = ["main.sh"], deps = [ ], data = [ ":licenses", ], ) golden_cmd_test( name = "main_test", srcs = [], cmd = "$(location :main)", tools = [":main"], golden = "main_golden.txt", ) rules_license-0.0.7/examples/manifest/android_mock.bzl000066400000000000000000000037051444314666600231630ustar00rootroot00000000000000load("manifest.bzl", "manifest") """This is a proof of concept to show how to modify a macro definition to create a sub-graph allowing for build time injection of license information. We use Android-inspired rule names since these are a likely candidate for this sort of injection.""" def android_library(name, **kwargs): # This is an approximation for demo purposes. data = kwargs.pop("data", []) native.filegroup( name = name, srcs = data + kwargs.get("srcs", []), ) # Inject the data dependency into the library, preserving any other data it has. native.sh_library( name = name + "_w_licenses", data = data + [name + "_manifest.txt"], **kwargs ) def android_binary(name, **kwargs): # Same observation about not being sloppy with mapping deps, but I think the only important attribute # in android_binary is deps, but need to double-check. native.filegroup( name = name + "_no_licenses", srcs = kwargs.get("data", []), ) mf_name = name + "_manifest" manifest( name = mf_name, deps = [":" + name + "_no_licenses"], ) # This uses the conditions tool to generate an approximation of a compliance report # to demonstrate how license data can be plumbed and made available at build time. native.genrule( name = "gen_" + name + "_manifest", srcs = [":" + mf_name], outs = ["licenses_manifest.txt"], cmd = "cat $(locations :%s) > $@" % mf_name, ) # Swap out the :licenses dep for our new :licenses_w_licenses dep newdeps = [] deps = kwargs.get("data", []) for dep in deps: if dep == ":licenses": newdeps.append(":licenses_w_licenses") else: newdeps.append(dep) kwargs["data"] = newdeps # Compile the executable with the user's originally supplied name, but with the new content. native.sh_binary( name = name, **kwargs ) rules_license-0.0.7/examples/manifest/license_display.sh000066400000000000000000000002231444314666600235140ustar00rootroot00000000000000#!/bin/bash function display_licenses { echo -n "Licenses: " cat "$0.runfiles/rules_license/examples/manifest/licenses_manifest.txt" echo } rules_license-0.0.7/examples/manifest/main.sh000077500000000000000000000005421444314666600213000ustar00rootroot00000000000000#!/bin/bash #source gbash.sh || exit #source "$RUNFILES/google3/tools/build_defs/license/examples/manifest/license_display.sh" source "$0.runfiles/rules_license/examples/manifest/license_display.sh" #source module google3/tools/build_defs/license/examples/manifest/license_display.sh echo "I am a program that uses open source code." display_licenses rules_license-0.0.7/examples/manifest/main_golden.txt000066400000000000000000000543621444314666600230430ustar00rootroot00000000000000I am a program that uses open source code. Licenses: Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. rules_license-0.0.7/examples/manifest/manifest.bzl000066400000000000000000000056541444314666600223450ustar00rootroot00000000000000# Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """An example using gather_licenses_info as input to another action.""" load( "@rules_license//rules:gather_licenses_info.bzl", "gather_licenses_info", ) load( "@rules_license//rules_gathering:gathering_providers.bzl", "TransitiveLicensesInfo", ) def get_licenses_mapping(deps, warn = False): """Creates list of entries representing all licenses for the deps. Args: deps: a list of deps which should have TransitiveLicensesInfo providers. This requires that you have run the gather_licenses_info aspect over them warn: boolean, if true, display output about legacy targets that need update Returns: {File:package_name} """ tls = [] for dep in deps: lds = dep[TransitiveLicensesInfo].licenses tls.append(lds) ds = depset(transitive = tls) # Ignore any legacy licenses that may be in the report mappings = {} for lic in ds.to_list(): if type(lic.license_text) == "File": mappings[lic.license_text] = lic.package_name elif warn: print("Legacy license %s not included, rule needs updating" % lic.license_text) return mappings def _manifest_impl(ctx): # Gather all licenses and make it available as deps for downstream rules # Additionally write the list of license filenames to a file that can # also be used as an input to downstream rules. licenses_file = ctx.actions.declare_file(ctx.attr.out.name) mappings = get_licenses_mapping(ctx.attr.deps, ctx.attr.warn_on_legacy_licenses) ctx.actions.write( output = licenses_file, content = "\n".join([",".join([f.path, p]) for (f, p) in mappings.items()]), ) return [DefaultInfo(files = depset(mappings.keys()))] _manifest = rule( implementation = _manifest_impl, doc = """Internal tmplementation method for manifest().""", attrs = { "deps": attr.label_list( doc = """List of targets to collect license files for.""", aspects = [gather_licenses_info], ), "out": attr.output( doc = """Output file.""", mandatory = True, ), "warn_on_legacy_licenses": attr.bool(default = False), }, ) def manifest(name, deps, out = None, **kwargs): if not out: out = name + ".manifest" _manifest(name = name, deps = deps, out = out, **kwargs) rules_license-0.0.7/examples/my_org/000077500000000000000000000000001444314666600175025ustar00rootroot00000000000000rules_license-0.0.7/examples/my_org/licenses/000077500000000000000000000000001444314666600213075ustar00rootroot00000000000000rules_license-0.0.7/examples/my_org/licenses/BUILD000066400000000000000000000045651444314666600221030ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Example license kind definitions. # We expect that all license_kind rules used by an organization exist in a # central place in their source repository. # # - This allows centralized audit and, with suport from the SCM, an assurance # that individual developers are not adding new license kinds to the code # base without authorization. # - When third party packages are used, they might come with license rules # pointing to well known license_kinds from @rules_license/licenses. # At import time, users can mechanically transform those target paths from # @rules_license to their own license_kind repository. # - The conditions for each license_kind may be customized for the organzation's # needs, and not match the conditions used by the canonical versions from # @rules_license. # - In rare cases, a third_party project will define their own license_kinds. # There is no reasonable automatic handling of that. Organizations will have # to hand inspect the license text to see if it matches the conditions, and # then will have to hand import it to their private license_kind repository. load("@rules_license//rules:license_kind.bzl", "license_kind") package(default_visibility = ["//examples:__subpackages__"]) # license_kind rules generally appear in a central location per workspace. They # are intermingled with normal target build rules license_kind( name = "generic_notice", conditions = [ "notice", ], ) license_kind( name = "generic_restricted", conditions = [ "restricted", ], ) license_kind( name = "unencumbered", conditions = [], # none ) license_kind( name = "lgpl_like", conditions = [ "restricted_if_statically_linked", ], ) license_kind( name = "acme_corp_paid", conditions = [ "allowlist:acme_corp_paid", ], ) rules_license-0.0.7/examples/policy_checker/000077500000000000000000000000001444314666600211715ustar00rootroot00000000000000rules_license-0.0.7/examples/policy_checker/BUILD000066400000000000000000000036231444314666600217570ustar00rootroot00000000000000# Example of automated license policy definitions. load("@rules_license//examples/policy_checker:license_policy.bzl", "license_policy") load("@rules_license//examples/policy_checker:license_policy_check.bzl", "license_policy_check") package(default_package_metadata = ["//:license", "//:package_info"]) # license_policy rules generally appear in a central location per workspace. That # should be access controlled by the policy team. # A production service can use licenses with most conditions license_policy( name = "production_service", conditions = [ "notice", "restricted_if_statically_linked", ], ) # A mobile application usually can not allow end-user replacable libraries. # So LGPL code (which is restricted_if_statically_linked) can not be used. license_policy( name = "mobile_application", conditions = [ "notice", ], ) license_policy( name = "special_allowlisted_app", # There could be a allowlist of targets here. conditions = [ "notice", "allowlist:acme_corp_paid", ], ) # Now we might build checks of critical applications against policies # # Questions to consider? # - Your organization migth want to fold these kinds of checks into # wrapper macros around the rules which generate services and apps # - You might want to distribute checks to rules alongside the products # - Or, you might want to consolidate them in a single place where your # compliance team owns them, as this example does license_policy_check( name = "check_server", policy = ":production_service", target = "//examples/src:my_server", ) # This is marked manual, so bazel test ... does not fail. Try it yourself with # bazel build :check_violating_server license_policy_check( name = "check_violating_server", policy = ":production_service", tags = [ "manual", ], target = "//examples/src:my_violating_server", ) rules_license-0.0.7/examples/policy_checker/license_policy.bzl000066400000000000000000000032661444314666600247120ustar00rootroot00000000000000# Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """license_policy rule. A license_policy names a set of conditions allowed in the union of all license_kinds use by a target. The name of the rule is typically an application type (e.g. production_server, mobile_application, ...) """ load( "@rules_license//examples/policy_checker:license_policy_provider.bzl", "LicensePolicyInfo" ) def _license_policy_impl(ctx): provider = LicensePolicyInfo( name = ctx.attr.name, label = "@%s//%s:%s" % ( ctx.label.workspace_name, ctx.label.package, ctx.label.name, ), conditions = ctx.attr.conditions, ) return [provider] _license_policy = rule( implementation = _license_policy_impl, attrs = { "conditions": attr.string_list( doc = "Conditions to be met when using software under this license." + " Conditions are defined by the organization using this license.", mandatory = True, ), }, ) def license_policy(name, conditions): _license_policy( name = name, conditions = conditions, applicable_licenses = [], ) rules_license-0.0.7/examples/policy_checker/license_policy_check.bzl000066400000000000000000000063251444314666600260460ustar00rootroot00000000000000# Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """License compliance checking at analysis time.""" load( "@rules_license//examples/policy_checker:license_policy_provider.bzl", "LicensePolicyInfo", ) load( "@rules_license//rules:gather_licenses_info.bzl", "gather_licenses_info", ) load("@rules_license//rules:providers.bzl", "LicenseInfo") load("@rules_license//rules_gathering:gathering_providers.bzl", "TransitiveLicensesInfo") # This is a crude example of the kind of thing which can be done. def _license_policy_check_impl(ctx): policy = ctx.attr.policy[LicensePolicyInfo] allowed_conditions = policy.conditions if TransitiveLicensesInfo in ctx.attr.target: for license in ctx.attr.target[TransitiveLicensesInfo].licenses.to_list(): for kind in license.license_kinds: # print(kind.conditions) for condition in kind.conditions: if condition not in allowed_conditions: fail("Condition %s violates policy %s" % ( condition, policy.label, )) if LicenseInfo in ctx.attr.target: for license in ctx.attr.target[LicenseInfo].licenses.to_list(): for kind in license.license_kinds: # print(kind.conditions) for condition in kind.conditions: if condition not in allowed_conditions: fail("Condition %s violates policy %s" % ( condition, policy.label, )) return [DefaultInfo()] _license_policy_check = rule( implementation = _license_policy_check_impl, doc = """Internal implementation method for license_policy_check().""", attrs = { "policy": attr.label( doc = """Policy definition.""", mandatory = True, providers = [LicensePolicyInfo], ), "target": attr.label( doc = """Target to collect LicenseInfo for.""", aspects = [gather_licenses_info], mandatory = True, allow_single_file = True, ), }, ) def license_policy_check(name, target, policy, **kwargs): """Checks a target against a policy. Args: name: The target. target: A target to test for compliance with a policy policy: A rule providing LicensePolicyInfo. **kwargs: other args. Usage: license_policy_check( name = "license_info", target = ":my_app", policy = "//my_org/compliance/policies:mobile_application", ) """ _license_policy_check(name = name, target = target, policy = policy, **kwargs) rules_license-0.0.7/examples/policy_checker/license_policy_provider.bzl000066400000000000000000000016421444314666600266200ustar00rootroot00000000000000# Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """LicensePolicyProvider.""" LicensePolicyInfo = provider( doc = """Declares a policy name and the license conditions allowable under it.""", fields = { "conditions": "List of conditions to be met when using this software.", "label": "The full path to the license policy definition.", "name": "License policy name", }, ) rules_license-0.0.7/examples/sboms/000077500000000000000000000000001444314666600173315ustar00rootroot00000000000000rules_license-0.0.7/examples/sboms/BUILD000066400000000000000000000007071444314666600201170ustar00rootroot00000000000000# Demonstrate the generate_sbom rule load("@rules_license//rules_gathering:generate_sbom.bzl", "generate_sbom") # There are not a lot of targets in this rule set to build a SBOM from # so we will (in a very self-referential way) generate one for the tool # which generates the SBOMs # See the output in bazel-bin/examples/sboms/write_sbom.txt generate_sbom( name = "write_sbom_sbom", out = "write_sbom.txt", deps = ["//tools:write_sbom"], ) rules_license-0.0.7/examples/src/000077500000000000000000000000001444314666600167755ustar00rootroot00000000000000rules_license-0.0.7/examples/src/BUILD000066400000000000000000000041521444314666600175610ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Examples of applications and interactions with licenses load("@rules_license//examples/vndor/constant_gen:defs.bzl", "constant_gen") load("@rules_license//rules:compliance.bzl", "check_license") load("@rules_license//sample_reports:licenses_used.bzl", "licenses_used") package( default_package_metadata = ["//:license", "//:package_info"], default_visibility = ["//examples:__subpackages__"], ) cc_binary( name = "my_server", srcs = ["server.cc"], deps = [":message"], ) # Sample constant_gen( name = "message", text = "Hello, world.", var = "server_message", ) # TODO(aiuto): Turn this strictly into a compliance test. check_license( name = "check_server", check_conditions = False, license_texts = "server_licenses.txt", report = "server_report.txt", deps = [ ":my_server", ], ) # # Verify the licenses are what we expect. The golden output shows that # :my_server only uses the unencumbered license type. licenses_used( name = "server_licenses", out = "server_licenses.json", deps = [":my_server"], ) py_test( name = "server_licenses_test", srcs = ["server_licenses_test.py"], data = [":server_licenses.json"], python_version = "PY3", deps = [ "@rules_license//tests:license_test_utils", ], ) # This server uses something under a restricted license cc_binary( name = "my_violating_server", srcs = ["server.cc"], deps = [ ":message", "@rules_license//examples/vndor/acme", "@rules_license//examples/vndor/libhhgttg", ], ) rules_license-0.0.7/examples/src/server.cc000066400000000000000000000013611444314666600206130ustar00rootroot00000000000000// Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include extern const char* server_message; int main(int argc, char* argv[]) { std::cout << server_message << std::endl; return 0; } rules_license-0.0.7/examples/src/server_licenses_test.py000066400000000000000000000030361444314666600236030ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Tests for license/examples/src.""" import os import unittest from tests import license_test_utils class ServerLicensesTest(unittest.TestCase): def test_has_expected_licenses(self): package_base = license_test_utils.LICENSE_PACKAGE_BASE licenses_info = license_test_utils.load_licenses_info( os.path.join(os.path.dirname(__file__), "server_licenses.json")) licenses_info = license_test_utils.filter_dependencies( licenses_info, target_filter=lambda targ: targ.startswith(package_base), licenses_filter=lambda lic: lic.startswith(package_base)) expected = { "/examples/src:message_src_": [ "/examples/vndor/constant_gen:license_for_emitted_code" ], "/examples/src:message": [ "/examples/vndor/constant_gen:license_for_emitted_code" ], } license_test_utils.check_licenses_of_dependencies( self, licenses_info, expected) if __name__ == "__main__": unittest.main() rules_license-0.0.7/examples/vndor/000077500000000000000000000000001444314666600173365ustar00rootroot00000000000000rules_license-0.0.7/examples/vndor/README.md000066400000000000000000000004511444314666600206150ustar00rootroot00000000000000# Third party packges used by your project. Note that these are presumed to be vendored in to your source tree. These examples to not try to address the concerns of organizations that wish to use license software without first examining the license and preserving their own copy and audit trail. rules_license-0.0.7/examples/vndor/acme/000077500000000000000000000000001444314666600202435ustar00rootroot00000000000000rules_license-0.0.7/examples/vndor/acme/ACME_LICENSE000066400000000000000000000003041444314666600220320ustar00rootroot00000000000000Acme Novelty & Software provides a license to this software under terms laid out in specific contracts. Unless you have purchased a license from us, you may not use this software for any purpose. rules_license-0.0.7/examples/vndor/acme/BUILD000066400000000000000000000020661444314666600210310ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # A package with a commercial license. load("@rules_license//rules:license.bzl", "license") package( default_applicable_licenses = [":license"], default_visibility = ["//examples:__subpackages__"], ) # The default license for an entire package is typically named "license". license( name = "license", license_kinds = [ "@rules_license//examples/my_org/licenses:acme_corp_paid", ], license_text = "ACME_LICENSE", ) cc_library( name = "acme", srcs = ["coyote.cc"], ) rules_license-0.0.7/examples/vndor/acme/coyote.cc000066400000000000000000000011661444314666600220600ustar00rootroot00000000000000// Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. bool caught_road_runner() { return false; } rules_license-0.0.7/examples/vndor/constant_gen/000077500000000000000000000000001444314666600220205ustar00rootroot00000000000000rules_license-0.0.7/examples/vndor/constant_gen/BUILD000066400000000000000000000044471444314666600226130ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # An example of a code generator with a distinct license for the generated code. load("@rules_license//rules:license.bzl", "license") load("@rules_license//sample_reports:licenses_used.bzl", "licenses_used") load(":defs.bzl", "constant_gen") package( default_applicable_licenses = [":license"], default_visibility = ["//examples:__subpackages__"], ) # The default license for an entire package is typically named "license". license( name = "license", package_name = "Trivial Code Generator", license_kinds = [ "@rules_license//examples/my_org/licenses:generic_restricted", ], license_text = "LICENSE", ) license( name = "license_for_emitted_code", package_name = "Trivial Code Generator Output", license_kinds = [ "@rules_license//examples/my_org/licenses:unencumbered", ], license_text = "LICENSE.on_output", ) # The generator itself will be licensed under :license py_binary( name = "constant_generator", srcs = ["constant_generator.py"], python_version = "PY3", ) # Sample: This target will be licensed under :license_for_emitted_code constant_gen( name = "libhello", text = "Hello, world.", var = "hello_world", ) # Verify the licenses are what we expect licenses_used( name = "generator_licenses", out = "generator_licenses.json", deps = [":constant_generator"], ) licenses_used( name = "generated_code_licenses", # Note: using default output file name deps = [":libhello"], ) py_test( name = "verify_licenses_test", srcs = ["verify_licenses_test.py"], data = [ ":generator_licenses.json", ":generated_code_licenses.json", ], python_version = "PY3", deps = [ "//tests:license_test_utils", ], ) rules_license-0.0.7/examples/vndor/constant_gen/LICENSE000066400000000000000000000001101444314666600230150ustar00rootroot00000000000000This code is provided under a license which contains some restrictions. rules_license-0.0.7/examples/vndor/constant_gen/LICENSE.on_output000066400000000000000000000001051444314666600250540ustar00rootroot00000000000000The generated output from constant_gen has no license encumberances. rules_license-0.0.7/examples/vndor/constant_gen/constant_generator.py000066400000000000000000000017421444314666600262750ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A trivial tool to turn a string into a C++ constant. This is not meant to be useful. It is only to provide an example of a tool that generates code. """ import sys def main(argv): if len(argv) != 4: raise Exception('usage: constant_generator out_file var_name text') with open(argv[1], 'w') as out: out.write('const char* %s = "%s";\n' % (argv[2], argv[3])) if __name__ == '__main__': main(sys.argv) rules_license-0.0.7/examples/vndor/constant_gen/defs.bzl000066400000000000000000000040121444314666600234470ustar00rootroot00000000000000# Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """A trivial rule to turn a string into a C++ constant.""" def _constant_gen_impl(ctx): # Turn text into a C++ constant. outputs = [ctx.outputs.src_out] ctx.actions.run( mnemonic = "GenerateConstant", progress_message = "Generating %s" % ctx.attr.var, outputs = outputs, executable = ctx.executable._generator, arguments = [ctx.outputs.src_out.path, ctx.attr.var, ctx.attr.text], ) return [DefaultInfo(files = depset(outputs))] _constant_gen = rule( implementation = _constant_gen_impl, attrs = { "src_out": attr.output(mandatory = True), "text": attr.string(mandatory = True), "var": attr.string(mandatory = False), "_generator": attr.label( default = Label("@rules_license//examples/vndor/constant_gen:constant_generator"), executable = True, allow_files = True, cfg = "exec", ), }, ) def constant_gen(name, text, var): # Generate the code _constant_gen( name = name + "_src_", src_out = name + "_src_.cc", text = text, var = var, applicable_licenses = ["@rules_license//examples/vndor/constant_gen:license_for_emitted_code"], ) # And turn it into a library we can link against native.cc_library( name = name, srcs = [name + "_src_"], applicable_licenses = ["@rules_license//examples/vndor/constant_gen:license_for_emitted_code"], ) rules_license-0.0.7/examples/vndor/constant_gen/verify_licenses_test.py000066400000000000000000000022441444314666600266240ustar00rootroot00000000000000"""Test that we see the expected licenses for some generated code.""" import codecs import os import unittest from tests import license_test_utils class VerifyLicensesTest(unittest.TestCase): def test_generater_license(self): licenses_info = license_test_utils.load_licenses_info( os.path.join(os.path.dirname(__file__), "generator_licenses.json")) expected = { "examples/vndor/constant_gen:constant_generator": [ "examples/vndor/constant_gen:license" ], } license_test_utils.check_licenses_of_dependencies( self, licenses_info, expected) def test_generated_code_license(self): licenses_info = license_test_utils.load_licenses_info( os.path.join(os.path.dirname(__file__), "generated_code_licenses.json")) expected = { "examples/vndor/constant_gen:libhello": [ "/constant_gen:license_for_emitted_code", ], "examples/vndor/constant_gen:libhello_src_": [ "/constant_gen:license_for_emitted_code", ], } license_test_utils.check_licenses_of_dependencies( self, licenses_info, expected) if __name__ == "__main__": unittest.main() rules_license-0.0.7/examples/vndor/libhhgttg/000077500000000000000000000000001444314666600213125ustar00rootroot00000000000000rules_license-0.0.7/examples/vndor/libhhgttg/BUILD000066400000000000000000000023161444314666600220760ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # A package with all code under a single license. This is the most common case # we expect to see. load("@rules_license//rules:license.bzl", "license") # Using a package wide default ensure that all targets are associated with the # license. package( default_applicable_licenses = [":license"], default_visibility = ["//examples:__subpackages__"], ) # The default license for an entire package is typically named "license". license( name = "license", license_kinds = [ "@rules_license//examples/my_org/licenses:generic_notice", ], license_text = "LICENSE", ) cc_library( name = "libhhgttg", srcs = ["answer.cc"], ) rules_license-0.0.7/examples/vndor/libhhgttg/LICENSE000066400000000000000000000001421444314666600223140ustar00rootroot00000000000000You can do whatever you want with this software. Just incude this license with your distribution. rules_license-0.0.7/examples/vndor/libhhgttg/answer.cc000066400000000000000000000011321444314666600231150ustar00rootroot00000000000000// Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. int answer = 42; rules_license-0.0.7/licenses/000077500000000000000000000000001444314666600161755ustar00rootroot00000000000000rules_license-0.0.7/licenses/generic/000077500000000000000000000000001444314666600176115ustar00rootroot00000000000000rules_license-0.0.7/licenses/generic/BUILD000066400000000000000000000057171444314666600204050ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """license_kind()s for generic license identifiers.""" # This is a set of license_kind declarations based on the legacy Bazel license # identifiers. # # Projects using one of these licenses may reference the license_kind targets # here. For example, their BUILD file might contain: # # package(default_applicable_licenses = [":license"]) # # license( # name = "license", # license_kinds = ["@rules_license//licenses/generic:notice"], # license_text = "LICENSE", # ) # # These licenses represent the LicenseType enum originally baked into Bazel. See # https://github.com/bazelbuild/bazel/blob/fcfca6157b6de903ab942cef2fc460bf8c8da6ed/src/main/java/com/google/devtools/build/lib/packages/License.java#L59 # # Packages may create license rules that use these license_kinds when the # package has provided a LICENSE file, but the text in it does not match any # of the well known licenses in @rules_license//licenses/spdx:* load("@rules_license//rules:license_kind.bzl", "license_kind") package( default_applicable_licenses = ["//:license"], default_visibility = ["//visibility:public"], ) licenses(["notice"]) filegroup( name = "standard_package", srcs = ["BUILD"], ) # "none" should be used for packages which are distributed with no license of # any kind. You can use this no-op license as a positive indication that the # code's license terms were reviewed, so that linters will not flag it later as # unreviewed. license_kind( name = "none", ) # See: https://opensource.google/docs/thirdparty/licenses/#unencumbered license_kind( name = "unencumbered", ) # See: https://opensource.google/docs/thirdparty/licenses/#notice license_kind( name = "notice", conditions = [ "notice", ], ) # See: https://opensource.google/docs/thirdparty/licenses/#permissive license_kind( name = "permissive", conditions = [ "permissive", ], ) # See: https://opensource.google/docs/thirdparty/licenses/#reciprocal license_kind( name = "reciprocal", conditions = [ "reciprocal", ], ) # See: https://opensource.google/docs/thirdparty/licenses/#restricted license_kind( name = "restricted", conditions = [ "restricted", ], ) # See: https://opensource.google/docs/thirdparty/licenses/#ByExceptionOnly license_kind( name = "by_exception_only", conditions = [ "by_exception_only", ], ) rules_license-0.0.7/licenses/spdx/000077500000000000000000000000001444314666600171535ustar00rootroot00000000000000rules_license-0.0.7/licenses/spdx/BUILD000066400000000000000000001674751444314666600177610ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """license_kind()s for SPDX license identifiers.""" # This is a set of license_kind declarations based on the SPDX license # identifiers. See: https://spdx.org/licenses/ # # Open source projects using one of these well known licenses may reference # the license_kind targets here. For example, their BUILD file might contain: # # package(default_applicable_licenses = [":license"]) # # license( # name = "license", # license_kinds = ["@rules_license//licenses/spdx:MIT-0"], # license_text = "LICENSE.txt", # ) # # Organizations building custom compliance checks based on these licenses # declarations can take several approaches to align the the package author's # declaration that the package is under (let's say) an MIT-0 license with # the conditions that organization believes are required by MIT-0. # # One technique might be to: # 1. Vendor in @rules_license to your source code tree. # 2. Modify the targets here to add conditions for your particular needs. # 3. Add it as a local_repository() to your Bazel WORKSPACE. # 3. As the SPDX license list evolves, and your dependencies start using new # licenses, add new license_kind rules to this copy. # Another possible strategy might be to # 1. maintain a private list of these license_kind declarations somewhere # in your source tree. Let's say //compliance/licenses/spdx/BUILD. # 2. Automatically remap "@rules_license//licenses/spdx:" to # "//compliance/licenses/spdx:" when importing third party code. # # The choice of approach should be based on your individual philosoply of how # you should bring dependencies into your code. If you build from downloaded # packages then you might favor the first approach, because external deps # can simply refer to @rules_pkg, and they will pick up your local copy. # If you maintain your own third_party directory of all your dependences, # so that your WORKSPACE files are empty, you might favor the second. load("@rules_license//rules:license_kind.bzl", "license_kind") package( default_applicable_licenses = ["//:license"], default_visibility = ["//visibility:public"], ) licenses(["notice"]) filegroup( name = "standard_package", srcs = ["BUILD"], ) license_kind( name = "0BSD", conditions = [], url = "https://spdx.org/licenses/0BSD.html", ) license_kind( name = "AAL", conditions = [], url = "https://spdx.org/licenses/AAL.html", ) license_kind( name = "Abstyles", conditions = [], url = "https://spdx.org/licenses/Abstyles.html", ) license_kind( name = "Adobe-2006", conditions = [], url = "https://spdx.org/licenses/Adobe-2006.html", ) license_kind( name = "Adobe-Glyph", conditions = [], url = "https://spdx.org/licenses/Adobe-Glyph.html", ) license_kind( name = "ADSL", conditions = [], url = "https://spdx.org/licenses/ADSL.html", ) license_kind( name = "AFL-1.1", conditions = [], url = "https://spdx.org/licenses/AFL-1.1.html", ) license_kind( name = "AFL-1.2", conditions = [], url = "https://spdx.org/licenses/AFL-1.2.html", ) license_kind( name = "AFL-2.0", conditions = [], url = "https://spdx.org/licenses/AFL-2.0.html", ) license_kind( name = "AFL-2.1", conditions = [], url = "https://spdx.org/licenses/AFL-2.1.html", ) license_kind( name = "AFL-3.0", conditions = [], url = "https://spdx.org/licenses/AFL-3.0.html", ) license_kind( name = "Afmparse", conditions = [], url = "https://spdx.org/licenses/Afmparse.html", ) license_kind( name = "AGPL-1.0", conditions = [], url = "https://spdx.org/licenses/AGPL-1.0.html", ) license_kind( name = "AGPL-1.0-only", conditions = [], url = "https://spdx.org/licenses/AGPL-1.0-only.html", ) license_kind( name = "AGPL-1.0-or-later", conditions = [], url = "https://spdx.org/licenses/AGPL-1.0-or-later.html", ) license_kind( name = "AGPL-3.0", conditions = [], url = "https://spdx.org/licenses/AGPL-3.0.html", ) license_kind( name = "AGPL-3.0-only", conditions = [], url = "https://spdx.org/licenses/AGPL-3.0-only.html", ) license_kind( name = "AGPL-3.0-or-later", conditions = [], url = "https://spdx.org/licenses/AGPL-3.0-or-later.html", ) license_kind( name = "Aladdin", conditions = [], url = "https://spdx.org/licenses/Aladdin.html", ) license_kind( name = "AMDPLPA", conditions = [], url = "https://spdx.org/licenses/AMDPLPA.html", ) license_kind( name = "AML", conditions = [], url = "https://spdx.org/licenses/AML.html", ) license_kind( name = "AMPAS", conditions = [], url = "https://spdx.org/licenses/AMPAS.html", ) license_kind( name = "ANTLR-PD", conditions = [], url = "https://spdx.org/licenses/ANTLR-PD.html", ) license_kind( name = "ANTLR-PD-fallback", conditions = [], url = "https://spdx.org/licenses/ANTLR-PD-fallback.html", ) license_kind( name = "Apache-1.0", conditions = [], url = "https://spdx.org/licenses/Apache-1.0.html", ) license_kind( name = "Apache-1.1", conditions = [], url = "https://spdx.org/licenses/Apache-1.1.html", ) license_kind( name = "Apache-2.0", conditions = [], url = "https://spdx.org/licenses/Apache-2.0.html", ) license_kind( name = "APAFML", conditions = [], url = "https://spdx.org/licenses/APAFML.html", ) license_kind( name = "APL-1.0", conditions = [], url = "https://spdx.org/licenses/APL-1.0.html", ) license_kind( name = "App-s2p", conditions = [], url = "https://spdx.org/licenses/App-s2p.html", ) license_kind( name = "APSL-1.0", conditions = [], url = "https://spdx.org/licenses/APSL-1.0.html", ) license_kind( name = "APSL-1.1", conditions = [], url = "https://spdx.org/licenses/APSL-1.1.html", ) license_kind( name = "APSL-1.2", conditions = [], url = "https://spdx.org/licenses/APSL-1.2.html", ) license_kind( name = "APSL-2.0", conditions = [], url = "https://spdx.org/licenses/APSL-2.0.html", ) license_kind( name = "Arphic-1999", conditions = [], url = "https://spdx.org/licenses/Arphic-1999.html", ) license_kind( name = "Artistic-1.0", conditions = [], url = "https://spdx.org/licenses/Artistic-1.0.html", ) license_kind( name = "Artistic-1.0-cl8", conditions = [], url = "https://spdx.org/licenses/Artistic-1.0-cl8.html", ) license_kind( name = "Artistic-1.0-Perl", conditions = [], url = "https://spdx.org/licenses/Artistic-1.0-Perl.html", ) license_kind( name = "Artistic-2.0", conditions = [], url = "https://spdx.org/licenses/Artistic-2.0.html", ) license_kind( name = "Baekmuk", conditions = [], url = "https://spdx.org/licenses/Baekmuk.html", ) license_kind( name = "Bahyph", conditions = [], url = "https://spdx.org/licenses/Bahyph.html", ) license_kind( name = "Barr", conditions = [], url = "https://spdx.org/licenses/Barr.html", ) license_kind( name = "Beerware", conditions = [], url = "https://spdx.org/licenses/Beerware.html", ) license_kind( name = "Bitstream-Vera", conditions = [], url = "https://spdx.org/licenses/Bitstream-Vera.html", ) license_kind( name = "BitTorrent-1.0", conditions = [], url = "https://spdx.org/licenses/BitTorrent-1.0.html", ) license_kind( name = "BitTorrent-1.1", conditions = [], url = "https://spdx.org/licenses/BitTorrent-1.1.html", ) license_kind( name = "blessing", conditions = [], url = "https://spdx.org/licenses/blessing.html", ) license_kind( name = "BlueOak-1.0.0", conditions = [], url = "https://spdx.org/licenses/BlueOak-1.0.0.html", ) license_kind( name = "Borceux", conditions = [], url = "https://spdx.org/licenses/Borceux.html", ) license_kind( name = "BSD-1-Clause", conditions = [], url = "https://spdx.org/licenses/BSD-1-Clause.html", ) license_kind( name = "BSD-2-Clause", conditions = [], url = "https://spdx.org/licenses/BSD-2-Clause.html", ) license_kind( name = "BSD-2-Clause-FreeBSD", conditions = [], url = "https://spdx.org/licenses/BSD-2-Clause-FreeBSD.html", ) license_kind( name = "BSD-2-Clause-NetBSD", conditions = [], url = "https://spdx.org/licenses/BSD-2-Clause-NetBSD.html", ) license_kind( name = "BSD-2-Clause-Patent", conditions = [], url = "https://spdx.org/licenses/BSD-2-Clause-Patent.html", ) license_kind( name = "BSD-2-Clause-Views", conditions = [], url = "https://spdx.org/licenses/BSD-2-Clause-Views.html", ) license_kind( name = "BSD-3-Clause", conditions = [], url = "https://spdx.org/licenses/BSD-3-Clause.html", ) license_kind( name = "BSD-3-Clause-Attribution", conditions = [], url = "https://spdx.org/licenses/BSD-3-Clause-Attribution.html", ) license_kind( name = "BSD-3-Clause-Clear", conditions = [], url = "https://spdx.org/licenses/BSD-3-Clause-Clear.html", ) license_kind( name = "BSD-3-Clause-LBNL", conditions = [], url = "https://spdx.org/licenses/BSD-3-Clause-LBNL.html", ) license_kind( name = "BSD-3-Clause-Modification", conditions = [], url = "https://spdx.org/licenses/BSD-3-Clause-Modification.html", ) license_kind( name = "BSD-3-Clause-No-Military-License", conditions = [], url = "https://spdx.org/licenses/BSD-3-Clause-No-Military-License.html", ) license_kind( name = "BSD-3-Clause-No-Nuclear-License", conditions = [], url = "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License.html", ) license_kind( name = "BSD-3-Clause-No-Nuclear-License-2014", conditions = [], url = "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License-2014.html", ) license_kind( name = "BSD-3-Clause-No-Nuclear-Warranty", conditions = [], url = "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-Warranty.html", ) license_kind( name = "BSD-3-Clause-Open-MPI", conditions = [], url = "https://spdx.org/licenses/BSD-3-Clause-Open-MPI.html", ) license_kind( name = "BSD-4-Clause", conditions = [], url = "https://spdx.org/licenses/BSD-4-Clause.html", ) license_kind( name = "BSD-4-Clause-Shortened", conditions = [], url = "https://spdx.org/licenses/BSD-4-Clause-Shortened.html", ) license_kind( name = "BSD-4-Clause-UC", conditions = [], url = "https://spdx.org/licenses/BSD-4-Clause-UC.html", ) license_kind( name = "BSD-Protection", conditions = [], url = "https://spdx.org/licenses/BSD-Protection.html", ) license_kind( name = "BSD-Source-Code", conditions = [], url = "https://spdx.org/licenses/BSD-Source-Code.html", ) license_kind( name = "BSL-1.0", conditions = [], url = "https://spdx.org/licenses/BSL-1.0.html", ) license_kind( name = "BUSL-1.1", conditions = [], url = "https://spdx.org/licenses/BUSL-1.1.html", ) license_kind( name = "bzip2-1.0.5", conditions = [], url = "https://spdx.org/licenses/bzip2-1.0.5.html", ) license_kind( name = "bzip2-1.0.6", conditions = [], url = "https://spdx.org/licenses/bzip2-1.0.6.html", ) license_kind( name = "C-UDA-1.0", conditions = [], url = "https://spdx.org/licenses/C-UDA-1.0.html", ) license_kind( name = "CAL-1.0", conditions = [], url = "https://spdx.org/licenses/CAL-1.0.html", ) license_kind( name = "CAL-1.0-Combined-Work-Exception", conditions = [], url = "https://spdx.org/licenses/CAL-1.0-Combined-Work-Exception.html", ) license_kind( name = "Caldera", conditions = [], url = "https://spdx.org/licenses/Caldera.html", ) license_kind( name = "CATOSL-1.1", conditions = [], url = "https://spdx.org/licenses/CATOSL-1.1.html", ) license_kind( name = "CC-BY-1.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-1.0.html", ) license_kind( name = "CC-BY-2.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-2.0.html", ) license_kind( name = "CC-BY-2.5", conditions = [], url = "https://spdx.org/licenses/CC-BY-2.5.html", ) license_kind( name = "CC-BY-2.5-AU", conditions = [], url = "https://spdx.org/licenses/CC-BY-2.5-AU.html", ) license_kind( name = "CC-BY-3.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-3.0.html", ) license_kind( name = "CC-BY-3.0-AT", conditions = [], url = "https://spdx.org/licenses/CC-BY-3.0-AT.html", ) license_kind( name = "CC-BY-3.0-DE", conditions = [], url = "https://spdx.org/licenses/CC-BY-3.0-DE.html", ) license_kind( name = "CC-BY-3.0-NL", conditions = [], url = "https://spdx.org/licenses/CC-BY-3.0-NL.html", ) license_kind( name = "CC-BY-3.0-US", conditions = [], url = "https://spdx.org/licenses/CC-BY-3.0-US.html", ) license_kind( name = "CC-BY-4.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-4.0.html", ) license_kind( name = "CC-BY-NC-1.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-1.0.html", ) license_kind( name = "CC-BY-NC-2.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-2.0.html", ) license_kind( name = "CC-BY-NC-2.5", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-2.5.html", ) license_kind( name = "CC-BY-NC-3.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-3.0.html", ) license_kind( name = "CC-BY-NC-3.0-DE", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-3.0-DE.html", ) license_kind( name = "CC-BY-NC-4.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-4.0.html", ) license_kind( name = "CC-BY-NC-ND-1.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-ND-1.0.html", ) license_kind( name = "CC-BY-NC-ND-2.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-ND-2.0.html", ) license_kind( name = "CC-BY-NC-ND-2.5", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-ND-2.5.html", ) license_kind( name = "CC-BY-NC-ND-3.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-ND-3.0.html", ) license_kind( name = "CC-BY-NC-ND-3.0-DE", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-ND-3.0-DE.html", ) license_kind( name = "CC-BY-NC-ND-3.0-IGO", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-ND-3.0-IGO.html", ) license_kind( name = "CC-BY-NC-ND-4.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-ND-4.0.html", ) license_kind( name = "CC-BY-NC-SA-1.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-SA-1.0.html", ) license_kind( name = "CC-BY-NC-SA-2.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-SA-2.0.html", ) license_kind( name = "CC-BY-NC-SA-2.0-FR", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-SA-2.0-FR.html", ) license_kind( name = "CC-BY-NC-SA-2.0-UK", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-SA-2.0-UK.html", ) license_kind( name = "CC-BY-NC-SA-2.5", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-SA-2.5.html", ) license_kind( name = "CC-BY-NC-SA-3.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-SA-3.0.html", ) license_kind( name = "CC-BY-NC-SA-3.0-DE", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-SA-3.0-DE.html", ) license_kind( name = "CC-BY-NC-SA-3.0-IGO", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-SA-3.0-IGO.html", ) license_kind( name = "CC-BY-NC-SA-4.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-NC-SA-4.0.html", ) license_kind( name = "CC-BY-ND-1.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-ND-1.0.html", ) license_kind( name = "CC-BY-ND-2.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-ND-2.0.html", ) license_kind( name = "CC-BY-ND-2.5", conditions = [], url = "https://spdx.org/licenses/CC-BY-ND-2.5.html", ) license_kind( name = "CC-BY-ND-3.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-ND-3.0.html", ) license_kind( name = "CC-BY-ND-3.0-DE", conditions = [], url = "https://spdx.org/licenses/CC-BY-ND-3.0-DE.html", ) license_kind( name = "CC-BY-ND-4.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-ND-4.0.html", ) license_kind( name = "CC-BY-SA-1.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-SA-1.0.html", ) license_kind( name = "CC-BY-SA-2.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-SA-2.0.html", ) license_kind( name = "CC-BY-SA-2.0-UK", conditions = [], url = "https://spdx.org/licenses/CC-BY-SA-2.0-UK.html", ) license_kind( name = "CC-BY-SA-2.1-JP", conditions = [], url = "https://spdx.org/licenses/CC-BY-SA-2.1-JP.html", ) license_kind( name = "CC-BY-SA-2.5", conditions = [], url = "https://spdx.org/licenses/CC-BY-SA-2.5.html", ) license_kind( name = "CC-BY-SA-3.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-SA-3.0.html", ) license_kind( name = "CC-BY-SA-3.0-AT", conditions = [], url = "https://spdx.org/licenses/CC-BY-SA-3.0-AT.html", ) license_kind( name = "CC-BY-SA-3.0-DE", conditions = [], url = "https://spdx.org/licenses/CC-BY-SA-3.0-DE.html", ) license_kind( name = "CC-BY-SA-4.0", conditions = [], url = "https://spdx.org/licenses/CC-BY-SA-4.0.html", ) license_kind( name = "CC-PDDC", conditions = [], url = "https://spdx.org/licenses/CC-PDDC.html", ) license_kind( name = "CC0-1.0", conditions = [], url = "https://spdx.org/licenses/CC0-1.0.html", ) license_kind( name = "CDDL-1.0", conditions = [], url = "https://spdx.org/licenses/CDDL-1.0.html", ) license_kind( name = "CDDL-1.1", conditions = [], url = "https://spdx.org/licenses/CDDL-1.1.html", ) license_kind( name = "CDL-1.0", conditions = [], url = "https://spdx.org/licenses/CDL-1.0.html", ) license_kind( name = "CDLA-Permissive-1.0", conditions = [], url = "https://spdx.org/licenses/CDLA-Permissive-1.0.html", ) license_kind( name = "CDLA-Permissive-2.0", conditions = [], url = "https://spdx.org/licenses/CDLA-Permissive-2.0.html", ) license_kind( name = "CDLA-Sharing-1.0", conditions = [], url = "https://spdx.org/licenses/CDLA-Sharing-1.0.html", ) license_kind( name = "CECILL-1.0", conditions = [], url = "https://spdx.org/licenses/CECILL-1.0.html", ) license_kind( name = "CECILL-1.1", conditions = [], url = "https://spdx.org/licenses/CECILL-1.1.html", ) license_kind( name = "CECILL-2.0", conditions = [], url = "https://spdx.org/licenses/CECILL-2.0.html", ) license_kind( name = "CECILL-2.1", conditions = [], url = "https://spdx.org/licenses/CECILL-2.1.html", ) license_kind( name = "CECILL-B", conditions = [], url = "https://spdx.org/licenses/CECILL-B.html", ) license_kind( name = "CECILL-C", conditions = [], url = "https://spdx.org/licenses/CECILL-C.html", ) license_kind( name = "CERN-OHL-1.1", conditions = [], url = "https://spdx.org/licenses/CERN-OHL-1.1.html", ) license_kind( name = "CERN-OHL-1.2", conditions = [], url = "https://spdx.org/licenses/CERN-OHL-1.2.html", ) license_kind( name = "CERN-OHL-P-2.0", conditions = [], url = "https://spdx.org/licenses/CERN-OHL-P-2.0.html", ) license_kind( name = "CERN-OHL-S-2.0", conditions = [], url = "https://spdx.org/licenses/CERN-OHL-S-2.0.html", ) license_kind( name = "CERN-OHL-W-2.0", conditions = [], url = "https://spdx.org/licenses/CERN-OHL-W-2.0.html", ) license_kind( name = "ClArtistic", conditions = [], url = "https://spdx.org/licenses/ClArtistic.html", ) license_kind( name = "CNRI-Jython", conditions = [], url = "https://spdx.org/licenses/CNRI-Jython.html", ) license_kind( name = "CNRI-Python", conditions = [], url = "https://spdx.org/licenses/CNRI-Python.html", ) license_kind( name = "CNRI-Python-GPL-Compatible", conditions = [], url = "https://spdx.org/licenses/CNRI-Python-GPL-Compatible.html", ) license_kind( name = "COIL-1.0", conditions = [], url = "https://spdx.org/licenses/COIL-1.0.html", ) license_kind( name = "Community-Spec-1.0", conditions = [], url = "https://spdx.org/licenses/Community-Spec-1.0.html", ) license_kind( name = "Condor-1.1", conditions = [], url = "https://spdx.org/licenses/Condor-1.1.html", ) license_kind( name = "copyleft-next-0.3.0", conditions = [], url = "https://spdx.org/licenses/copyleft-next-0.3.0.html", ) license_kind( name = "copyleft-next-0.3.1", conditions = [], url = "https://spdx.org/licenses/copyleft-next-0.3.1.html", ) license_kind( name = "CPAL-1.0", conditions = [], url = "https://spdx.org/licenses/CPAL-1.0.html", ) license_kind( name = "CPL-1.0", conditions = [], url = "https://spdx.org/licenses/CPL-1.0.html", ) license_kind( name = "CPOL-1.02", conditions = [], url = "https://spdx.org/licenses/CPOL-1.02.html", ) license_kind( name = "Crossword", conditions = [], url = "https://spdx.org/licenses/Crossword.html", ) license_kind( name = "CrystalStacker", conditions = [], url = "https://spdx.org/licenses/CrystalStacker.html", ) license_kind( name = "CUA-OPL-1.0", conditions = [], url = "https://spdx.org/licenses/CUA-OPL-1.0.html", ) license_kind( name = "Cube", conditions = [], url = "https://spdx.org/licenses/Cube.html", ) license_kind( name = "curl", conditions = [], url = "https://spdx.org/licenses/curl.html", ) license_kind( name = "D-FSL-1.0", conditions = [], url = "https://spdx.org/licenses/D-FSL-1.0.html", ) license_kind( name = "diffmark", conditions = [], url = "https://spdx.org/licenses/diffmark.html", ) license_kind( name = "DL-DE-BY-2.0", conditions = [], url = "https://spdx.org/licenses/DL-DE-BY-2.0.html", ) license_kind( name = "DOC", conditions = [], url = "https://spdx.org/licenses/DOC.html", ) license_kind( name = "Dotseqn", conditions = [], url = "https://spdx.org/licenses/Dotseqn.html", ) license_kind( name = "DRL-1.0", conditions = [], url = "https://spdx.org/licenses/DRL-1.0.html", ) license_kind( name = "DSDP", conditions = [], url = "https://spdx.org/licenses/DSDP.html", ) license_kind( name = "dvipdfm", conditions = [], url = "https://spdx.org/licenses/dvipdfm.html", ) license_kind( name = "ECL-1.0", conditions = [], url = "https://spdx.org/licenses/ECL-1.0.html", ) license_kind( name = "ECL-2.0", conditions = [], url = "https://spdx.org/licenses/ECL-2.0.html", ) license_kind( name = "eCos-2.0", conditions = [], url = "https://spdx.org/licenses/eCos-2.0.html", ) license_kind( name = "EFL-1.0", conditions = [], url = "https://spdx.org/licenses/EFL-1.0.html", ) license_kind( name = "EFL-2.0", conditions = [], url = "https://spdx.org/licenses/EFL-2.0.html", ) license_kind( name = "eGenix", conditions = [], url = "https://spdx.org/licenses/eGenix.html", ) license_kind( name = "Elastic-2.0", conditions = [], url = "https://spdx.org/licenses/Elastic-2.0.html", ) license_kind( name = "Entessa", conditions = [], url = "https://spdx.org/licenses/Entessa.html", ) license_kind( name = "EPICS", conditions = [], url = "https://spdx.org/licenses/EPICS.html", ) license_kind( name = "EPL-1.0", conditions = [], url = "https://spdx.org/licenses/EPL-1.0.html", ) license_kind( name = "EPL-2.0", conditions = [], url = "https://spdx.org/licenses/EPL-2.0.html", ) license_kind( name = "ErlPL-1.1", conditions = [], url = "https://spdx.org/licenses/ErlPL-1.1.html", ) license_kind( name = "etalab-2.0", conditions = [], url = "https://spdx.org/licenses/etalab-2.0.html", ) license_kind( name = "EUDatagrid", conditions = [], url = "https://spdx.org/licenses/EUDatagrid.html", ) license_kind( name = "EUPL-1.0", conditions = [], url = "https://spdx.org/licenses/EUPL-1.0.html", ) license_kind( name = "EUPL-1.1", conditions = [], url = "https://spdx.org/licenses/EUPL-1.1.html", ) license_kind( name = "EUPL-1.2", conditions = [], url = "https://spdx.org/licenses/EUPL-1.2.html", ) license_kind( name = "Eurosym", conditions = [], url = "https://spdx.org/licenses/Eurosym.html", ) license_kind( name = "Fair", conditions = [], url = "https://spdx.org/licenses/Fair.html", ) license_kind( name = "FDK-AAC", conditions = [], url = "https://spdx.org/licenses/FDK-AAC.html", ) license_kind( name = "Frameworx-1.0", conditions = [], url = "https://spdx.org/licenses/Frameworx-1.0.html", ) license_kind( name = "FreeBSD-DOC", conditions = [], url = "https://spdx.org/licenses/FreeBSD-DOC.html", ) license_kind( name = "FreeImage", conditions = [], url = "https://spdx.org/licenses/FreeImage.html", ) license_kind( name = "FSFAP", conditions = [], url = "https://spdx.org/licenses/FSFAP.html", ) license_kind( name = "FSFUL", conditions = [], url = "https://spdx.org/licenses/FSFUL.html", ) license_kind( name = "FSFULLR", conditions = [], url = "https://spdx.org/licenses/FSFULLR.html", ) license_kind( name = "FTL", conditions = [], url = "https://spdx.org/licenses/FTL.html", ) license_kind( name = "GD", conditions = [], url = "https://spdx.org/licenses/GD.html", ) license_kind( name = "GFDL-1.1", conditions = [], url = "https://spdx.org/licenses/GFDL-1.1.html", ) license_kind( name = "GFDL-1.1-invariants-only", conditions = [], url = "https://spdx.org/licenses/GFDL-1.1-invariants-only.html", ) license_kind( name = "GFDL-1.1-invariants-or-later", conditions = [], url = "https://spdx.org/licenses/GFDL-1.1-invariants-or-later.html", ) license_kind( name = "GFDL-1.1-no-invariants-only", conditions = [], url = "https://spdx.org/licenses/GFDL-1.1-no-invariants-only.html", ) license_kind( name = "GFDL-1.1-no-invariants-or-later", conditions = [], url = "https://spdx.org/licenses/GFDL-1.1-no-invariants-or-later.html", ) license_kind( name = "GFDL-1.1-only", conditions = [], url = "https://spdx.org/licenses/GFDL-1.1-only.html", ) license_kind( name = "GFDL-1.1-or-later", conditions = [], url = "https://spdx.org/licenses/GFDL-1.1-or-later.html", ) license_kind( name = "GFDL-1.2", conditions = [], url = "https://spdx.org/licenses/GFDL-1.2.html", ) license_kind( name = "GFDL-1.2-invariants-only", conditions = [], url = "https://spdx.org/licenses/GFDL-1.2-invariants-only.html", ) license_kind( name = "GFDL-1.2-invariants-or-later", conditions = [], url = "https://spdx.org/licenses/GFDL-1.2-invariants-or-later.html", ) license_kind( name = "GFDL-1.2-no-invariants-only", conditions = [], url = "https://spdx.org/licenses/GFDL-1.2-no-invariants-only.html", ) license_kind( name = "GFDL-1.2-no-invariants-or-later", conditions = [], url = "https://spdx.org/licenses/GFDL-1.2-no-invariants-or-later.html", ) license_kind( name = "GFDL-1.2-only", conditions = [], url = "https://spdx.org/licenses/GFDL-1.2-only.html", ) license_kind( name = "GFDL-1.2-or-later", conditions = [], url = "https://spdx.org/licenses/GFDL-1.2-or-later.html", ) license_kind( name = "GFDL-1.3", conditions = [], url = "https://spdx.org/licenses/GFDL-1.3.html", ) license_kind( name = "GFDL-1.3-invariants-only", conditions = [], url = "https://spdx.org/licenses/GFDL-1.3-invariants-only.html", ) license_kind( name = "GFDL-1.3-invariants-or-later", conditions = [], url = "https://spdx.org/licenses/GFDL-1.3-invariants-or-later.html", ) license_kind( name = "GFDL-1.3-no-invariants-only", conditions = [], url = "https://spdx.org/licenses/GFDL-1.3-no-invariants-only.html", ) license_kind( name = "GFDL-1.3-no-invariants-or-later", conditions = [], url = "https://spdx.org/licenses/GFDL-1.3-no-invariants-or-later.html", ) license_kind( name = "GFDL-1.3-only", conditions = [], url = "https://spdx.org/licenses/GFDL-1.3-only.html", ) license_kind( name = "GFDL-1.3-or-later", conditions = [], url = "https://spdx.org/licenses/GFDL-1.3-or-later.html", ) license_kind( name = "Giftware", conditions = [], url = "https://spdx.org/licenses/Giftware.html", ) license_kind( name = "GL2PS", conditions = [], url = "https://spdx.org/licenses/GL2PS.html", ) license_kind( name = "Glide", conditions = [], url = "https://spdx.org/licenses/Glide.html", ) license_kind( name = "Glulxe", conditions = [], url = "https://spdx.org/licenses/Glulxe.html", ) license_kind( name = "GLWTPL", conditions = [], url = "https://spdx.org/licenses/GLWTPL.html", ) license_kind( name = "gnuplot", conditions = [], url = "https://spdx.org/licenses/gnuplot.html", ) license_kind( name = "GPL-1.0", conditions = [], url = "https://spdx.org/licenses/GPL-1.0.html", ) license_kind( name = "GPL-1.0+", conditions = [], url = "https://spdx.org/licenses/GPL-1.0+.html", ) license_kind( name = "GPL-1.0-only", conditions = [], url = "https://spdx.org/licenses/GPL-1.0-only.html", ) license_kind( name = "GPL-1.0-or-later", conditions = [], url = "https://spdx.org/licenses/GPL-1.0-or-later.html", ) license_kind( name = "GPL-2.0", conditions = [], url = "https://spdx.org/licenses/GPL-2.0.html", ) license_kind( name = "GPL-2.0+", conditions = [], url = "https://spdx.org/licenses/GPL-2.0+.html", ) license_kind( name = "GPL-2.0-only", conditions = [], url = "https://spdx.org/licenses/GPL-2.0-only.html", ) license_kind( name = "GPL-2.0-or-later", conditions = [], url = "https://spdx.org/licenses/GPL-2.0-or-later.html", ) license_kind( name = "GPL-2.0-with-autoconf-exception", conditions = [], url = "https://spdx.org/licenses/GPL-2.0-with-autoconf-exception.html", ) license_kind( name = "GPL-2.0-with-bison-exception", conditions = [], url = "https://spdx.org/licenses/GPL-2.0-with-bison-exception.html", ) license_kind( name = "GPL-2.0-with-classpath-exception", conditions = [], url = "https://spdx.org/licenses/GPL-2.0-with-classpath-exception.html", ) license_kind( name = "GPL-2.0-with-font-exception", conditions = [], url = "https://spdx.org/licenses/GPL-2.0-with-font-exception.html", ) license_kind( name = "GPL-2.0-with-GCC-exception", conditions = [], url = "https://spdx.org/licenses/GPL-2.0-with-GCC-exception.html", ) license_kind( name = "GPL-3.0", conditions = [], url = "https://spdx.org/licenses/GPL-3.0.html", ) license_kind( name = "GPL-3.0+", conditions = [], url = "https://spdx.org/licenses/GPL-3.0+.html", ) license_kind( name = "GPL-3.0-only", conditions = [], url = "https://spdx.org/licenses/GPL-3.0-only.html", ) license_kind( name = "GPL-3.0-or-later", conditions = [], url = "https://spdx.org/licenses/GPL-3.0-or-later.html", ) license_kind( name = "GPL-3.0-with-autoconf-exception", conditions = [], url = "https://spdx.org/licenses/GPL-3.0-with-autoconf-exception.html", ) license_kind( name = "GPL-3.0-with-GCC-exception", conditions = [], url = "https://spdx.org/licenses/GPL-3.0-with-GCC-exception.html", ) license_kind( name = "gSOAP-1.3b", conditions = [], url = "https://spdx.org/licenses/gSOAP-1.3b.html", ) license_kind( name = "HaskellReport", conditions = [], url = "https://spdx.org/licenses/HaskellReport.html", ) license_kind( name = "Hippocratic-2.1", conditions = [], url = "https://spdx.org/licenses/Hippocratic-2.1.html", ) license_kind( name = "HPND", conditions = [], url = "https://spdx.org/licenses/HPND.html", ) license_kind( name = "HPND-sell-variant", conditions = [], url = "https://spdx.org/licenses/HPND-sell-variant.html", ) license_kind( name = "HTMLTIDY", conditions = [], url = "https://spdx.org/licenses/HTMLTIDY.html", ) license_kind( name = "IBM-pibs", conditions = [], url = "https://spdx.org/licenses/IBM-pibs.html", ) license_kind( name = "ICU", conditions = [], url = "https://spdx.org/licenses/ICU.html", ) license_kind( name = "IJG", conditions = [], url = "https://spdx.org/licenses/IJG.html", ) license_kind( name = "ImageMagick", conditions = [], url = "https://spdx.org/licenses/ImageMagick.html", ) license_kind( name = "iMatix", conditions = [], url = "https://spdx.org/licenses/iMatix.html", ) license_kind( name = "Imlib2", conditions = [], url = "https://spdx.org/licenses/Imlib2.html", ) license_kind( name = "Info-ZIP", conditions = [], url = "https://spdx.org/licenses/Info-ZIP.html", ) license_kind( name = "Intel", conditions = [], url = "https://spdx.org/licenses/Intel.html", ) license_kind( name = "Intel-ACPI", conditions = [], url = "https://spdx.org/licenses/Intel-ACPI.html", ) license_kind( name = "Interbase-1.0", conditions = [], url = "https://spdx.org/licenses/Interbase-1.0.html", ) license_kind( name = "IPA", conditions = [], url = "https://spdx.org/licenses/IPA.html", ) license_kind( name = "IPL-1.0", conditions = [], url = "https://spdx.org/licenses/IPL-1.0.html", ) license_kind( name = "ISC", conditions = [], url = "https://spdx.org/licenses/ISC.html", ) license_kind( name = "Jam", conditions = [], url = "https://spdx.org/licenses/Jam.html", ) license_kind( name = "JasPer-2.0", conditions = [], url = "https://spdx.org/licenses/JasPer-2.0.html", ) license_kind( name = "JPNIC", conditions = [], url = "https://spdx.org/licenses/JPNIC.html", ) license_kind( name = "JSON", conditions = [], url = "https://spdx.org/licenses/JSON.html", ) license_kind( name = "KiCad-libraries-exception", conditions = [], url = "https://spdx.org/licenses/KiCad-libraries-exception.html", ) license_kind( name = "LAL-1.2", conditions = [], url = "https://spdx.org/licenses/LAL-1.2.html", ) license_kind( name = "LAL-1.3", conditions = [], url = "https://spdx.org/licenses/LAL-1.3.html", ) license_kind( name = "Latex2e", conditions = [], url = "https://spdx.org/licenses/Latex2e.html", ) license_kind( name = "Leptonica", conditions = [], url = "https://spdx.org/licenses/Leptonica.html", ) license_kind( name = "LGPL-2.0", conditions = [], url = "https://spdx.org/licenses/LGPL-2.0.html", ) license_kind( name = "LGPL-2.0+", conditions = [], url = "https://spdx.org/licenses/LGPL-2.0+.html", ) license_kind( name = "LGPL-2.0-only", conditions = [], url = "https://spdx.org/licenses/LGPL-2.0-only.html", ) license_kind( name = "LGPL-2.0-or-later", conditions = [], url = "https://spdx.org/licenses/LGPL-2.0-or-later.html", ) license_kind( name = "LGPL-2.1", conditions = [], url = "https://spdx.org/licenses/LGPL-2.1.html", ) license_kind( name = "LGPL-2.1+", conditions = [], url = "https://spdx.org/licenses/LGPL-2.1+.html", ) license_kind( name = "LGPL-2.1-only", conditions = [], url = "https://spdx.org/licenses/LGPL-2.1-only.html", ) license_kind( name = "LGPL-2.1-or-later", conditions = [], url = "https://spdx.org/licenses/LGPL-2.1-or-later.html", ) license_kind( name = "LGPL-3.0", conditions = [], url = "https://spdx.org/licenses/LGPL-3.0.html", ) license_kind( name = "LGPL-3.0+", conditions = [], url = "https://spdx.org/licenses/LGPL-3.0+.html", ) license_kind( name = "LGPL-3.0-only", conditions = [], url = "https://spdx.org/licenses/LGPL-3.0-only.html", ) license_kind( name = "LGPL-3.0-or-later", conditions = [], url = "https://spdx.org/licenses/LGPL-3.0-or-later.html", ) license_kind( name = "LGPLLR", conditions = [], url = "https://spdx.org/licenses/LGPLLR.html", ) license_kind( name = "Libpng", conditions = [], url = "https://spdx.org/licenses/Libpng.html", ) license_kind( name = "libpng-2.0", conditions = [], url = "https://spdx.org/licenses/libpng-2.0.html", ) license_kind( name = "libselinux-1.0", conditions = [], url = "https://spdx.org/licenses/libselinux-1.0.html", ) license_kind( name = "libtiff", conditions = [], url = "https://spdx.org/licenses/libtiff.html", ) license_kind( name = "LiLiQ-P-1.1", conditions = [], url = "https://spdx.org/licenses/LiLiQ-P-1.1.html", ) license_kind( name = "LiLiQ-R-1.1", conditions = [], url = "https://spdx.org/licenses/LiLiQ-R-1.1.html", ) license_kind( name = "LiLiQ-Rplus-1.1", conditions = [], url = "https://spdx.org/licenses/LiLiQ-Rplus-1.1.html", ) license_kind( name = "Linux-man-pages-copyleft", conditions = [], url = "https://spdx.org/licenses/Linux-man-pages-copyleft.html", ) license_kind( name = "Linux-OpenIB", conditions = [], url = "https://spdx.org/licenses/Linux-OpenIB.html", ) license_kind( name = "LPL-1.0", conditions = [], url = "https://spdx.org/licenses/LPL-1.0.html", ) license_kind( name = "LPL-1.02", conditions = [], url = "https://spdx.org/licenses/LPL-1.02.html", ) license_kind( name = "LPPL-1.0", conditions = [], url = "https://spdx.org/licenses/LPPL-1.0.html", ) license_kind( name = "LPPL-1.1", conditions = [], url = "https://spdx.org/licenses/LPPL-1.1.html", ) license_kind( name = "LPPL-1.2", conditions = [], url = "https://spdx.org/licenses/LPPL-1.2.html", ) license_kind( name = "LPPL-1.3a", conditions = [], url = "https://spdx.org/licenses/LPPL-1.3a.html", ) license_kind( name = "LPPL-1.3c", conditions = [], url = "https://spdx.org/licenses/LPPL-1.3c.html", ) license_kind( name = "MakeIndex", conditions = [], url = "https://spdx.org/licenses/MakeIndex.html", ) license_kind( name = "MirOS", conditions = [], url = "https://spdx.org/licenses/MirOS.html", ) license_kind( name = "MIT", conditions = [], url = "https://spdx.org/licenses/MIT.html", ) license_kind( name = "MIT-0", conditions = [], url = "https://spdx.org/licenses/MIT-0.html", ) license_kind( name = "MIT-advertising", conditions = [], url = "https://spdx.org/licenses/MIT-advertising.html", ) license_kind( name = "MIT-CMU", conditions = [], url = "https://spdx.org/licenses/MIT-CMU.html", ) license_kind( name = "MIT-enna", conditions = [], url = "https://spdx.org/licenses/MIT-enna.html", ) license_kind( name = "MIT-feh", conditions = [], url = "https://spdx.org/licenses/MIT-feh.html", ) license_kind( name = "MIT-Modern-Variant", conditions = [], url = "https://spdx.org/licenses/MIT-Modern-Variant.html", ) license_kind( name = "MIT-open-group", conditions = [], url = "https://spdx.org/licenses/MIT-open-group.html", ) license_kind( name = "MITNFA", conditions = [], url = "https://spdx.org/licenses/MITNFA.html", ) license_kind( name = "Motosoto", conditions = [], url = "https://spdx.org/licenses/Motosoto.html", ) license_kind( name = "mpich2", conditions = [], url = "https://spdx.org/licenses/mpich2.html", ) license_kind( name = "MPL-1.0", conditions = [], url = "https://spdx.org/licenses/MPL-1.0.html", ) license_kind( name = "MPL-1.1", conditions = [], url = "https://spdx.org/licenses/MPL-1.1.html", ) license_kind( name = "MPL-2.0", conditions = [], url = "https://spdx.org/licenses/MPL-2.0.html", ) license_kind( name = "MPL-2.0-no-copyleft-exception", conditions = [], url = "https://spdx.org/licenses/MPL-2.0-no-copyleft-exception.html", ) license_kind( name = "mplus", conditions = [], url = "https://spdx.org/licenses/mplus.html", ) license_kind( name = "MS-PL", conditions = [], url = "https://spdx.org/licenses/MS-PL.html", ) license_kind( name = "MS-RL", conditions = [], url = "https://spdx.org/licenses/MS-RL.html", ) license_kind( name = "MTLL", conditions = [], url = "https://spdx.org/licenses/MTLL.html", ) license_kind( name = "MulanPSL-1.0", conditions = [], url = "https://spdx.org/licenses/MulanPSL-1.0.html", ) license_kind( name = "MulanPSL-2.0", conditions = [], url = "https://spdx.org/licenses/MulanPSL-2.0.html", ) license_kind( name = "Multics", conditions = [], url = "https://spdx.org/licenses/Multics.html", ) license_kind( name = "Mup", conditions = [], url = "https://spdx.org/licenses/Mup.html", ) license_kind( name = "NAIST-2003", conditions = [], url = "https://spdx.org/licenses/NAIST-2003.html", ) license_kind( name = "NASA-1.3", conditions = [], url = "https://spdx.org/licenses/NASA-1.3.html", ) license_kind( name = "Naumen", conditions = [], url = "https://spdx.org/licenses/Naumen.html", ) license_kind( name = "NBPL-1.0", conditions = [], url = "https://spdx.org/licenses/NBPL-1.0.html", ) license_kind( name = "NCGL-UK-2.0", conditions = [], url = "https://spdx.org/licenses/NCGL-UK-2.0.html", ) license_kind( name = "NCSA", conditions = [], url = "https://spdx.org/licenses/NCSA.html", ) license_kind( name = "Net-SNMP", conditions = [], url = "https://spdx.org/licenses/Net-SNMP.html", ) license_kind( name = "NetCDF", conditions = [], url = "https://spdx.org/licenses/NetCDF.html", ) license_kind( name = "Newsletr", conditions = [], url = "https://spdx.org/licenses/Newsletr.html", ) license_kind( name = "NGPL", conditions = [], url = "https://spdx.org/licenses/NGPL.html", ) license_kind( name = "NIST-PD", conditions = [], url = "https://spdx.org/licenses/NIST-PD.html", ) license_kind( name = "NIST-PD-fallback", conditions = [], url = "https://spdx.org/licenses/NIST-PD-fallback.html", ) license_kind( name = "NLOD-1.0", conditions = [], url = "https://spdx.org/licenses/NLOD-1.0.html", ) license_kind( name = "NLOD-2.0", conditions = [], url = "https://spdx.org/licenses/NLOD-2.0.html", ) license_kind( name = "NLPL", conditions = [], url = "https://spdx.org/licenses/NLPL.html", ) license_kind( name = "Nokia", conditions = [], url = "https://spdx.org/licenses/Nokia.html", ) license_kind( name = "NOSL", conditions = [], url = "https://spdx.org/licenses/NOSL.html", ) license_kind( name = "Noweb", conditions = [], url = "https://spdx.org/licenses/Noweb.html", ) license_kind( name = "NPL-1.0", conditions = [], url = "https://spdx.org/licenses/NPL-1.0.html", ) license_kind( name = "NPL-1.1", conditions = [], url = "https://spdx.org/licenses/NPL-1.1.html", ) license_kind( name = "NPOSL-3.0", conditions = [], url = "https://spdx.org/licenses/NPOSL-3.0.html", ) license_kind( name = "NRL", conditions = [], url = "https://spdx.org/licenses/NRL.html", ) license_kind( name = "NTP", conditions = [], url = "https://spdx.org/licenses/NTP.html", ) license_kind( name = "NTP-0", conditions = [], url = "https://spdx.org/licenses/NTP-0.html", ) license_kind( name = "Nunit", conditions = [], url = "https://spdx.org/licenses/Nunit.html", ) license_kind( name = "O-UDA-1.0", conditions = [], url = "https://spdx.org/licenses/O-UDA-1.0.html", ) license_kind( name = "OCCT-PL", conditions = [], url = "https://spdx.org/licenses/OCCT-PL.html", ) license_kind( name = "OCLC-2.0", conditions = [], url = "https://spdx.org/licenses/OCLC-2.0.html", ) license_kind( name = "ODbL-1.0", conditions = [], url = "https://spdx.org/licenses/ODbL-1.0.html", ) license_kind( name = "ODC-By-1.0", conditions = [], url = "https://spdx.org/licenses/ODC-By-1.0.html", ) license_kind( name = "OFL-1.0", conditions = [], url = "https://spdx.org/licenses/OFL-1.0.html", ) license_kind( name = "OFL-1.0-no-RFN", conditions = [], url = "https://spdx.org/licenses/OFL-1.0-no-RFN.html", ) license_kind( name = "OFL-1.0-RFN", conditions = [], url = "https://spdx.org/licenses/OFL-1.0-RFN.html", ) license_kind( name = "OFL-1.1", conditions = [], url = "https://spdx.org/licenses/OFL-1.1.html", ) license_kind( name = "OFL-1.1-no-RFN", conditions = [], url = "https://spdx.org/licenses/OFL-1.1-no-RFN.html", ) license_kind( name = "OFL-1.1-RFN", conditions = [], url = "https://spdx.org/licenses/OFL-1.1-RFN.html", ) license_kind( name = "OGC-1.0", conditions = [], url = "https://spdx.org/licenses/OGC-1.0.html", ) license_kind( name = "OGDL-Taiwan-1.0", conditions = [], url = "https://spdx.org/licenses/OGDL-Taiwan-1.0.html", ) license_kind( name = "OGL-Canada-2.0", conditions = [], url = "https://spdx.org/licenses/OGL-Canada-2.0.html", ) license_kind( name = "OGL-UK-1.0", conditions = [], url = "https://spdx.org/licenses/OGL-UK-1.0.html", ) license_kind( name = "OGL-UK-2.0", conditions = [], url = "https://spdx.org/licenses/OGL-UK-2.0.html", ) license_kind( name = "OGL-UK-3.0", conditions = [], url = "https://spdx.org/licenses/OGL-UK-3.0.html", ) license_kind( name = "OGTSL", conditions = [], url = "https://spdx.org/licenses/OGTSL.html", ) license_kind( name = "OLDAP-1.1", conditions = [], url = "https://spdx.org/licenses/OLDAP-1.1.html", ) license_kind( name = "OLDAP-1.2", conditions = [], url = "https://spdx.org/licenses/OLDAP-1.2.html", ) license_kind( name = "OLDAP-1.3", conditions = [], url = "https://spdx.org/licenses/OLDAP-1.3.html", ) license_kind( name = "OLDAP-1.4", conditions = [], url = "https://spdx.org/licenses/OLDAP-1.4.html", ) license_kind( name = "OLDAP-2.0", conditions = [], url = "https://spdx.org/licenses/OLDAP-2.0.html", ) license_kind( name = "OLDAP-2.0.1", conditions = [], url = "https://spdx.org/licenses/OLDAP-2.0.1.html", ) license_kind( name = "OLDAP-2.1", conditions = [], url = "https://spdx.org/licenses/OLDAP-2.1.html", ) license_kind( name = "OLDAP-2.2", conditions = [], url = "https://spdx.org/licenses/OLDAP-2.2.html", ) license_kind( name = "OLDAP-2.2.1", conditions = [], url = "https://spdx.org/licenses/OLDAP-2.2.1.html", ) license_kind( name = "OLDAP-2.2.2", conditions = [], url = "https://spdx.org/licenses/OLDAP-2.2.2.html", ) license_kind( name = "OLDAP-2.3", conditions = [], url = "https://spdx.org/licenses/OLDAP-2.3.html", ) license_kind( name = "OLDAP-2.4", conditions = [], url = "https://spdx.org/licenses/OLDAP-2.4.html", ) license_kind( name = "OLDAP-2.5", conditions = [], url = "https://spdx.org/licenses/OLDAP-2.5.html", ) license_kind( name = "OLDAP-2.6", conditions = [], url = "https://spdx.org/licenses/OLDAP-2.6.html", ) license_kind( name = "OLDAP-2.7", conditions = [], url = "https://spdx.org/licenses/OLDAP-2.7.html", ) license_kind( name = "OLDAP-2.8", conditions = [], url = "https://spdx.org/licenses/OLDAP-2.8.html", ) license_kind( name = "OML", conditions = [], url = "https://spdx.org/licenses/OML.html", ) license_kind( name = "OpenSSL", conditions = [], url = "https://spdx.org/licenses/OpenSSL.html", ) license_kind( name = "OPL-1.0", conditions = [], url = "https://spdx.org/licenses/OPL-1.0.html", ) license_kind( name = "OPUBL-1.0", conditions = [], url = "https://spdx.org/licenses/OPUBL-1.0.html", ) license_kind( name = "OSET-PL-2.1", conditions = [], url = "https://spdx.org/licenses/OSET-PL-2.1.html", ) license_kind( name = "OSL-1.0", conditions = [], url = "https://spdx.org/licenses/OSL-1.0.html", ) license_kind( name = "OSL-1.1", conditions = [], url = "https://spdx.org/licenses/OSL-1.1.html", ) license_kind( name = "OSL-2.0", conditions = [], url = "https://spdx.org/licenses/OSL-2.0.html", ) license_kind( name = "OSL-2.1", conditions = [], url = "https://spdx.org/licenses/OSL-2.1.html", ) license_kind( name = "OSL-3.0", conditions = [], url = "https://spdx.org/licenses/OSL-3.0.html", ) license_kind( name = "Parity-6.0.0", conditions = [], url = "https://spdx.org/licenses/Parity-6.0.0.html", ) license_kind( name = "Parity-7.0.0", conditions = [], url = "https://spdx.org/licenses/Parity-7.0.0.html", ) license_kind( name = "PDDL-1.0", conditions = [], url = "https://spdx.org/licenses/PDDL-1.0.html", ) license_kind( name = "PHP-3.0", conditions = [], url = "https://spdx.org/licenses/PHP-3.0.html", ) license_kind( name = "PHP-3.01", conditions = [], url = "https://spdx.org/licenses/PHP-3.01.html", ) license_kind( name = "Plexus", conditions = [], url = "https://spdx.org/licenses/Plexus.html", ) license_kind( name = "PolyForm-Noncommercial-1.0.0", conditions = [], url = "https://spdx.org/licenses/PolyForm-Noncommercial-1.0.0.html", ) license_kind( name = "PolyForm-Small-Business-1.0.0", conditions = [], url = "https://spdx.org/licenses/PolyForm-Small-Business-1.0.0.html", ) license_kind( name = "PostgreSQL", conditions = [], url = "https://spdx.org/licenses/PostgreSQL.html", ) license_kind( name = "PSF-2.0", conditions = [], url = "https://spdx.org/licenses/PSF-2.0.html", ) license_kind( name = "psfrag", conditions = [], url = "https://spdx.org/licenses/psfrag.html", ) license_kind( name = "psutils", conditions = [], url = "https://spdx.org/licenses/psutils.html", ) license_kind( name = "Python-2.0", conditions = [], url = "https://spdx.org/licenses/Python-2.0.html", ) license_kind( name = "Qhull", conditions = [], url = "https://spdx.org/licenses/Qhull.html", ) license_kind( name = "QPL-1.0", conditions = [], url = "https://spdx.org/licenses/QPL-1.0.html", ) license_kind( name = "Rdisc", conditions = [], url = "https://spdx.org/licenses/Rdisc.html", ) license_kind( name = "RHeCos-1.1", conditions = [], url = "https://spdx.org/licenses/RHeCos-1.1.html", ) license_kind( name = "RPL-1.1", conditions = [], url = "https://spdx.org/licenses/RPL-1.1.html", ) license_kind( name = "RPL-1.5", conditions = [], url = "https://spdx.org/licenses/RPL-1.5.html", ) license_kind( name = "RPSL-1.0", conditions = [], url = "https://spdx.org/licenses/RPSL-1.0.html", ) license_kind( name = "RSA-MD", conditions = [], url = "https://spdx.org/licenses/RSA-MD.html", ) license_kind( name = "RSCPL", conditions = [], url = "https://spdx.org/licenses/RSCPL.html", ) license_kind( name = "Ruby", conditions = [], url = "https://spdx.org/licenses/Ruby.html", ) license_kind( name = "SAX-PD", conditions = [], url = "https://spdx.org/licenses/SAX-PD.html", ) license_kind( name = "Saxpath", conditions = [], url = "https://spdx.org/licenses/Saxpath.html", ) license_kind( name = "SCEA", conditions = [], url = "https://spdx.org/licenses/SCEA.html", ) license_kind( name = "SchemeReport", conditions = [], url = "https://spdx.org/licenses/SchemeReport.html", ) license_kind( name = "Sendmail", conditions = [], url = "https://spdx.org/licenses/Sendmail.html", ) license_kind( name = "Sendmail-8.23", conditions = [], url = "https://spdx.org/licenses/Sendmail-8.23.html", ) license_kind( name = "SGI-B-1.0", conditions = [], url = "https://spdx.org/licenses/SGI-B-1.0.html", ) license_kind( name = "SGI-B-1.1", conditions = [], url = "https://spdx.org/licenses/SGI-B-1.1.html", ) license_kind( name = "SGI-B-2.0", conditions = [], url = "https://spdx.org/licenses/SGI-B-2.0.html", ) license_kind( name = "SHL-0.5", conditions = [], url = "https://spdx.org/licenses/SHL-0.5.html", ) license_kind( name = "SHL-0.51", conditions = [], url = "https://spdx.org/licenses/SHL-0.51.html", ) license_kind( name = "SimPL-2.0", conditions = [], url = "https://spdx.org/licenses/SimPL-2.0.html", ) license_kind( name = "SISSL", conditions = [], url = "https://spdx.org/licenses/SISSL.html", ) license_kind( name = "SISSL-1.2", conditions = [], url = "https://spdx.org/licenses/SISSL-1.2.html", ) license_kind( name = "Sleepycat", conditions = [], url = "https://spdx.org/licenses/Sleepycat.html", ) license_kind( name = "SMLNJ", conditions = [], url = "https://spdx.org/licenses/SMLNJ.html", ) license_kind( name = "SMPPL", conditions = [], url = "https://spdx.org/licenses/SMPPL.html", ) license_kind( name = "SNIA", conditions = [], url = "https://spdx.org/licenses/SNIA.html", ) license_kind( name = "Spencer-86", conditions = [], url = "https://spdx.org/licenses/Spencer-86.html", ) license_kind( name = "Spencer-94", conditions = [], url = "https://spdx.org/licenses/Spencer-94.html", ) license_kind( name = "Spencer-99", conditions = [], url = "https://spdx.org/licenses/Spencer-99.html", ) license_kind( name = "SPL-1.0", conditions = [], url = "https://spdx.org/licenses/SPL-1.0.html", ) license_kind( name = "SSH-OpenSSH", conditions = [], url = "https://spdx.org/licenses/SSH-OpenSSH.html", ) license_kind( name = "SSH-short", conditions = [], url = "https://spdx.org/licenses/SSH-short.html", ) license_kind( name = "SSPL-1.0", conditions = [], url = "https://spdx.org/licenses/SSPL-1.0.html", ) license_kind( name = "StandardML-NJ", conditions = [], url = "https://spdx.org/licenses/StandardML-NJ.html", ) license_kind( name = "SugarCRM-1.1.3", conditions = [], url = "https://spdx.org/licenses/SugarCRM-1.1.3.html", ) license_kind( name = "SWL", conditions = [], url = "https://spdx.org/licenses/SWL.html", ) license_kind( name = "TAPR-OHL-1.0", conditions = [], url = "https://spdx.org/licenses/TAPR-OHL-1.0.html", ) license_kind( name = "TCL", conditions = [], url = "https://spdx.org/licenses/TCL.html", ) license_kind( name = "TCP-wrappers", conditions = [], url = "https://spdx.org/licenses/TCP-wrappers.html", ) license_kind( name = "TMate", conditions = [], url = "https://spdx.org/licenses/TMate.html", ) license_kind( name = "TORQUE-1.1", conditions = [], url = "https://spdx.org/licenses/TORQUE-1.1.html", ) license_kind( name = "TOSL", conditions = [], url = "https://spdx.org/licenses/TOSL.html", ) license_kind( name = "TU-Berlin-1.0", conditions = [], url = "https://spdx.org/licenses/TU-Berlin-1.0.html", ) license_kind( name = "TU-Berlin-2.0", conditions = [], url = "https://spdx.org/licenses/TU-Berlin-2.0.html", ) license_kind( name = "UCL-1.0", conditions = [], url = "https://spdx.org/licenses/UCL-1.0.html", ) license_kind( name = "Unicode-DFS-2015", conditions = [], url = "https://spdx.org/licenses/Unicode-DFS-2015.html", ) license_kind( name = "Unicode-DFS-2016", conditions = [], url = "https://spdx.org/licenses/Unicode-DFS-2016.html", ) license_kind( name = "Unicode-TOU", conditions = [], url = "https://spdx.org/licenses/Unicode-TOU.html", ) license_kind( name = "Unlicense", conditions = [], url = "https://spdx.org/licenses/Unlicense.html", ) license_kind( name = "UPL-1.0", conditions = [], url = "https://spdx.org/licenses/UPL-1.0.html", ) license_kind( name = "Vim", conditions = [], url = "https://spdx.org/licenses/Vim.html", ) license_kind( name = "VOSTROM", conditions = [], url = "https://spdx.org/licenses/VOSTROM.html", ) license_kind( name = "VSL-1.0", conditions = [], url = "https://spdx.org/licenses/VSL-1.0.html", ) license_kind( name = "W3C", conditions = [], url = "https://spdx.org/licenses/W3C.html", ) license_kind( name = "W3C-19980720", conditions = [], url = "https://spdx.org/licenses/W3C-19980720.html", ) license_kind( name = "W3C-20150513", conditions = [], url = "https://spdx.org/licenses/W3C-20150513.html", ) license_kind( name = "Watcom-1.0", conditions = [], url = "https://spdx.org/licenses/Watcom-1.0.html", ) license_kind( name = "Wsuipa", conditions = [], url = "https://spdx.org/licenses/Wsuipa.html", ) license_kind( name = "WTFPL", conditions = [], url = "https://spdx.org/licenses/WTFPL.html", ) license_kind( name = "wxWindows", conditions = [], url = "https://spdx.org/licenses/wxWindows.html", ) license_kind( name = "X11", conditions = [], url = "https://spdx.org/licenses/X11.html", ) license_kind( name = "X11-distribute-modifications-variant", conditions = [], url = "https://spdx.org/licenses/X11-distribute-modifications-variant.html", ) license_kind( name = "Xerox", conditions = [], url = "https://spdx.org/licenses/Xerox.html", ) license_kind( name = "XFree86-1.1", conditions = [], url = "https://spdx.org/licenses/XFree86-1.1.html", ) license_kind( name = "xinetd", conditions = [], url = "https://spdx.org/licenses/xinetd.html", ) license_kind( name = "Xnet", conditions = [], url = "https://spdx.org/licenses/Xnet.html", ) license_kind( name = "xpp", conditions = [], url = "https://spdx.org/licenses/xpp.html", ) license_kind( name = "XSkat", conditions = [], url = "https://spdx.org/licenses/XSkat.html", ) license_kind( name = "YPL-1.0", conditions = [], url = "https://spdx.org/licenses/YPL-1.0.html", ) license_kind( name = "YPL-1.1", conditions = [], url = "https://spdx.org/licenses/YPL-1.1.html", ) license_kind( name = "Zed", conditions = [], url = "https://spdx.org/licenses/Zed.html", ) license_kind( name = "Zend-2.0", conditions = [], url = "https://spdx.org/licenses/Zend-2.0.html", ) license_kind( name = "Zimbra-1.3", conditions = [], url = "https://spdx.org/licenses/Zimbra-1.3.html", ) license_kind( name = "Zimbra-1.4", conditions = [], url = "https://spdx.org/licenses/Zimbra-1.4.html", ) license_kind( name = "Zlib", conditions = [], url = "https://spdx.org/licenses/Zlib.html", ) license_kind( name = "zlib-acknowledgement", conditions = [], url = "https://spdx.org/licenses/zlib-acknowledgement.html", ) license_kind( name = "ZPL-1.1", conditions = [], url = "https://spdx.org/licenses/ZPL-1.1.html", ) license_kind( name = "ZPL-2.0", conditions = [], url = "https://spdx.org/licenses/ZPL-2.0.html", ) license_kind( name = "ZPL-2.1", conditions = [], url = "https://spdx.org/licenses/ZPL-2.1.html", ) rules_license-0.0.7/rules/000077500000000000000000000000001444314666600155225ustar00rootroot00000000000000rules_license-0.0.7/rules/BUILD000066400000000000000000000030561444314666600163100ustar00rootroot00000000000000# BUILD file defining @rules_license/rules # # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Rules for making license declarations.""" load("@rules_license//rules_gathering:trace.bzl", "trace") package( default_applicable_licenses = ["//:license"], default_visibility = ["//visibility:public"], ) licenses(["notice"]) # This target controls the value of the traced target used during dependency collection. # This value should always be the empty string! # Specify this value with a flag, like --@rules_license//rules:trace_target=//target/to:trace trace( name = "trace_target", build_setting_default = "", # TRACE-TARGET-SHOULD-BE-EMPTY visibility = ["//visibility:public"], ) filegroup( name = "standard_package", srcs = glob([ "**/BUILD", "**/*.bzl", ]), ) # Do not create a bzl_library(). That would create a dependency loop back # to bazel-skylib. We export the .bzl files to the documentation maker. exports_files( glob([ "*.bzl", ]), visibility = ["//doc_build:__pkg__"], ) rules_license-0.0.7/rules/check_licenses_shim.bzl000066400000000000000000000026701444314666600222220ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """This module provides a custom Starlark rule used to create wrappers for targets that can have blaze build --check_licenses executed against them.""" def _shim_rule_impl(ctx): # This rule doesn't need to return anything. It only exists to propagate the dependency supplied # by the label_flag return [] shim_rule = rule( doc = """This rule exists to configure a dependent target via label. An instantiation of this rule is then used as a dependency for the legacy_check_target rule, which can be built with --check_licenses to get the effect of running --check_licenses on an arbitrary target which may or may not have a distribs attribute""", implementation = _shim_rule_impl, # The definition of this attribute creates a dependency relationship on the manually provided label. attrs = {"target": attr.label(default = ":check_licenses_target")}, ) rules_license-0.0.7/rules/compliance.bzl000066400000000000000000000125721444314666600203540ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """License compliance checking.""" load( "@rules_license//rules:gather_licenses_info.bzl", "gather_licenses_info", "gather_licenses_info_and_write", "write_licenses_info", ) load( "@rules_license//rules_gathering:gathering_providers.bzl", "TransitiveLicensesInfo", ) # Forward licenses used until users migrate. Delete at 0.0.7 or 0.1.0. load( "@rules_license//sample_reports:licenses_used.bzl", _licenses_used = "licenses_used", ) licenses_used = _licenses_used # This rule is proof of concept, and may not represent the final # form of a rule for compliance validation. def _check_license_impl(ctx): # Gather all licenses and write information to one place licenses_file = ctx.actions.declare_file("_%s_licenses_info.json" % ctx.label.name) write_licenses_info(ctx, ctx.attr.deps, licenses_file) license_files = [] if ctx.outputs.license_texts: license_files = get_licenses_mapping(ctx.attr.deps).keys() # Now run the checker on it inputs = [licenses_file] outputs = [ctx.outputs.report] args = ctx.actions.args() args.add("--licenses_info", licenses_file.path) args.add("--report", ctx.outputs.report.path) if ctx.attr.check_conditions: args.add("--check_conditions") if ctx.outputs.copyright_notices: args.add("--copyright_notices", ctx.outputs.copyright_notices.path) outputs.append(ctx.outputs.copyright_notices) if ctx.outputs.license_texts: args.add("--license_texts", ctx.outputs.license_texts.path) outputs.append(ctx.outputs.license_texts) inputs.extend(license_files) ctx.actions.run( mnemonic = "CheckLicenses", progress_message = "Checking license compliance for %s" % ctx.label, inputs = inputs, outputs = outputs, executable = ctx.executable._checker, arguments = [args], ) outputs.append(licenses_file) # also make the json file available. return [DefaultInfo(files = depset(outputs))] _check_license = rule( implementation = _check_license_impl, attrs = { "deps": attr.label_list( aspects = [gather_licenses_info], ), "check_conditions": attr.bool(default = True, mandatory = False), "copyright_notices": attr.output(mandatory = False), "license_texts": attr.output(mandatory = False), "report": attr.output(mandatory = True), "_checker": attr.label( default = Label("@rules_license//tools:checker_demo"), executable = True, allow_files = True, cfg = "exec", ), }, ) # TODO(b/152546336): Update the check to take a pointer to a condition list. def check_license(**kwargs): _check_license(**kwargs) def _manifest_impl(ctx): # Gather all licenses and make it available as deps for downstream rules # Additionally write the list of license filenames to a file that can # also be used as an input to downstream rules. licenses_file = ctx.actions.declare_file(ctx.attr.out.name) mappings = get_licenses_mapping(ctx.attr.deps, ctx.attr.warn_on_legacy_licenses) ctx.actions.write( output = licenses_file, content = "\n".join([",".join([f.path, p]) for (f, p) in mappings.items()]), ) return [DefaultInfo(files = depset(mappings.keys()))] _manifest = rule( implementation = _manifest_impl, doc = """Internal tmplementation method for manifest().""", attrs = { "deps": attr.label_list( doc = """List of targets to collect license files for.""", aspects = [gather_licenses_info], ), "out": attr.output( doc = """Output file.""", mandatory = True, ), "warn_on_legacy_licenses": attr.bool(default = False), }, ) def manifest(name, deps, out = None, **kwargs): if not out: out = name + ".manifest" _manifest(name = name, deps = deps, out = out, **kwargs) def get_licenses_mapping(deps, warn = False): """Creates list of entries representing all licenses for the deps. Args: deps: a list of deps which should have TransitiveLicensesInfo providers. This requires that you have run the gather_licenses_info aspect over them warn: boolean, if true, display output about legacy targets that need update Returns: {File:package_name} """ tls = [] for dep in deps: lds = dep[TransitiveLicensesInfo].licenses tls.append(lds) ds = depset(transitive = tls) # Ignore any legacy licenses that may be in the report mappings = {} for lic in ds.to_list(): if type(lic.license_text) == "File": mappings[lic.license_text] = lic.package_name elif warn: print("Legacy license %s not included, rule needs updating" % lic.license_text) return mappings rules_license-0.0.7/rules/filtered_rule_kinds.bzl000066400000000000000000000032301444314666600222460ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Filtered rule kinds for aspect inspection. The format of this dictionary is: rule_name: [attr, attr, ...] Only filters for rules that are part of the Bazel distribution should be added to this file. Other filters should be added in user_filtered_rule_kinds.bzl Attributes are either the explicit list of attributes to filter, or '_*' which would ignore all attributes prefixed with a _. """ # Rule kinds with attributes the aspect currently needs to ignore aspect_filters = { "*": ["linter"], "_constant_gen": ["_generator"], "cc_binary": ["_*"], "cc_embed_data": ["_*"], "cc_grpc_library": ["_*"], "cc_library": ["_*"], "cc_toolchain_alias": ["_cc_toolchain"], "genrule": ["tools", "exec_tools", "toolchains"], "genyacc": ["_*"], "go_binary": ["_*"], "go_library": ["_*"], "go_wrap_cc": ["_*"], "java_binary": ["_*", "plugins", "exported_plugins"], "java_library": ["plugins", "exported_plugins"], "java_wrap_cc": ["_cc_toolchain", "swig_top"], "py_binary": ["_*"], "py_extension": ["_cc_toolchain"], "sh_binary": ["_bash_binary"], } rules_license-0.0.7/rules/gather_licenses_info.bzl000066400000000000000000000227321444314666600224130ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Rules and macros for collecting LicenseInfo providers.""" load( "@rules_license//rules:licenses_core.bzl", "gather_metadata_info_common", "should_traverse", ) load( "@rules_license//rules_gathering:gathering_providers.bzl", "TransitiveLicensesInfo", ) load("@rules_license//rules_gathering:trace.bzl", "TraceInfo") def _strip_null_repo(label): """Removes the null repo name (e.g. @//) from a string. The is to make str(label) compatible between bazel 5.x and 6.x """ s = str(label) if s.startswith('@//'): return s[1:] elif s.startswith('@@//'): return s[2:] return s def _gather_licenses_info_impl(target, ctx): return gather_metadata_info_common(target, ctx, TransitiveLicensesInfo, [], should_traverse) gather_licenses_info = aspect( doc = """Collects LicenseInfo providers into a single TransitiveLicensesInfo provider.""", implementation = _gather_licenses_info_impl, attr_aspects = ["*"], attrs = { "_trace": attr.label(default = "@rules_license//rules:trace_target"), }, provides = [TransitiveLicensesInfo], apply_to_generating_rules = True, ) def _write_licenses_info_impl(target, ctx): """Write transitive license info into a JSON file Args: target: The target of the aspect. ctx: The aspect evaluation context. Returns: OutputGroupInfo """ if not TransitiveLicensesInfo in target: return [OutputGroupInfo(licenses = depset())] info = target[TransitiveLicensesInfo] outs = [] # If the result doesn't contain licenses, we simply return the provider if not hasattr(info, "target_under_license"): return [OutputGroupInfo(licenses = depset())] # Write the output file for the target name = "%s_licenses_info.json" % ctx.label.name lic_info, _ = licenses_info_to_json(info) content = "[\n%s\n]\n" % ",\n".join(lic_info) out = ctx.actions.declare_file(name) ctx.actions.write( output = out, content = content, ) outs.append(out) if ctx.attr._trace[TraceInfo].trace: trace = ctx.actions.declare_file("%s_trace_info.json" % ctx.label.name) ctx.actions.write(output = trace, content = "\n".join(info.traces)) outs.append(trace) return [OutputGroupInfo(licenses = depset(outs))] gather_licenses_info_and_write = aspect( doc = """Collects TransitiveLicensesInfo providers and writes JSON representation to a file. Usage: blaze build //some:target \ --aspects=@rules_license//rules:gather_licenses_info.bzl%gather_licenses_info_and_write --output_groups=licenses """, implementation = _write_licenses_info_impl, attr_aspects = ["*"], attrs = { "_trace": attr.label(default = "@rules_license//rules:trace_target"), }, provides = [OutputGroupInfo], requires = [gather_licenses_info], apply_to_generating_rules = True, ) def write_licenses_info(ctx, deps, json_out): """Writes TransitiveLicensesInfo providers for a set of targets as JSON. TODO(aiuto): Document JSON schema. But it is under development, so the current best place to look is at tests/hello_licenses.golden. Usage: write_licenses_info must be called from a rule implementation, where the rule has run the gather_licenses_info aspect on its deps to collect the transitive closure of LicenseInfo providers into a LicenseInfo provider. foo = rule( implementation = _foo_impl, attrs = { "deps": attr.label_list(aspects = [gather_licenses_info]) } ) def _foo_impl(ctx): ... json_file = ctx.actions.declare_file("%s_licenses.json" % ctx.label.name) license_files = write_licenses_info(ctx, ctx.attr.deps, json_file) // process the json file and the license_files referenced by it ctx.actions.run( inputs = [json_file] + license_files executable = ... ) Args: ctx: context of the caller deps: a list of deps which should have TransitiveLicensesInfo providers. This requires that you have run the gather_licenses_info aspect over them json_out: output handle to write the JSON info Returns: A list of License File objects for each of the license paths referenced in the json. """ licenses_json = [] licenses_files = [] for dep in deps: if TransitiveLicensesInfo in dep: transitive_licenses_info = dep[TransitiveLicensesInfo] lic_info, _ = licenses_info_to_json(transitive_licenses_info) licenses_json.extend(lic_info) for info in transitive_licenses_info.licenses.to_list(): if info.license_text: licenses_files.append(info.license_text) ctx.actions.write( output = json_out, content = "[\n%s\n]\n" % ",\n".join(licenses_json), ) return licenses_files def licenses_info_to_json(licenses_info): """Render a single LicenseInfo provider to JSON Args: licenses_info: A LicenseInfo. Returns: [(str)] list of LicenseInfo values rendered as JSON. [(File)] list of Files containing license texts. """ main_template = """ {{ "top_level_target": "{top_level_target}", "dependencies": [{dependencies} ], "licenses": [{licenses} ]\n }}""" dep_template = """ {{ "target_under_license": "{target_under_license}", "licenses": [ {licenses} ] }}""" # TODO(aiuto): 'rule' is a duplicate of 'label' until old users are transitioned license_template = """ {{ "label": "{label}", "rule": "{label}", "license_kinds": [{kinds} ], "copyright_notice": "{copyright_notice}", "package_name": "{package_name}", "package_url": "{package_url}", "package_version": "{package_version}", "license_text": "{license_text}", "used_by": [ {used_by} ] }}""" kind_template = """ {{ "target": "{kind_path}", "name": "{kind_name}", "long_name": "{kind_long_name}", "conditions": {kind_conditions} }}""" # Build reverse map of license to user used_by = {} for dep in licenses_info.deps.to_list(): # Undo the concatenation applied when stored in the provider. dep_licenses = dep.licenses.split(",") for license in dep_licenses: if license not in used_by: used_by[license] = [] used_by[license].append(_strip_null_repo(dep.target_under_license)) all_licenses = [] all_license_text_files = [] for license in sorted(licenses_info.licenses.to_list(), key = lambda x: x.label): kinds = [] for kind in sorted(license.license_kinds, key = lambda x: x.name): if hasattr(kind, "long_name"): long_name = kind.long_name else: long_name = "" kinds.append(kind_template.format( kind_name = kind.name, kind_long_name = long_name, kind_path = kind.label, kind_conditions = kind.conditions, )) if license.license_text: # Special handling for synthetic LicenseInfo text_path = (license.license_text.package + "/" + license.license_text.name if type(license.license_text) == "Label" else license.license_text.path) all_licenses.append(license_template.format( copyright_notice = license.copyright_notice, kinds = ",".join(kinds), license_text = text_path, package_name = license.package_name, package_url = license.package_url, package_version = license.package_version, label = _strip_null_repo(license.label), used_by = ",\n ".join(sorted(['"%s"' % x for x in used_by[str(license.label)]])), )) # Additionally return all File references so that other rules invoking # this method can load license text file contents from external repos # using runfiles all_license_text_files.append(license.license_text) all_deps = [] for dep in sorted(licenses_info.deps.to_list(), key = lambda x: x.target_under_license): # Undo the concatenation applied when stored in the provider. dep_licenses = dep.licenses.split(",") all_deps.append(dep_template.format( target_under_license = _strip_null_repo(dep.target_under_license), licenses = ",\n ".join(sorted(['"%s"' % _strip_null_repo(x) for x in dep_licenses])), )) return [main_template.format( top_level_target = _strip_null_repo(licenses_info.target_under_license), dependencies = ",".join(all_deps), licenses = ",".join(all_licenses), )], all_license_text_files rules_license-0.0.7/rules/gather_metadata.bzl000066400000000000000000000016701444314666600213510ustar00rootroot00000000000000# Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Forwarder for gather_metadata_info. To be deleted before version 0.1.0 """ load( "@rules_license//rules_gathering:gather_metadata.bzl", _gather_metadata_info = "gather_metadata_info", _gather_metadata_info_and_write = "gather_metadata_info_and_write", ) gather_metadata_info = _gather_metadata_info gather_metadata_info_and_write = _gather_metadata_info_and_write rules_license-0.0.7/rules/license.bzl000066400000000000000000000122171444314666600176600ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Rules for declaring the compliance licenses used by a package. """ load( "@rules_license//rules:providers.bzl", "LicenseKindInfo", ) load( "@rules_license//rules:license_impl.bzl", "license_rule_impl", ) # Enable this if your organization requires the license text to be a file # checked into source control instead of, possibly, another rule. _require_license_text_is_a_file = False # This rule must be named "_license" for backwards compatability with older # or Bazel that checked that name explicitly. See # https://github.com/bazelbuild/bazel/commit/bbc221f60bc8c9177470529d85c3e47a5d9aaf21 # TODO(after bazel 7.0 release): Feel free to rename the rule and move. _license = rule( implementation = license_rule_impl, attrs = { "license_kinds": attr.label_list( mandatory = False, doc = "License kind(s) of this license. If multiple license kinds are" + " listed in the LICENSE file, and they all apply, then all" + " should be listed here. If the user can choose a single one" + " of many, then only list one here.", providers = [LicenseKindInfo], # This should be the null configuration, not the exec. cfg = "exec", ), "copyright_notice": attr.string( doc = "Copyright notice.", ), "license_text": attr.label( allow_single_file = True, default = "LICENSE", doc = "The license file.", ), "package_name": attr.string( doc = "A human readable name identifying this package." + " This may be used to produce an index of OSS packages used by" + " an applicatation.", ), "package_url": attr.string( doc = "The URL this instance of the package was download from." + " This may be used to produce an index of OSS packages used by" + " an applicatation.", ), "package_version": attr.string( doc = "A human readable version string identifying this package." + " This may be used to produce an index of OSS packages used" + " by an applicatation. It should be a value that" + " increases over time, rather than a commit hash." ), }, ) # buildifier: disable=function-docstring-args def license( name, license_text = "LICENSE", license_kind = None, license_kinds = None, copyright_notice = None, package_name = None, package_url = None, package_version = None, namespace = None, tags = [], visibility = ["//visibility:public"]): """Wrapper for license rule. @wraps(_license) Args: name: str target name. license_text: str Filename of the license file license_kind: label a single license_kind. Only one of license_kind or license_kinds may be specified license_kinds: list(label) list of license_kind targets. copyright_notice: str Copyright notice associated with this package. package_name: str A human readable name identifying this package. This may be used to produce an index of OSS packages used by an application. package_url: str The canonical URL this package was downloaded from. package_version: str The version corresponding the the URL. tags: list(str) tags applied to the rule visibility: list(label) visibility spec. """ if license_kind: if license_kinds: fail("Can not use both license_kind and license_kinds") license_kinds = [license_kind] if _require_license_text_is_a_file: # Make sure the file exists as named in the rule. A glob expression that # expands to the name of the file is not acceptable. srcs = native.glob([license_text]) if len(srcs) != 1 or srcs[0] != license_text: fail("Specified license file doesn't exist: %s" % license_text) # TODO(0.0.6 release): Remove this warning and fail hard instead. if namespace: # buildifier: disable=print print("license(namespace=) is deprecated.") _license( name = name, license_kinds = license_kinds, license_text = license_text, copyright_notice = copyright_notice, package_name = package_name, package_url = package_url, package_version = package_version, applicable_licenses = [], visibility = visibility, tags = tags, testonly = 0, ) rules_license-0.0.7/rules/license_impl.bzl000066400000000000000000000025551444314666600207050ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Rules for declaring the licenses used by a package. """ load( "@rules_license//rules:providers.bzl", "LicenseInfo", "LicenseKindInfo", ) # Debugging verbosity _VERBOSITY = 0 def _debug(loglevel, msg): if _VERBOSITY > loglevel: print(msg) # buildifier: disable=print # # license() # def license_rule_impl(ctx): provider = LicenseInfo( license_kinds = tuple([k[LicenseKindInfo] for k in ctx.attr.license_kinds]), copyright_notice = ctx.attr.copyright_notice, package_name = ctx.attr.package_name or ctx.build_file_path.rstrip("/BUILD"), package_url = ctx.attr.package_url, package_version = ctx.attr.package_version, license_text = ctx.file.license_text, label = ctx.label, ) _debug(0, provider) return [provider] rules_license-0.0.7/rules/license_kind.bzl000066400000000000000000000043001444314666600206570ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Proof of concept. License restriction.""" load("@rules_license//rules:providers.bzl", "LicenseKindInfo") # # License Kind: The declaration of a well known category of license, for example, # Apache, MIT, LGPL v2. An organization may also declare its own license kinds # that it may user privately. # def _license_kind_impl(ctx): provider = LicenseKindInfo( name = ctx.attr.name, label = "@%s//%s:%s" % ( ctx.label.workspace_name, ctx.label.package, ctx.label.name, ), long_name = ctx.attr.long_name, conditions = ctx.attr.conditions, ) return [provider] _license_kind = rule( implementation = _license_kind_impl, attrs = { "conditions": attr.string_list( doc = "Conditions to be met when using software under this license." + " Conditions are defined by the organization using this license.", mandatory = True, ), "canonical_text": attr.label( doc = "File containing the canonical text for this license. Must be UTF-8 encoded.", allow_single_file = True, ), "long_name": attr.string(doc = "Human readable long name of license."), "url": attr.string(doc = "URL pointing to canonical license definition"), }, ) def license_kind(name, **kwargs): """Wrapper for license_kind. @wraps(_license_kind) """ if "conditions" not in kwargs: kwargs["conditions"] = [] if "long_name" not in kwargs: kwargs["long_name"] = name _license_kind( name = name, applicable_licenses = [], **kwargs ) rules_license-0.0.7/rules/licenses_core.bzl000066400000000000000000000207451444314666600210600ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Rules and macros for collecting LicenseInfo providers.""" load("@rules_license//rules:filtered_rule_kinds.bzl", "aspect_filters") load("@rules_license//rules:providers.bzl", "LicenseInfo") load("@rules_license//rules:user_filtered_rule_kinds.bzl", "user_aspect_filters") load( "@rules_license//rules_gathering:gathering_providers.bzl", "LicensedTargetInfo", "TransitiveLicensesInfo", ) load("@rules_license//rules_gathering:trace.bzl", "TraceInfo") def should_traverse(ctx, attr): """Checks if the dependent attribute should be traversed. Args: ctx: The aspect evaluation context. attr: The name of the attribute to be checked. Returns: True iff the attribute should be traversed. """ k = ctx.rule.kind for filters in [aspect_filters, user_aspect_filters]: always_ignored = filters.get("*", []) if k in filters: attr_matches = filters[k] if (attr in attr_matches or "*" in attr_matches or ("_*" in attr_matches and attr.startswith("_")) or attr in always_ignored): return False for m in attr_matches: if attr == m: return False return True def _get_transitive_metadata(ctx, trans_licenses, trans_other_metadata, trans_package_info, trans_deps, traces, provider, filter_func): attrs = [a for a in dir(ctx.rule.attr)] for name in attrs: if not filter_func(ctx, name): continue a = getattr(ctx.rule.attr, name) # Make anything singleton into a list for convenience. if type(a) != type([]): a = [a] for dep in a: # Ignore anything that isn't a target if type(dep) != "Target": continue # Targets can also include things like input files that won't have the # aspect, so we additionally check for the aspect rather than assume # it's on all targets. Even some regular targets may be synthetic and # not have the aspect. This provides protection against those outlier # cases. if provider in dep: info = dep[provider] if info.licenses: trans_licenses.append(info.licenses) if info.deps: trans_deps.append(info.deps) if info.traces: for trace in info.traces: traces.append("(" + ", ".join([str(ctx.label), ctx.rule.kind, name]) + ") -> " + trace) # We only need one or the other of these stanzas. # If we use a polymorphic approach to metadata providers, then # this works. if hasattr(info, "other_metadata"): if info.other_metadata: trans_other_metadata.append(info.other_metadata) # But if we want more precise type safety, we would have a # trans_* for each type of metadata. That is not user # extensibile. if hasattr(info, "package_info"): if info.package_info: trans_package_info.append(info.package_info) def gather_metadata_info_common(target, ctx, provider_factory, metadata_providers, filter_func): """Collect license and other metadata info from myself and my deps. Any single target might directly depend on a license, or depend on something that transitively depends on a license, or neither. This aspect bundles all those into a single provider. At each level, we add in new direct license deps found and forward up the transitive information collected so far. This is a common abstraction for crawling the dependency graph. It is parameterized to allow specifying the provider that is populated with results. It is configurable to select only a subset of providers. It is also configurable to specify which dependency edges should not be traced for the purpose of tracing the graph. Args: target: The target of the aspect. ctx: The aspect evaluation context. provider_factory: abstracts the provider returned by this aspect metadata_providers: a list of other providers of interest filter_func: a function that returns true iff the dep edge should be ignored Returns: provider of parameterized type """ # First we gather my direct license attachments licenses = [] other_metadata = [] package_info = [] if ctx.rule.kind == "_license": # Don't try to gather licenses from the license rule itself. We'll just # blunder into the text file of the license and pick up the default # attribute of the package, which we don't want. pass else: if hasattr(ctx.rule.attr, "applicable_licenses"): for dep in ctx.rule.attr.applicable_licenses: if LicenseInfo in dep: lic = dep[LicenseInfo] licenses.append(lic) for m_p in metadata_providers: if m_p in dep: other_metadata.append(dep[m_p]) # A hack until https://github.com/bazelbuild/rules_license/issues/89 is # fully resolved. If exec is in the bin_dir path, then the current # configuration is probably cfg = exec. if "-exec-" in ctx.bin_dir.path: return [provider_factory(deps = depset(), licenses = depset(), traces = [])] # Now gather transitive collection of providers from the targets # this target depends upon. trans_licenses = [] trans_other_metadata = [] trans_package_info = [] trans_deps = [] traces = [] _get_transitive_metadata(ctx, trans_licenses, trans_other_metadata, trans_package_info, trans_deps, traces, provider_factory, filter_func) if not licenses and not trans_licenses: return [provider_factory(deps = depset(), licenses = depset(), traces = [])] # If this is the target, start the sequence of traces. if ctx.attr._trace[TraceInfo].trace and ctx.attr._trace[TraceInfo].trace in str(ctx.label): traces = [ctx.attr._trace[TraceInfo].trace] # Trim the number of traces accumulated since the output can be quite large. # A few representative traces are generally sufficient to identify why a dependency # is incorrectly incorporated. if len(traces) > 10: traces = traces[0:10] if licenses: # At this point we have a target and a list of directly used licenses. # Bundle those together so we can report the exact targets that cause the # dependency on each license. Since a list cannot be stored in a # depset, even inside a provider, the list is concatenated into a # string and will be unconcatenated in the output phase. direct_license_uses = [LicensedTargetInfo( target_under_license = target.label, licenses = ",".join([str(x.label) for x in licenses]), )] else: direct_license_uses = None # This is a bit of a hack for bazel 5.x. We can not pass extra fields to # the provider constructor, so we need to do something special for each. # In Bazel 6.x we can use a provider initializer function that would take # all the args and only use the ones it wants. if provider_factory == TransitiveLicensesInfo: return [provider_factory( target_under_license = target.label, licenses = depset(tuple(licenses), transitive = trans_licenses), deps = depset(direct = direct_license_uses, transitive = trans_deps), traces = traces, )] return [provider_factory( target_under_license = target.label, licenses = depset(tuple(licenses), transitive = trans_licenses), other_metadata = depset(tuple(other_metadata), transitive = trans_other_metadata), deps = depset(direct = direct_license_uses, transitive = trans_deps), traces = traces, )] rules_license-0.0.7/rules/package_info.bzl000066400000000000000000000075501444314666600206500ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Rules for declaring metadata about a package.""" load( "@rules_license//rules:providers.bzl", "ExperimentalMetadataInfo", "PackageInfo", ) # # package_info() # def _package_info_impl(ctx): provider = PackageInfo( # Metadata providers must include a type discriminator. We don't need it # to collect the providers, but we do need it to write the JSON. We # key on the type field to look up the correct block of code to pull # data out and format it. We can't to the lookup on the provider class. type = "package_info", label = ctx.label, package_name = ctx.attr.package_name or ctx.build_file_path.rstrip("/BUILD"), package_url = ctx.attr.package_url, package_version = ctx.attr.package_version, ) # Experimental alternate design, using a generic 'data' back to hold things generic_provider = ExperimentalMetadataInfo( type = "package_info_alt", label = ctx.label, data = { "package_name": ctx.attr.package_name or ctx.build_file_path.rstrip("/BUILD"), "package_url": ctx.attr.package_url, "package_version": ctx.attr.package_version } ) return [provider, generic_provider] _package_info = rule( implementation = _package_info_impl, attrs = { "package_name": attr.string( doc = "A human readable name identifying this package." + " This may be used to produce an index of OSS packages used by" + " an applicatation.", ), "package_url": attr.string( doc = "The URL this instance of the package was download from." + " This may be used to produce an index of OSS packages used by" + " an applicatation.", ), "package_version": attr.string( doc = "A human readable version string identifying this package." + " This may be used to produce an index of OSS packages used" + " by an applicatation. It should be a value that" + " increases over time, rather than a commit hash." ), }, ) # buildifier: disable=function-docstring-args def package_info( name, package_name = None, package_url = None, package_version = None, **kwargs): """Wrapper for package_info rule. @wraps(_package_info) Args: name: str target name. package_name: str A human readable name identifying this package. This may be used to produce an index of OSS packages used by an application. package_url: str The canoncial URL this package distribution was retrieved from. Note that, because of local mirroring, that might not be the physical URL it was retrieved from. package_version: str A human readable name identifying version of this package. kwargs: other args. Most are ignored. """ visibility = kwargs.get("visibility") or ["//visibility:public"] _package_info( name = name, package_name = package_name, package_url = package_url, package_version = package_version, applicable_licenses = [], visibility = visibility, tags = [], testonly = 0, ) rules_license-0.0.7/rules/private/000077500000000000000000000000001444314666600171745ustar00rootroot00000000000000rules_license-0.0.7/rules/private/BUILD000066400000000000000000000020461444314666600177600ustar00rootroot00000000000000# Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Rules for making license declarations.""" package( default_applicable_licenses = ["//:license"], default_visibility = ["//visibility:public"], ) licenses(["notice"]) filegroup( name = "standard_package", srcs = glob(["**"]), ) # Do not create a bzl_library(). That would create a dependency loop back # to bazel-skylib. We export the .bzl files to the documentation maker. exports_files( glob([ "*.bzl", ]), visibility = ["//doc_build:__pkg__"], ) rules_license-0.0.7/rules/private/gathering_providers.bzl000066400000000000000000000014761444314666600237620ustar00rootroot00000000000000# Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Temporary forwarder. TODO(2023-07-01): Delete this file. """ load( "@rules_license//rules_gathering:gathering_providers.bzl", _private_TransitiveLicensesInfo = "TransitiveLicensesInfo", ) TransitiveLicensesInfo = _private_TransitiveLicensesInfo rules_license-0.0.7/rules/providers.bzl000066400000000000000000000056021444314666600202530ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Basic providers for license rules. This file should only contain the basic providers needed to create license and package_info declarations. Providers needed to gather them are declared in other places. """ load( "@rules_license//rules_gathering:gathering_providers.bzl", _private_TransitiveLicensesInfo = "TransitiveLicensesInfo", ) LicenseKindInfo = provider( doc = """Provides information about a license_kind instance.""", fields = { "conditions": "list(string): List of conditions to be met when using this packages under this license.", "label": "Label: The full path to the license kind definition.", "long_name": "string: Human readable license name", "name": "string: Canonical license name", }, ) LicenseInfo = provider( doc = """Provides information about a license instance.""", fields = { "copyright_notice": "string: Human readable short copyright notice", "label": "Label: label of the license rule", "license_kinds": "list(LicenseKindInfo): License kinds ", "license_text": "string: The license file path", # TODO(aiuto): move to PackageInfo "package_name": "string: Human readable package name", "package_url": "URL from which this package was downloaded.", "package_version": "Human readable version string", }, ) PackageInfo = provider( doc = """Provides information about a package.""", fields = { "type": "string: How to interpret data", "label": "Label: label of the package_info rule", "package_name": "string: Human readable package name", "package_url": "string: URL from which this package was downloaded.", "package_version": "string: Human readable version string", }, ) # This is more extensible. Because of the provider implementation, having a big # dict of values rather than named fields is not much more costly. # Design choice. Replace data with actual providers, such as PackageInfo ExperimentalMetadataInfo = provider( doc = """Generic bag of metadata.""", fields = { "type": "string: How to interpret data", "label": "Label: label of the metadata rule", "data": "String->any: Map of names to values", }, ) # Deprecated: Use write_licenses_info instead. TransitiveLicensesInfo = _private_TransitiveLicensesInfo rules_license-0.0.7/rules/sbom.bzl000077700000000000000000000000001444314666600261062../rules_gathering/generate_sbom.bzlustar00rootroot00000000000000rules_license-0.0.7/rules/user_filtered_rule_kinds.bzl000066400000000000000000000017501444314666600233110ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Filtered rule kinds for aspect inspection. The format of this dictionary is: rule_name: [attr, attr, ...] Filters for rules that are not part of the Bazel distribution should be added to this file. Attributes are either the explicit list of attributes to filter, or '_*' which would ignore all attributes prefixed with a _. """ # Rule kinds with attributes the aspect currently needs to ignore user_aspect_filters = { } rules_license-0.0.7/rules_gathering/000077500000000000000000000000001444314666600175525ustar00rootroot00000000000000rules_license-0.0.7/rules_gathering/BUILD000066400000000000000000000020201444314666600203260ustar00rootroot00000000000000# Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Rules for making license declarations.""" package( default_applicable_licenses = ["//:license"], default_visibility = ["//visibility:public"], ) filegroup( name = "standard_package", srcs = glob(["**"]), ) # Do not create a bzl_library(). That would create a dependency loop back # to bazel-skylib. We export the .bzl files to the documentation maker. exports_files( glob([ "*.bzl", ]), visibility = ["//doc_build:__pkg__"], ) rules_license-0.0.7/rules_gathering/gather_metadata.bzl000066400000000000000000000251621444314666600234030ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Rules and macros for collecting LicenseInfo providers.""" load( "@rules_license//rules:licenses_core.bzl", "gather_metadata_info_common", "should_traverse", ) load( "@rules_license//rules:providers.bzl", "ExperimentalMetadataInfo", "PackageInfo", ) load( "@rules_license//rules_gathering:gathering_providers.bzl", "TransitiveMetadataInfo", ) load("@rules_license//rules_gathering:trace.bzl", "TraceInfo") def _strip_null_repo(label): """Removes the null repo name (e.g. @//) from a string. The is to make str(label) compatible between bazel 5.x and 6.x """ s = str(label) if s.startswith('@//'): return s[1:] elif s.startswith('@@//'): return s[2:] return s def _bazel_package(label): clean_label = _strip_null_repo(label) return clean_label[0:-(len(label.name) + 1)] def _gather_metadata_info_impl(target, ctx): return gather_metadata_info_common( target, ctx, TransitiveMetadataInfo, [ExperimentalMetadataInfo, PackageInfo], should_traverse) gather_metadata_info = aspect( doc = """Collects LicenseInfo providers into a single TransitiveMetadataInfo provider.""", implementation = _gather_metadata_info_impl, attr_aspects = ["*"], attrs = { "_trace": attr.label(default = "@rules_license//rules:trace_target"), }, provides = [TransitiveMetadataInfo], apply_to_generating_rules = True, ) def _write_metadata_info_impl(target, ctx): """Write transitive license info into a JSON file Args: target: The target of the aspect. ctx: The aspect evaluation context. Returns: OutputGroupInfo """ if not TransitiveMetadataInfo in target: return [OutputGroupInfo(licenses = depset())] info = target[TransitiveMetadataInfo] outs = [] # If the result doesn't contain licenses, we simply return the provider if not hasattr(info, "target_under_license"): return [OutputGroupInfo(licenses = depset())] # Write the output file for the target name = "%s_metadata_info.json" % ctx.label.name content = "[\n%s\n]\n" % ",\n".join(metadata_info_to_json(info)) out = ctx.actions.declare_file(name) ctx.actions.write( output = out, content = content, ) outs.append(out) if ctx.attr._trace[TraceInfo].trace: trace = ctx.actions.declare_file("%s_trace_info.json" % ctx.label.name) ctx.actions.write(output = trace, content = "\n".join(info.traces)) outs.append(trace) return [OutputGroupInfo(licenses = depset(outs))] gather_metadata_info_and_write = aspect( doc = """Collects TransitiveMetadataInfo providers and writes JSON representation to a file. Usage: bazel build //some:target \ --aspects=@rules_license//rules:gather_metadata_info.bzl%gather_metadata_info_and_write --output_groups=licenses """, implementation = _write_metadata_info_impl, attr_aspects = ["*"], attrs = { "_trace": attr.label(default = "@rules_license//rules:trace_target"), }, provides = [OutputGroupInfo], requires = [gather_metadata_info], apply_to_generating_rules = True, ) def write_metadata_info(ctx, deps, json_out): """Writes TransitiveMetadataInfo providers for a set of targets as JSON. TODO(aiuto): Document JSON schema. But it is under development, so the current best place to look is at tests/hello_licenses.golden. Usage: write_metadata_info must be called from a rule implementation, where the rule has run the gather_metadata_info aspect on its deps to collect the transitive closure of LicenseInfo providers into a LicenseInfo provider. foo = rule( implementation = _foo_impl, attrs = { "deps": attr.label_list(aspects = [gather_metadata_info]) } ) def _foo_impl(ctx): ... out = ctx.actions.declare_file("%s_licenses.json" % ctx.label.name) write_metadata_info(ctx, ctx.attr.deps, metadata_file) Args: ctx: context of the caller deps: a list of deps which should have TransitiveMetadataInfo providers. This requires that you have run the gather_metadata_info aspect over them json_out: output handle to write the JSON info """ licenses = [] for dep in deps: if TransitiveMetadataInfo in dep: licenses.extend(metadata_info_to_json(dep[TransitiveMetadataInfo])) ctx.actions.write( output = json_out, content = "[\n%s\n]\n" % ",\n".join(licenses), ) def metadata_info_to_json(metadata_info): """Render a single LicenseInfo provider to JSON Args: metadata_info: A LicenseInfo. Returns: [(str)] list of LicenseInfo values rendered as JSON. """ main_template = """ {{ "top_level_target": "{top_level_target}", "dependencies": [{dependencies} ], "licenses": [{licenses} ], "packages": [{packages} ]\n }}""" dep_template = """ {{ "target_under_license": "{target_under_license}", "licenses": [ {licenses} ] }}""" license_template = """ {{ "label": "{label}", "bazel_package": "{bazel_package}", "license_kinds": [{kinds} ], "copyright_notice": "{copyright_notice}", "package_name": "{package_name}", "package_url": "{package_url}", "package_version": "{package_version}", "license_text": "{license_text}", "used_by": [ {used_by} ] }}""" kind_template = """ {{ "target": "{kind_path}", "name": "{kind_name}", "conditions": {kind_conditions} }}""" package_info_template = """ {{ "target": "{label}", "bazel_package": "{bazel_package}", "package_name": "{package_name}", "package_url": "{package_url}", "package_version": "{package_version}" }}""" # Build reverse map of license to user used_by = {} for dep in metadata_info.deps.to_list(): # Undo the concatenation applied when stored in the provider. dep_licenses = dep.licenses.split(",") for license in dep_licenses: if license not in used_by: used_by[license] = [] used_by[license].append(_strip_null_repo(dep.target_under_license)) all_licenses = [] for license in sorted(metadata_info.licenses.to_list(), key = lambda x: x.label): kinds = [] for kind in sorted(license.license_kinds, key = lambda x: x.name): kinds.append(kind_template.format( kind_name = kind.name, kind_path = kind.label, kind_conditions = kind.conditions, )) if license.license_text: # Special handling for synthetic LicenseInfo text_path = (license.license_text.package + "/" + license.license_text.name if type(license.license_text) == "Label" else license.license_text.path) all_licenses.append(license_template.format( copyright_notice = license.copyright_notice, kinds = ",".join(kinds), license_text = text_path, package_name = license.package_name, package_url = license.package_url, package_version = license.package_version, label = _strip_null_repo(license.label), bazel_package = _bazel_package(license.label), used_by = ",\n ".join(sorted(['"%s"' % x for x in used_by[str(license.label)]])), )) all_deps = [] for dep in sorted(metadata_info.deps.to_list(), key = lambda x: x.target_under_license): # Undo the concatenation applied when stored in the provider. dep_licenses = dep.licenses.split(",") all_deps.append(dep_template.format( target_under_license = _strip_null_repo(dep.target_under_license), licenses = ",\n ".join(sorted(['"%s"' % _strip_null_repo(x) for x in dep_licenses])), )) all_packages = [] # We would use this if we had distinct depsets for every provider type. #for package in sorted(metadata_info.package_info.to_list(), key = lambda x: x.label): # all_packages.append(package_info_template.format( # label = _strip_null_repo(package.label), # package_name = package.package_name, # package_url = package.package_url, # package_version = package.package_version, # )) for mi in sorted(metadata_info.other_metadata.to_list(), key = lambda x: x.label): # Maybe use a map of provider class to formatter. A generic dict->json function # in starlark would help # This format is for using distinct providers. I like the compile time safety. if mi.type == "package_info": all_packages.append(package_info_template.format( label = _strip_null_repo(mi.label), bazel_package = _bazel_package(mi.label), package_name = mi.package_name, package_url = mi.package_url, package_version = mi.package_version, )) # experimental: Support the ExperimentalMetadataInfo bag of data # WARNING: Do not depend on this. It will change without notice. if mi.type == "package_info_alt": all_packages.append(package_info_template.format( label = _strip_null_repo(mi.label), bazel_package = _bazel_package(mi.label), # data is just a bag, so we need to use get() or "" package_name = mi.data.get("package_name") or "", package_url = mi.data.get("package_url") or "", package_version = mi.data.get("package_version") or "", )) return [main_template.format( top_level_target = _strip_null_repo(metadata_info.target_under_license), dependencies = ",".join(all_deps), licenses = ",".join(all_licenses), packages = ",".join(all_packages), )] rules_license-0.0.7/rules_gathering/gathering_providers.bzl000066400000000000000000000043121444314666600243300ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Providers for transitively gathering all license and package_info targets. Warning: This is private to the aspect that walks the tree. The API is subject to change at any release. """ LicensedTargetInfo = provider( doc = """Lists the licenses directly used by a single target.""", fields = { "target_under_license": "Label: The target label", "licenses": "list(label of a license rule)", }, ) def licenses_info(): return provider( doc = """The transitive set of licenses used by a target.""", fields = { "target_under_license": "Label: The top level target label.", "deps": "depset(LicensedTargetInfo): The transitive list of dependencies that have licenses.", "licenses": "depset(LicenseInfo)", "traces": "list(string) - diagnostic for tracing a dependency relationship to a target.", }, ) # This provider is used by the aspect that is used by manifest() rules. TransitiveLicensesInfo = licenses_info() TransitiveMetadataInfo = provider( doc = """The transitive set of licenses used by a target.""", fields = { "top_level_target": "Label: The top level target label we are examining.", "other_metadata": "depset(ExperimentalMetatdataInfo)", "licenses": "depset(LicenseInfo)", "package_info": "depset(PackageInfo)", "target_under_license": "Label: A target which will be associated with some licenses.", "deps": "depset(LicensedTargetInfo): The transitive list of dependencies that have licenses.", "traces": "list(string) - diagnostic for tracing a dependency relationship to a target.", }, ) rules_license-0.0.7/rules_gathering/generate_sbom.bzl000066400000000000000000000106421444314666600231000ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """SBOM generation""" load( "@rules_license//rules_gathering:gather_metadata.bzl", "gather_metadata_info", "gather_metadata_info_and_write", "write_metadata_info", ) load( "@rules_license//rules_gathering:gathering_providers.bzl", "TransitiveLicensesInfo", ) # This rule is proof of concept, and may not represent the final # form of a rule for compliance validation. def _generate_sbom_impl(ctx): # Gather all licenses and write information to one place licenses_file = ctx.actions.declare_file("_%s_licenses_info.json" % ctx.label.name) write_metadata_info(ctx, ctx.attr.deps, licenses_file) # Now turn the big blob of data into something consumable. inputs = [licenses_file] outputs = [ctx.outputs.out] args = ctx.actions.args() args.add("--licenses_info", licenses_file.path) args.add("--out", ctx.outputs.out.path) ctx.actions.run( mnemonic = "CreateSBOM", progress_message = "Creating SBOM for %s" % ctx.label, inputs = inputs, outputs = outputs, executable = ctx.executable._sbom_generator, arguments = [args], ) outputs.append(licenses_file) # also make the json file available. return [DefaultInfo(files = depset(outputs))] _generate_sbom = rule( implementation = _generate_sbom_impl, attrs = { "deps": attr.label_list( aspects = [gather_metadata_info], ), "out": attr.output(mandatory = True), "_sbom_generator": attr.label( default = Label("@rules_license//tools:write_sbom"), executable = True, allow_files = True, cfg = "exec", ), }, ) def generate_sbom(**kwargs): _generate_sbom(**kwargs) def _manifest_impl(ctx): # Gather all licenses and make it available as deps for downstream rules # Additionally write the list of license filenames to a file that can # also be used as an input to downstream rules. licenses_file = ctx.actions.declare_file(ctx.attr.out.name) mappings = get_licenses_mapping(ctx.attr.deps, ctx.attr.warn_on_legacy_licenses) ctx.actions.write( output = licenses_file, content = "\n".join([",".join([f.path, p]) for (f, p) in mappings.items()]), ) return [DefaultInfo(files = depset(mappings.keys()))] _manifest = rule( implementation = _manifest_impl, doc = """Internal tmplementation method for manifest().""", attrs = { "deps": attr.label_list( doc = """List of targets to collect license files for.""", aspects = [gather_metadata_info], ), "out": attr.output( doc = """Output file.""", mandatory = True, ), "warn_on_legacy_licenses": attr.bool(default = False), }, ) def manifest(name, deps, out = None, **kwargs): if not out: out = name + ".manifest" _manifest(name = name, deps = deps, out = out, **kwargs) def get_licenses_mapping(deps, warn = False): """Creates list of entries representing all licenses for the deps. Args: deps: a list of deps which should have TransitiveLicensesInfo providers. This requires that you have run the gather_licenses_info aspect over them warn: boolean, if true, display output about legacy targets that need update Returns: {File:package_name} """ tls = [] for dep in deps: lds = dep[TransitiveLicensesInfo].licenses tls.append(lds) ds = depset(transitive = tls) # Ignore any legacy licenses that may be in the report mappings = {} for lic in ds.to_list(): if type(lic.license_text) == "File": mappings[lic.license_text] = lic.package_name elif warn: # buildifier: disable=print print("Legacy license %s not included, rule needs updating" % lic.license_text) return mappings rules_license-0.0.7/rules_gathering/trace.bzl000066400000000000000000000021461444314666600213640ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Rules and macros for collecting package metdata providers.""" TraceInfo = provider( doc = """Provides a target (as a string) to assist in debugging dependency issues.""", fields = { "trace": "String: a target to trace dependency edges to.", }, ) def _trace_impl(ctx): return TraceInfo(trace = ctx.build_setting_value) trace = rule( doc = """Used to allow the specification of a target to trace while collecting license dependencies.""", implementation = _trace_impl, build_setting = config.string(flag = True), ) rules_license-0.0.7/sample_reports/000077500000000000000000000000001444314666600174275ustar00rootroot00000000000000rules_license-0.0.7/sample_reports/BUILD000066400000000000000000000021541444314666600202130ustar00rootroot00000000000000# BUILD file defining reference implementations for reporting tools # # Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Rules for making license declarations.""" package( default_applicable_licenses = ["//:license"], default_visibility = ["//visibility:public"], ) licenses(["notice"]) filegroup( name = "standard_package", srcs = glob(["**"]), ) # Do not create a bzl_library(). That would create a dependency loop back # to bazel-skylib. We export the .bzl files to the documentation maker. exports_files( glob([ "*.bzl", ]), visibility = ["//doc_build:__pkg__"], ) rules_license-0.0.7/sample_reports/licenses_used.bzl000066400000000000000000000042111444314666600227630ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """License compliance checking.""" load( "@rules_license//rules:gather_licenses_info.bzl", "gather_licenses_info", "write_licenses_info", ) def _licenses_used_impl(ctx): # Gather all licenses and make it available as JSON write_licenses_info(ctx, ctx.attr.deps, ctx.outputs.out) return [DefaultInfo(files = depset([ctx.outputs.out]))] _licenses_used = rule( implementation = _licenses_used_impl, doc = """Internal tmplementation method for licenses_used().""", attrs = { "deps": attr.label_list( doc = """List of targets to collect LicenseInfo for.""", aspects = [gather_licenses_info], ), "out": attr.output( doc = """Output file.""", mandatory = True, ), }, ) def licenses_used(name, deps, out = None, **kwargs): """Collects LicensedInfo providers for a set of targets and writes as JSON. The output is a single JSON array, with an entry for each license used. See gather_licenses_info.bzl:write_licenses_info() for a description of the schema. Args: name: The target. deps: A list of targets to get LicenseInfo for. The output is the union of the result, not a list of information for each dependency. out: The output file name. Default: .json. **kwargs: Other args Usage: licenses_used( name = "license_info", deps = [":my_app"], out = "license_info.json", ) """ if not out: out = name + ".json" _licenses_used(name = name, deps = deps, out = out, **kwargs) rules_license-0.0.7/tests/000077500000000000000000000000001444314666600155325ustar00rootroot00000000000000rules_license-0.0.7/tests/BUILD000066400000000000000000000070021444314666600163130ustar00rootroot00000000000000# Test cases for license rules. load("@rules_license//rules:compliance.bzl", "check_license") load("@rules_license//rules:license.bzl", "license") load("@rules_license//rules:license_kind.bzl", "license_kind") load("@rules_license//sample_reports:licenses_used.bzl", "licenses_used") package( default_applicable_licenses = [":license"], default_visibility = [ "//examples:__subpackages__", "//tests:__subpackages__", ], ) # license_kind rules generally appear in a central location per workspace. They # are intermingled with normal target build rules license_kind( name = "generic_notice_license", conditions = [ "notice", ], ) license_kind( name = "generic_restricted_license", conditions = [ "restricted", ], ) # The default license for an entire package is typically named "license". license( name = "license", package_name = "A test case package", # Note the UTF-8 encoded copyright symbol. copyright_notice = "Copyright © 2019 Uncle Toasty", license_kinds = [":generic_notice_license"], # Note. This need not be precise. If a downloader creates the license # clause for you, then it should use the absolute download URL. package_url = "http://github.com/bazelbuild/rules_license", package_version = "0.0.4", ) license( name = "license_for_extra_feature", package_name = "A test case package", license_kinds = [":generic_restricted_license"], license_text = "LICENSE.extra", ) cc_binary( name = "hello", srcs = ["hello.cc"], deps = [ ":c_bar", ], ) cc_library( name = "c_bar", srcs = [ "bar.cc", ], applicable_licenses = [ ":license", ":license_for_extra_feature", ], deps = [ "@rules_license//tests/legacy:another_library_with_legacy_license_clause", "@rules_license//tests/legacy:library_with_legacy_license_clause", ], ) java_binary( name = "hello_java", srcs = ["Hello.java"], # Add an addition license to this target, beyond what my deps have. applicable_licenses = [ ":license_for_extra_feature", ], javacopts = ["-Xep:DefaultPackage:OFF"], main_class = "Hello", deps = [ ":j_bar", ], ) java_library( name = "j_bar", srcs = ["Bar.java"], javacopts = ["-Xep:DefaultPackage:OFF"], ) check_license( name = "check_cc_app", check_conditions = False, copyright_notices = "hello_cc_copyrights.txt", license_texts = "hello_cc_licenses.txt", report = "hello_cc_report", deps = [ ":hello", ], ) licenses_used( name = "hello_licenses", out = "hello_licenses.json", deps = [":hello"], ) py_test( name = "hello_licenses_test", srcs = ["hello_licenses_test.py"], data = [ ":hello_licenses.json", ":hello_cc_copyrights.txt", ], python_version = "PY3", deps = [ ":license_test_utils", ], ) py_library( name = "license_test_utils", srcs = ["license_test_utils.py"], srcs_version = "PY3", ) check_license( name = "check_java_app", check_conditions = False, copyright_notices = "hello_java_copyrights.txt", license_texts = "hello_java_licenses.txt", report = "hello_java_report", deps = [ ":hello_java", ], ) license( name = "license_with_generated_text", license_text = ":created_license", license_kinds = [":generic_notice_license"], ) genrule( name = "created_license", outs = ["something.text"], cmd = "echo hello >$@", ) rules_license-0.0.7/tests/Bar.java000066400000000000000000000013111444314666600170750ustar00rootroot00000000000000// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /** * A java class. */ package rules_license.tests; final class Bar { static final int PI = 3; private Bar() { } } rules_license-0.0.7/tests/Hello.java000066400000000000000000000014121444314666600174360ustar00rootroot00000000000000// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /** * A java main. */ package rules_license.tests; final class Hello { private Hello() { } int whatIsPi() { return Bar.PI; } public static void main(String[] args) { } } rules_license-0.0.7/tests/LICENSE000066400000000000000000000002341444314666600165360ustar00rootroot00000000000000Copyright © 2019 Uncle Toasty Example of a notice style license. You may use this software in any way as long as you include the copyright notice above. rules_license-0.0.7/tests/LICENSE.extra000066400000000000000000000003441444314666600176620ustar00rootroot00000000000000Copyright (c) 2020 The authors of this software A license for an extra feature to a package. For example, you might have most of the package with a notice license, but an additional feature is added under a restricted license. rules_license-0.0.7/tests/apps/000077500000000000000000000000001444314666600164755ustar00rootroot00000000000000rules_license-0.0.7/tests/apps/BUILD000066400000000000000000000040471444314666600172640ustar00rootroot00000000000000# Test cases for license rules: Sample app load("@rules_license//sample_reports:licenses_used.bzl", "licenses_used") load("@rules_python//python:defs.bzl", "py_test") package(default_visibility = ["//examples:__subpackages__"]) # Note that the app explicitly depends only on a library and some legacy # style licensed code. cc_binary( name = "an_app", srcs = ["an_app.cc"], deps = [ ":level4", # "@rules_license//rules/tests/legacy:another_library_with_legacy_license_clause", # "@rules_license//rules/tests/legacy:library_with_legacy_license_clause", ], ) # pointless chain of libraries to show transitive rule gathering, culminating # in a diamond dependency on a library under license. # Note that the lowest level depends on some third party code [ genrule( name = "level_%d_src" % level, outs = ["level_%d.cc" % level], # Note to reviewers: This should use string format, but format # is broken when cmd = """cat >$@ < extern void {lower}(); void lib_level_{level}() {{ std::cout << "This is level {level}" << std::endl; {lower}(); }} END """.format( level = level, lower = "lib_level_%d" % (level - 1) if level > 0 else "new_lib_func", ), ) for level in range(5) ] [ cc_library( name = "level%d" % level, srcs = [":level_%d.cc" % level], deps = [ (":level%d" % (level - 1) if level > 0 else "@rules_license//tests/thrdparty:new_style_lib"), ], ) for level in range(5) ] licenses_used( name = "an_app_licenses", out = "an_app_licenses.json", deps = [":an_app"], ) # Examining the golden file shows that we depend on both kinds of license. py_test( name = "an_app_licenses_test", srcs = ["an_app_licenses_test.py"], data = [":an_app_licenses.json"], python_version = "PY3", deps = [ "@rules_license//tests:license_test_utils", ], ) rules_license-0.0.7/tests/apps/an_app.cc000066400000000000000000000014251444314666600202440ustar00rootroot00000000000000// Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include extern const char* server_message; extern void lib_level_4(); int main(int argc, char* argv[]) { std::cout << "main" << std::endl; lib_level_4(); return 0; } rules_license-0.0.7/tests/apps/an_app_licenses_test.py000066400000000000000000000025551444314666600232400ustar00rootroot00000000000000# Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import unittest from tests import license_test_utils class AnAppLicensesTest(unittest.TestCase): def test_has_expected_licenses(self): package_base = license_test_utils.LICENSE_PACKAGE_BASE licenses_info = license_test_utils.load_licenses_info( os.path.join(os.path.dirname(__file__), "an_app_licenses.json")) licenses_info = license_test_utils.filter_dependencies( licenses_info, target_filter=lambda targ: targ.startswith(package_base), licenses_filter=lambda lic: lic.startswith(package_base)) expected = { "/tests/thrdparty:new_style_lib": [ "/tests/thrdparty:license", ], } license_test_utils.check_licenses_of_dependencies( self, licenses_info, expected) if __name__ == "__main__": unittest.main() rules_license-0.0.7/tests/bar.cc000066400000000000000000000011461444314666600166070ustar00rootroot00000000000000// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. int bar() { return 42; } rules_license-0.0.7/tests/hello.cc000066400000000000000000000012721444314666600171460ustar00rootroot00000000000000// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include int main(int argc, char* argv[]) { std::cout << "Hello foo." << std::endl; return 0; } rules_license-0.0.7/tests/hello_licenses_test.py000066400000000000000000000023041444314666600221320ustar00rootroot00000000000000"""Tests for google3.tools.build_defs.license.tests.hello_licenses.""" import codecs import os import unittest from tests import license_test_utils class HelloLicensesTest(unittest.TestCase): def test_has_expected_licenses(self): licenses_info = license_test_utils.load_licenses_info( os.path.join(os.path.dirname(__file__), "hello_licenses.json")) expected = { "/tests:hello": [ "/tests:license", ], "/tests:c_bar": [ "/tests:license", "/tests:license_for_extra_feature", ], } license_test_utils.check_licenses_of_dependencies( self, licenses_info, expected) def test_has_expected_copyrights(self): copyrights_file = os.path.join(os.path.dirname(__file__), "hello_cc_copyrights.txt") with codecs.open(copyrights_file, encoding="utf-8") as inp: copyrights = inp.read().split('\n') self.assertIn( "package(A test case package/0.0.4), copyright(Copyright © 2019 Uncle Toasty)", copyrights) self.assertIn( "package(A test case package), copyright()", copyrights) if __name__ == "__main__": unittest.main() rules_license-0.0.7/tests/legacy/000077500000000000000000000000001444314666600167765ustar00rootroot00000000000000rules_license-0.0.7/tests/legacy/BUILD000066400000000000000000000005241444314666600175610ustar00rootroot00000000000000# Example of an unmigrated package. package(default_visibility = [ "//tests:__subpackages__", ]) licenses(["unencumbered"]) cc_library( name = "library_with_legacy_license_clause", srcs = ["file_under_notice.cc"], ) cc_library( name = "another_library_with_legacy_license_clause", srcs = ["file_under_notice.cc"], ) rules_license-0.0.7/tests/legacy/file_under_notice.cc000066400000000000000000000011431444314666600227610ustar00rootroot00000000000000// Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. int file_under_notice = 1; rules_license-0.0.7/tests/license_test_utils.py000066400000000000000000000057551444314666600220210ustar00rootroot00000000000000"""Utilities for writing tests of license rules.""" import codecs import json # This is extracted out to make it easier to keep test equivalence between # the OSS version and Google. LICENSE_PACKAGE_BASE = "/" def load_licenses_info(info_path): """Loads the licenses_info() JSON format.""" with codecs.open(info_path, encoding="utf-8") as licenses_file: return json.loads(licenses_file.read()) def filter_dependencies(licenses_info, target_filter=None, licenses_filter=None): """Filters licenses_info to only include dependencies of interest. Args: licenses_info: (dict) licenses info. target_filter: (function): function which returns true if we should include the target. licenses_filter: (function): function which returns true if we should include the license. Returns: (dict) a valid licenses_info dict. """ top_target = licenses_info[0] new_top_target = dict(top_target) new_deps = [] for dep in top_target["dependencies"]: target_name = dep["target_under_license"] if target_filter and not target_filter(target_name): continue licenses = dep["licenses"] if licenses_filter: licenses = [lic for lic in licenses if licenses_filter(lic)] new_deps.append({ "target_under_license": target_name, "licenses": licenses}) new_top_target["dependencies"] = new_deps return [new_top_target] def check_licenses_of_dependencies(test_case, licenses_info, expected, path_prefix=LICENSE_PACKAGE_BASE): """Checks that licenses_info contains an expected set of licenses. Args: test_case: (TestCase) the test. licenses_info: (dict) licenses info. expected: (dict) map of target name suffixes to the licenses they are under. path_prefix: (str) prefix to prepend to targets and licenses in expected. This turns the relative target names to absolute ones. """ # Turn the list of deps into a dict by target for easier comparison. deps_to_licenses = { x["target_under_license"].lstrip("@"): set(l.strip("@") for l in x["licenses"]) for x in licenses_info[0]["dependencies"]} target_names = ",".join(deps_to_licenses.keys()) # This is n**2, but N is typically < 3 or we are doing this wrong. for want_target, want_licenses in expected.items(): found_target = False for got_target, got_licenses in deps_to_licenses.items(): if got_target.endswith(want_target): found_target = True test_case.assertEqual(len(want_licenses), len(got_licenses)) found_license = False for want_l in want_licenses: for got_l in got_licenses: if got_l.endswith(want_l): found_license = True break test_case.assertTrue( found_license, msg="license (%s) not a suffix in %s" % (want_l, got_licenses)) break test_case.assertTrue( found_target, msg="target (%s) not a suffix in [%s]" % (want_target, target_names)) rules_license-0.0.7/tests/thrdparty/000077500000000000000000000000001444314666600175535ustar00rootroot00000000000000rules_license-0.0.7/tests/thrdparty/BUILD000066400000000000000000000011141444314666600203320ustar00rootroot00000000000000# A sample library using new license rules. load("@rules_license//rules:license.bzl", "license") package( default_applicable_licenses = [":license"], default_visibility = [ "//examples:__subpackages__", "//tests:__subpackages__", ], ) # The default license for an entire package is typically named "license". license( name = "license", package_name = "migrated package", license_kinds = ["//licenses/generic:restricted"], license_text = "LICENSE", ) cc_library( name = "new_style_lib", srcs = [ "new_style_lib.cc", ], ) rules_license-0.0.7/tests/thrdparty/LICENSE000066400000000000000000000000351444314666600205560ustar00rootroot00000000000000I am restricted in some way. rules_license-0.0.7/tests/thrdparty/new_style_lib.cc000066400000000000000000000013031444314666600227160ustar00rootroot00000000000000// Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include void new_lib_func() { std::cout << "This is restricted code" << std::endl; } rules_license-0.0.7/tools/000077500000000000000000000000001444314666600155305ustar00rootroot00000000000000rules_license-0.0.7/tools/BUILD000066400000000000000000000024121444314666600163110ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """License declaration and compliance checking tools.""" load("@rules_python//python:defs.bzl", "py_binary") package( default_applicable_licenses = ["//:license", "//:package_info"], default_visibility = ["//visibility:public"], ) licenses(["notice"]) filegroup( name = "standard_package", srcs = glob(["**"]), visibility = ["//distro:__pkg__"], ) exports_files(["diff_test.sh"]) py_binary( name = "checker_demo", srcs = ["checker_demo.py"], python_version = "PY3", visibility = ["//visibility:public"], ) py_binary( name = "write_sbom", srcs = ["write_sbom.py"], python_version = "PY3", visibility = ["//visibility:public"], ) rules_license-0.0.7/tools/checker_demo.py000066400000000000000000000113161444314666600205140ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Proof of concept license checker. This is only a demonstration. It will be replaced with other tools. """ import argparse import codecs import json # Conditions allowed for all applications _ALWAYS_ALLOWED_CONDITIONS = frozenset(['notice', 'permissive', 'unencumbered']) def _load_license_data(licenses_info): with codecs.open(licenses_info, encoding='utf-8') as licenses_file: return json.loads(licenses_file.read()) def unique_licenses(licenses): for target in licenses: for lic in target.get('licenses') or []: yield lic def _do_report(out, licenses): """Produce a report showing the set of licenses being used. Args: out: file object to write to licenses: list of LicenseInfo objects Returns: 0 for no restricted licenses. """ for target in unique_licenses(licenses): for lic in target.get('licenses') or []: print("lic:", lic) rule = lic['rule'] for kind in lic['license_kinds']: out.write('= %s\n kind: %s\n' % (rule, kind['target'])) out.write(' conditions: %s\n' % kind['conditions']) def _check_conditions(out, licenses, allowed_conditions): """Check that the application does not use any disallowed licenses. Args: out: file object to write to licenses: list of LicenseInfo objects allowed_conditions: list of allowed condition names Returns: 0 for no licenses from outside allowed_conditions. """ err = 0 for lic in licenses: # using strange name lic because license is built-in rule = lic['rule'] for kind in lic['license_kinds']: disallowed = [] for condition in kind['conditions']: if condition not in allowed_conditions: disallowed.append(condition) if disallowed: out.write('ERROR: %s\n' % rule) out.write(' kind: %s\n' % kind['target']) out.write(' conditions: %s\n' % kind['conditions']) out.write(' disallowed condition: %s\n' % ','.join(disallowed)) err += 1 return err def _do_copyright_notices(out, licenses): for l in licenses: name = l.get('package_name') or '' if l.get('package_version'): name = name + "/" + l['package_version'] # IGNORE_COPYRIGHT: Not a copyright notice. It is a variable holding one. out.write('package(%s), copyright(%s)\n' % (name, l['copyright_notice'])) def _do_licenses(out, licenses): for lic in unique_licenses(licenses): path = lic['license_text'] with codecs.open(path, encoding='utf-8') as license_file: out.write('= %s\n' % path) out.write(license_file.read()) def main(): parser = argparse.ArgumentParser( description='Demonstraton license compliance checker') parser.add_argument('--licenses_info', help='path to JSON file containing all license data') parser.add_argument('--report', default='report', help='Summary report') parser.add_argument('--copyright_notices', help='output file of all copyright notices') parser.add_argument('--license_texts', help='output file of all license files') parser.add_argument('--check_conditions', action='store_true', help='check that the dep only includes allowed license conditions') args = parser.parse_args() license_data = _load_license_data(args.licenses_info) target = license_data[0] # we assume only one target for the demo top_level_target = target['top_level_target'] dependencies = target['dependencies'] licenses = target['licenses'] err = 0 with codecs.open(args.report, mode='w', encoding='utf-8') as rpt: _do_report(rpt, licenses) if args.check_conditions: # TODO(aiuto): Read conditions from a file of allowed conditions for # a specified application deployment environment. err = _check_conditions(rpt, licenses, _ALWAYS_ALLOWED_CONDITIONS) if args.copyright_notices: with codecs.open( args.copyright_notices, mode='w', encoding='utf-8') as out: _do_copyright_notices(out, licenses) if args.license_texts: with codecs.open(args.license_texts, mode='w', encoding='utf-8') as out: _do_licenses(out, licenses) return err if __name__ == '__main__': main() rules_license-0.0.7/tools/diff_test.sh000077500000000000000000000017731444314666600200460ustar00rootroot00000000000000#!/bin/bash # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Diff two files and PASS if they are equal, FAIL otherwise. # Usage: # diff_test.sh path_to_expected path_to_got # Find input files declare -r EXPECTED="$1" declare -r GOT="$2" diff_out=$(mktemp /tmp/diff_test.XXXXXXXXX) diff -cB "$EXPECTED" "$GOT" >"$diff_out" err=0 if [[ -s "$diff_out" ]] ; then cat "$diff_out" err=1 echo 'To update:' echo ' cp bazel-bin/'"$GOT" "$EXPECTED" echo FAIL else echo PASS fi exit $err rules_license-0.0.7/tools/test_helpers.bzl000066400000000000000000000053221444314666600207440ustar00rootroot00000000000000# Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Compare rule output to a golden version.""" def golden_test( name, golden, subject): """Check that output from a rule matches the expected output. Args: name: test name golden: expected content of subect subject: build target """ native.sh_test( name = name, size = "medium", srcs = ["@rules_license//tools:diff_test.sh"], args = [ "$(location %s)" % golden, "$(location %s)" % subject, ], data = [ subject, golden, ], ) def golden_cmd_test( name, cmd, golden, # Required toolchains = [], tools = None, exec_tools = None, srcs = [], # Optional **kwargs): # Rest """Compares cmd output to golden output, passes if they are identical. Args: name: Name of the build rule. cmd: The command to run to generate output. golden: The golden file to be compared. toolchains: List of toolchains needed to run the command, passed to genrule. tools: List of tools needed to run the command, passed to genrule. exec_tools: List of tools needed to run the command, passed to genrule. srcs: List of sources needed as input to the command, passed to genrule. **kwargs: Any additional parameters for the generated golden_test. """ actual = name + ".output" # There are some cases where tools are provided and exec_tools are provided. # Specifying both in the same genrule, confuses the host vs exec rules, # which prevents python3 from execution. if tools and exec_tools: fail("Only set one: tools or exec_tools. " + "Setting both confuses python execution mode (host vs exec).") native.genrule( name = name + "_output", srcs = srcs, outs = [actual], cmd = cmd + " > '$@'", # Redirect to collect output toolchains = toolchains, tools = tools, exec_tools = exec_tools, testonly = True, ) golden_test( name = name, subject = actual, golden = golden, **kwargs ) rules_license-0.0.7/tools/write_sbom.py000066400000000000000000000067751444314666600202730ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Proof of concept license checker. This is only a demonstration. It will be replaced with other tools. """ import argparse import codecs import datetime import json import os TOOL = 'https//github.com/bazelbuild/rules_license/tools:write_sbom' def _load_package_data(package_info): with codecs.open(package_info, encoding='utf-8') as inp: return json.loads(inp.read()) def _write_sbom_header(out, package): header = [ 'SPDXVersion: SPDX-2.2', 'DataLicense: CC0-1.0', 'SPDXID: SPDXRef-DOCUMENT', 'DocumentName: %s' % package, # TBD # 'DocumentNamespace: https://swinslow.net/spdx-examples/example1/hello-v3 'Creator: Person: %s' % os.getlogin(), 'Creator: Tool: %s' % TOOL, datetime.datetime.utcnow().strftime('Created: %Y-%m-%d-%H:%M:%SZ'), '', '##### Package: %s' % package, ] out.write('\n'.join(header)) def _write_sbom(out, packages): """Produce a basic SBOM Args: out: file object to write to packages: package metadata. A big blob of JSON. """ for p in packages: name = p.get('package_name') or '' out.write('\n') out.write('SPDXID: "%s"\n' % name) out.write(' name: "%s"\n' % name) if p.get('package_version'): out.write(' versionInfo: "%s"\n' % p['package_version']) # IGNORE_COPYRIGHT: Not a copyright notice. It is a variable holding one. cn = p.get('copyright_notice') if cn: out.write(' copyrightText: "%s"\n' % cn) kinds = p.get('license_kinds') if kinds: out.write(' licenseDeclared: "%s"\n' % ','.join([k['name'] for k in kinds])) url = p.get('package_url') if url: out.write(' downloadLocation: %s\n' % url) def main(): parser = argparse.ArgumentParser( description='Demonstraton license compliance checker') parser.add_argument('--licenses_info', help='path to JSON file containing all license data') parser.add_argument('--out', default='sbom.out', help='SBOM output') args = parser.parse_args() license_data = _load_package_data(args.licenses_info) target = license_data[0] # we assume only one target for the demo top_level_target = target['top_level_target'] dependencies = target['dependencies'] # It's not really packages, but this is close proxy for now licenses = target['licenses'] package_infos = target['packages'] # These are similar dicts, so merge them by package. This is not # strictly true, as different licenese can appear in the same # package, but it is good enough for demonstrating the sbom. all = {x['bazel_package']: x for x in licenses} for pi in package_infos: p = all.get(pi['bazel_package']) if p: p.update(pi) else: all[pi['bazel_package']] = pi err = 0 with codecs.open(args.out, mode='w', encoding='utf-8') as out: _write_sbom_header(out, package=top_level_target) _write_sbom(out, all.values()) return err if __name__ == '__main__': main() rules_license-0.0.7/version.bzl000066400000000000000000000012211444314666600165620ustar00rootroot00000000000000# Copyright 2022 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """The version of rules_license.""" version = "0.0.7"