Skip to content

Commit f5406ef

Browse files
authored
pythongh-116122: Add SBOM generation to PCbuild/build.bat (pythonGH-116138)
(cherry picked from commit 72dae53) Co-authored-by: Seth Michael Larson <[email protected]>
1 parent 0586d54 commit f5406ef

File tree

2 files changed

+31
-5
lines changed

2 files changed

+31
-5
lines changed

PCbuild/regen.targets

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,15 @@
3030
</_TokenOutputs>
3131
<_KeywordSources Include="$(PySourcePath)Grammar\python.gram;$(PySourcePath)Grammar\Tokens" />
3232
<_KeywordOutputs Include="$(PySourcePath)Lib\keyword.py" />
33+
<_SbomSources Include="$(PySourcePath)PCbuild\get_externals.bat" />
34+
<_SbomOutputs Include="$(PySourcePath)Misc\externals.spdx.json;$(PySourcePath)Misc\sbom.spdx.json">
35+
<Format>json</Format>
36+
</_SbomOutputs>
3337
</ItemGroup>
3438

3539
<Target Name="_TouchRegenSources" Condition="$(ForceRegen) == 'true'">
3640
<Message Text="Touching source files to force regeneration" Importance="high" />
37-
<Touch Files="@(_PegenSources);@(_ASTSources);@(_OpcodeSources);@(_TokenSources);@(_KeywordOutputs)"
41+
<Touch Files="@(_PegenSources);@(_ASTSources);@(_OpcodeSources);@(_TokenSources);@(_KeywordOutputs);@(_SbomSources)"
3842
AlwaysCreate="False" />
3943
</Target>
4044

@@ -89,9 +93,16 @@
8993
WorkingDirectory="$(PySourcePath)" />
9094
</Target>
9195

96+
<Target Name="_RegenSbom"
97+
DependsOnTargets="FindPythonForBuild"
98+
Inputs="@(_SbomSources)"
99+
Outputs="@(_SbomOutputs)">
100+
<Exec Command='$(PythonForBuild) "$(PySourcePath)Tools\build\generate_sbom.py"'/>
101+
</Target>
102+
92103
<Target Name="Regen"
93104
Condition="$(Configuration) != 'PGUpdate'"
94-
DependsOnTargets="_TouchRegenSources;_RegenPegen;_RegenAST_H;_RegenOpcodes;_RegenTokens;_RegenKeywords;_RegenGlobalObjects">
105+
DependsOnTargets="_TouchRegenSources;_RegenPegen;_RegenAST_H;_RegenOpcodes;_RegenTokens;_RegenKeywords;_RegenGlobalObjects;_RegenSbom">
95106
<Message Text="Generated sources are up to date" Importance="high" />
96107
</Target>
97108

Tools/build/generate_sbom.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
import hashlib
55
import json
66
import glob
7-
import pathlib
7+
from pathlib import Path, PurePosixPath, PureWindowsPath
88
import subprocess
99
import sys
1010
import urllib.request
1111
import typing
1212

13-
CPYTHON_ROOT_DIR = pathlib.Path(__file__).parent.parent.parent
13+
CPYTHON_ROOT_DIR = Path(__file__).parent.parent.parent
1414

1515
# Before adding a new entry to this list, double check that
1616
# the license expression is a valid SPDX license expression:
@@ -119,9 +119,16 @@ def filter_gitignored_paths(paths: list[str]) -> list[str]:
119119
# 1 means matches, 0 means no matches.
120120
assert git_check_ignore_proc.returncode in (0, 1)
121121

122+
# Paths may or may not be quoted, Windows quotes paths.
123+
git_check_ignore_re = re.compile(r"^::\s+(\"([^\"]+)\"|(.+))\Z")
124+
122125
# Return the list of paths sorted
123126
git_check_ignore_lines = git_check_ignore_proc.stdout.decode().splitlines()
124-
return sorted([line.split()[-1] for line in git_check_ignore_lines if line.startswith("::")])
127+
git_check_not_ignored = []
128+
for line in git_check_ignore_lines:
129+
if match := git_check_ignore_re.fullmatch(line):
130+
git_check_not_ignored.append(match.group(2) or match.group(3))
131+
return sorted(git_check_not_ignored)
125132

126133

127134
def get_externals() -> list[str]:
@@ -238,12 +245,20 @@ def create_source_sbom() -> None:
238245
)
239246

240247
for path in paths:
248+
249+
# Normalize the filename from any combination of slashes.
250+
path = str(PurePosixPath(PureWindowsPath(path)))
251+
241252
# Skip directories and excluded files
242253
if not (CPYTHON_ROOT_DIR / path).is_file() or path in exclude:
243254
continue
244255

245256
# SPDX requires SHA1 to be used for files, but we provide SHA256 too.
246257
data = (CPYTHON_ROOT_DIR / path).read_bytes()
258+
# We normalize line-endings for consistent checksums.
259+
# This is a rudimentary check for binary files.
260+
if b"\x00" not in data:
261+
data = data.replace(b"\r\n", b"\n")
247262
checksum_sha1 = hashlib.sha1(data).hexdigest()
248263
checksum_sha256 = hashlib.sha256(data).hexdigest()
249264

0 commit comments

Comments
 (0)