diff --git a/.github/workflows/golang.yml b/.github/workflows/golang.yml index 825ab79..683eb5e 100644 --- a/.github/workflows/golang.yml +++ b/.github/workflows/golang.yml @@ -78,3 +78,19 @@ jobs: with: go-version: ${{ env.GOLANG_VERSION }} - run: make build + check-third-party-notices: + name: Check third-party notices + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + name: Checkout code + - name: Get Golang version + id: vars + run: | + GOLANG_VERSION=$( grep "GOLANG_VERSION ?=" versions.mk ) + echo "GOLANG_VERSION=${GOLANG_VERSION##GOLANG_VERSION ?= }" >> $GITHUB_ENV + - name: Install Go + uses: actions/setup-go@v6 + with: + go-version: ${{ env.GOLANG_VERSION }} + - run: make check-third-party-notices diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ae3c172 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/Makefile b/Makefile index 77bcdd3..ffe1784 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ include $(CURDIR)/versions.mk DOCKERFILE_DEVEL := "images/devel/Dockerfile" K8S_TEST_INFRA := "https://github.com/NVIDIA/k8s-test-infra.git" -TARGETS := binary build all check fmt assert-fmt generate test coverage golangci-lint +TARGETS := binary build all check fmt assert-fmt generate test coverage golangci-lint third-party-notices check-third-party-notices DOCKER_TARGETS := $(patsubst %, docker-%, $(TARGETS)) .PHONY: $(TARGETS) $(DOCKER_TARGETS) @@ -70,6 +70,21 @@ vendor: check-vendor: vendor git diff --quiet HEAD -- go.mod go.sum vendor +GO_LICENSES = $(CURDIR)/bin/go-licenses + +$(GO_LICENSES): versions.mk + GOBIN=$(CURDIR)/bin GOFLAGS= go install github.com/google/go-licenses/v2@$(GO_LICENSES_VERSION) + +third-party-notices: $(GO_LICENSES) + @bash hack/generate-third-party-notices.sh + +check-third-party-notices: third-party-notices + @echo "- Checking if THIRD_PARTY_NOTICES.md is up to date..." + @git ls-files --error-unmatch THIRD_PARTY_NOTICES.md >/dev/null 2>&1 \ + || { echo "ERROR: THIRD_PARTY_NOTICES.md is not tracked. Run 'make third-party-notices' and commit the result."; exit 1; } + @git diff --exit-code -- THIRD_PARTY_NOTICES.md \ + || { echo "ERROR: THIRD_PARTY_NOTICES.md is stale. Run 'make third-party-notices' and commit the change."; exit 1; } + build-image: $(DOCKERFILE_DEVEL) $(DOCKER) build \ --progress=plain \ diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md new file mode 100644 index 0000000..b6861ef --- /dev/null +++ b/THIRD_PARTY_NOTICES.md @@ -0,0 +1,500 @@ +# Third-Party Notices + +NVIDIA go-gpuallocator + +This file lists the third-party Go modules that `go-gpuallocator` links into the +packages a consumer imports, along with the verbatim text of each dependency's +license. `go-gpuallocator` is a library: the module itself is the unit of +distribution, so this covers every package in it. + +Go standard library packages are excluded; they are covered by the license of +the Go distribution itself. Dependencies reached only from `_test.go` files are +excluded; they are vendored for testing but a consumer does not link them. + +## Dependency Index + +| Package | License | Module | +|---------|---------|--------| +| `github.com/NVIDIA/go-nvlib/pkg/nvlib/device` | Apache-2.0 | `github.com/NVIDIA/go-nvlib@v0.10.0` | +| `github.com/NVIDIA/go-nvml/pkg` | Apache-2.0 | `github.com/NVIDIA/go-nvml@v0.13.0-1` | +| `github.com/google/uuid` | BSD-3-Clause | `github.com/google/uuid@v1.6.0` | + +## License Texts + +### github.com/NVIDIA/go-nvlib/pkg/nvlib/device + +* License: Apache-2.0 +* Module: github.com/NVIDIA/go-nvlib@v0.10.0 + +#### LICENSE + +```text + + 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. + +``` + +#### NOTICE + +```text +The file pkg/pciids/default_pci.ids is distributed under the 3-clause BSD License. +Maintained by Albert Pool, Martin Mares, and other volunteers from +the PCI ID Project at https://pci-ids.ucw.cz/. + + +``` + + +### github.com/NVIDIA/go-nvml/pkg + +* License: Apache-2.0 +* Module: github.com/NVIDIA/go-nvml@v0.13.0-1 + +#### LICENSE + +```text + + 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. + +``` + + +### github.com/google/uuid + +* License: BSD-3-Clause +* Module: github.com/google/uuid@v1.6.0 + +#### LICENSE + +```text +Copyright (c) 2009,2014 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +``` + + diff --git a/hack/generate-third-party-notices.sh b/hack/generate-third-party-notices.sh new file mode 100755 index 0000000..fba0d54 --- /dev/null +++ b/hack/generate-third-party-notices.sh @@ -0,0 +1,315 @@ +#!/usr/bin/env bash +# Copyright (c) NVIDIA CORPORATION. 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. + +set -euo pipefail + +OUTPUT="${OUTPUT:-THIRD_PARTY_NOTICES.md}" +MODULES_TXT="${MODULES_TXT:-vendor/modules.txt}" + +PACKAGES=("./...") + +PLATFORMS=( + "linux/amd64" + "linux/arm64" +) + +# CGO must stay on: with it off, go-nvml/pkg/dl leaves the import graph and +# go-licenses reports go-nvml as ".../pkg/nvml" rather than ".../pkg". +export CGO_ENABLED=1 + +die() { + printf 'ERROR: %s\n' "$1" >&2 + shift + if (( $# > 0 )); then + printf '%s\n' "$@" >&2 + fi + exit 1 +} + +log() { + printf '%s\n' "$*" >&2 +} + +# A license that is itself Markdown would close a fixed ``` fence early. +fence_for() { + local file="$1" longest_backtick_run fence_width + # -a: a license holding a NUL byte would print "Binary file ... matches". + longest_backtick_run=$(LC_ALL=C grep -oaE '`+' "${file}" 2>/dev/null \ + | awk '{ if (length($0) > longest) longest = length($0) } END { print longest+0 }') + fence_width=$(( longest_backtick_run + 1 )) + (( fence_width < 3 )) && fence_width=3 + printf '%*s' "${fence_width}" '' | tr ' ' '`' +} + +check_prerequisites() { + command -v go >/dev/null 2>&1 || die "go is not installed." + + if ./bin/go-licenses --help >/dev/null 2>&1; then + GO_LICENSES="${PWD}/bin/go-licenses" + elif command -v go-licenses >/dev/null 2>&1; then + GO_LICENSES="$(command -v go-licenses)" + else + die "no usable go-licenses binary found." \ + "Run 'rm -f bin/go-licenses': a binary built for another platform cannot run here," \ + "and make will not replace one that already exists. Make reinstalls it once it is gone." + fi + + [[ -f "${MODULES_TXT}" ]] \ + || die "${MODULES_TXT} not found — run this from the repo root, or 'make vendor' to create it." + [[ -r "${MODULES_TXT}" ]] \ + || die "${MODULES_TXT} is not readable." + + LOCAL_MODULE=$(go list -m 2>/dev/null || true) + [[ -n "${LOCAL_MODULE}" ]] || die "could not determine local module path via 'go list -m'." + + export GOFLAGS="-mod=vendor" +} + +prepare_workspace() { + # Explicit templates: macOS mktemp ignores TMPDIR without one. + local work_dir_template="${TMPDIR:-/tmp}/go-gpuallocator-notices" + WORK_DIR="$(mktemp -d "${work_dir_template}.XXXXXX")" + SAVE_ROOT="${WORK_DIR}/save" + LICENSES_DIR="${WORK_DIR}/licenses" + COMBINED_CSV="${WORK_DIR}/licenses.csv" + INDEX_FILE="${WORK_DIR}/index" + mkdir -p "${SAVE_ROOT}" "${LICENSES_DIR}" + : > "${COMBINED_CSV}" + + local output_dir + output_dir="$(dirname "${OUTPUT}")" + mkdir -p "${output_dir}" + OUTPUT_TMP="$(mktemp "${output_dir}/.$(basename "${OUTPUT}").XXXXXX")" + trap 'rm -rf "${WORK_DIR}"; rm -f "${OUTPUT_TMP}"' EXIT +} + +collect_licenses() { + local platform goos goarch platform_save_dir + + for platform in "${PLATFORMS[@]}"; do + goos="${platform%/*}" + goarch="${platform#*/}" + log "Collecting licenses for ${goos}/${goarch}..." + + platform_save_dir="${SAVE_ROOT}/${goos}_${goarch}" + + # Only the local module: --ignore matches raw string prefixes, so a + # stdlib list adds the token "go" and drops golang.org/x/*, gopkg.in/*. + GOOS="${goos}" GOARCH="${goarch}" "${GO_LICENSES}" save "${PACKAGES[@]}" \ + --save_path="${platform_save_dir}" \ + --force \ + --ignore="${LOCAL_MODULE}" + + GOOS="${goos}" GOARCH="${goarch}" "${GO_LICENSES}" csv "${PACKAGES[@]}" \ + --ignore="${LOCAL_MODULE}" \ + >> "${COMBINED_CSV}" + + cp -R "${platform_save_dir}/." "${LICENSES_DIR}/" + chmod -R u+w "${LICENSES_DIR}" + done +} + +# Whole-line sort: key-only dedup drops rows, and differs between BSD and GNU. +collapse_index() { + LC_ALL=C sort -u "$1" | awk -F, ' + { + package_path = $1 + if (!(package_path in source_url)) { + source_url[package_path] = $2 + package_order[++package_count] = package_path + } + if (!((package_path SUBSEP $3) in seen_license)) { + seen_license[package_path SUBSEP $3] = 1 + # Count, do not test "package_path in joined_licenses": mawk + # instantiates the target before evaluating the RHS, BWK awk does not. + joined_licenses[package_path] = \ + (license_count[package_path]++ ? joined_licenses[package_path] " / " : "") $3 + } + } + END { + for (i = 1; i <= package_count; i++) { + package_path = package_order[i] + print package_path "," source_url[package_path] "," joined_licenses[package_path] + } + } + ' +} + +# module@version, not a URL: in vendor mode go-licenses points into this repo. +annotate_modules() { + awk -v modules_txt="${MODULES_TXT}" ' + BEGIN { + FS = OFS = "," + while ((getline line < modules_txt) > 0) { + if (line !~ /^# /) continue + split(line, fields, " ") + if (fields[4] == "=>" || fields[3] == "=>") { + replacement_field = (fields[4] == "=>") ? 5 : 4 + if (fields[replacement_field + 1] == "") { + print "ERROR: " modules_txt " replaces " fields[2] " with a local path;" > "/dev/stderr" + print "teach hack/generate-third-party-notices.sh how to attribute it." > "/dev/stderr" + exit 1 + } + module_paths[++module_count] = fields[2] + module_display[fields[2]] = fields[replacement_field] "@" fields[replacement_field + 1] + } else { + module_paths[++module_count] = fields[2] + module_display[fields[2]] = fields[2] "@" fields[3] + } + } + close(modules_txt) + if (module_count == 0) { + print "ERROR: no module lines read from " modules_txt > "/dev/stderr" + exit 1 + } + } + { + longest_match = "" + for (i = 1; i <= module_count; i++) { + module_path = module_paths[i] + if (($1 == module_path || index($1, module_path "/") == 1) \ + && length(module_path) > length(longest_match)) { + longest_match = module_path + } + } + print $0, (longest_match == "" ? "unknown" : module_display[longest_match]) + } + ' +} + +build_index() { + log "Generating dependency index..." + collapse_index "${COMBINED_CSV}" | annotate_modules > "${INDEX_FILE}" + + [[ -s "${INDEX_FILE}" ]] \ + || die "go-licenses produced no entries for ${PACKAGES[*]} — refusing to write empty notices file." + + # go-licenses reports an unclassifiable license as "Unknown" and exits 0. + if cut -d, -f3 "${INDEX_FILE}" | LC_ALL=C grep -qE '^$|(^| / )Unknown( / |$)'; then + die "go-licenses could not classify the license of some packages." \ + "Inspect them by hand rather than committing a file that says 'Unknown'." + fi + + if cut -d, -f4 "${INDEX_FILE}" | LC_ALL=C grep -qx 'unknown'; then + die "could not resolve module@version for some packages from ${MODULES_TXT}." \ + "Run 'make vendor' and re-run, rather than committing a file with unattributed entries." + fi +} + +# Filter by name: for restricted licenses 'go-licenses save' copies whole source. +license_files_for() { + local package_dir="$1" candidate_file + [[ -d "${package_dir}" ]] || return 0 + while IFS= read -r -d '' candidate_file; do + if printf '%s' "$(basename "${candidate_file}")" \ + | LC_ALL=C grep -qiE '^(licen[cs]e|notice|copying|copyright|authors|patents)([-._].*)?$'; then + printf '%s\n' "${candidate_file}" + fi + done < <(find "${package_dir}" -maxdepth 1 -type f -print0 2>/dev/null | LC_ALL=C sort -z) +} + +emit_index_table() { + local package_path _source_url license module + printf '| Package | License | Module |\n' + printf '|---------|---------|--------|\n' + + while IFS=, read -r package_path _source_url license module; do + [[ -z "${package_path}" ]] && continue + # shellcheck disable=SC2016 # backticks are literal markdown here. + printf '| `%s` | %s | `%s` |\n' "${package_path}" "${license:-Unknown}" "${module:-unknown}" + done < "${INDEX_FILE}" +} + +emit_sections() { + local package_path _source_url license module license_files license_file fence + + while IFS=, read -r package_path _source_url license module; do + [[ -z "${package_path}" ]] && continue + + printf '### %s\n\n' "${package_path}" + printf '* License: %s\n' "${license:-Unknown}" + printf '* Module: %s\n\n' "${module:-unknown}" + + license_files=() + while IFS= read -r license_file; do + [[ -n "${license_file}" ]] && license_files+=("${license_file}") + done < <(license_files_for "${LICENSES_DIR}/${package_path}") + + if (( ${#license_files[@]} == 0 )); then + printf 'License text unavailable. See upstream source for the full license.\n' + else + for license_file in "${license_files[@]}"; do + fence="$(fence_for "${license_file}")" + printf '#### %s\n\n' "$(basename "${license_file}")" + printf '%stext\n' "${fence}" + cat "${license_file}" + echo + printf '%s\n' "${fence}" + echo + done + fi + echo + done < "${INDEX_FILE}" +} + +compose_document() { + log "Composing ${OUTPUT}..." + { + cat <<'EOF' +# Third-Party Notices + +NVIDIA go-gpuallocator + +This file lists the third-party Go modules that `go-gpuallocator` links into the +packages a consumer imports, along with the verbatim text of each dependency's +license. `go-gpuallocator` is a library: the module itself is the unit of +distribution, so this covers every package in it. + +Go standard library packages are excluded; they are covered by the license of +the Go distribution itself. Dependencies reached only from `_test.go` files are +excluded; they are vendored for testing but a consumer does not link them. + +## Dependency Index + +EOF + emit_index_table + + cat <<'EOF' + +## License Texts + +EOF + emit_sections + } > "${OUTPUT_TMP}" + + # mktemp creates 0600, and mv within OUTPUT's directory is an atomic rename. + chmod 644 "${OUTPUT_TMP}" + mv -f "${OUTPUT_TMP}" "${OUTPUT}" +} + +main() { + check_prerequisites + prepare_workspace + + collect_licenses + build_index + compose_document + + local package_count + package_count=$(wc -l < "${INDEX_FILE}" | tr -d ' ') + log "Wrote ${OUTPUT} (${package_count} Go packages)" +} + +main "$@" diff --git a/versions.mk b/versions.mk index 6826a1e..9c5a980 100644 --- a/versions.mk +++ b/versions.mk @@ -23,5 +23,7 @@ VERSION ?= $(GIT_TAG) GOLANG_VERSION ?= 1.24.4 +GO_LICENSES_VERSION ?= v2.0.1 + BUILDIMAGE_TAG ?= $(GOLANG_VERSION)-bookworm BUILDIMAGE ?= golang:$(BUILDIMAGE_TAG)