diff --git a/share/sbom.am b/share/sbom.am index 49d7a16..cb600a2 100644 --- a/share/sbom.am +++ b/share/sbom.am @@ -44,6 +44,10 @@ # captured (e.g. wolfEngine: $(abs_builddir)/include/config.h; # wolfCLU: $(abs_builddir)/src/config.h). # Default: $(abs_builddir)/config.h. +# SBOM_HOSTCC Host C compiler used to expand the build macros (the +# -D/-U/-I tokens only, never the configured cross $(CC)), +# so the SBOM is byte-reproducible across toolchains. +# Default: cc. # # The wolfSSL/OpenSSL dependency flags are feature-detected against gen-sbom # --help, so a product wired for them still produces a valid SBOM (with a NOTE) @@ -69,6 +73,13 @@ SBOM_BIN_NAME ?= $(SBOM_PKGNAME) SBOM_DEP_WOLFSSL ?= no SBOM_DEP_OPENSSL ?= no SBOM_CONFIG_H ?= $(abs_builddir)/config.h +# Host C compiler used to capture the build macros (matching the Make/CMake +# paths' HOSTCC), NOT the configured $(CC): on a cross build $(CC) would bake +# the cross compiler's target-specific predefined macros into the SBOM, so the +# same product built through a different toolchain would produce a different +# document. Only the -D/-U/-I tokens are fed to it (see the capture below), so +# it never sees target arch flags it cannot parse. +SBOM_HOSTCC ?= cc # Directory the wolfGlass tooling (gen-sbom) is vendored into. Products that # vendor elsewhere override this (or SBOM_GEN directly). SBOM_VENDOR_DIR ?= $(srcdir)/tools/sbom @@ -109,9 +120,11 @@ CLEANFILES += $(SBOM_CDX) $(SBOM_SPDX) $(SBOM_SPDX_TV) # Stage a `make install` into a private tree, discover the installed artifact # (shared/static library or program; ELF/Mach-O/PE), hash it, capture the -# configured build macros (from SBOM_OPTIONS_H if set, else AM_CPPFLAGS/ -# AM_CFLAGS/CFLAGS + config.h; some products carry their feature -D flags in -# AM_CFLAGS rather than AM_CPPFLAGS, and some outside config.h entirely), +# configured build macros (from SBOM_OPTIONS_H if set, else the -D/-U/-I tokens +# of AM_CPPFLAGS/AM_CFLAGS/CFLAGS + config.h, expanded through the HOST compiler +# SBOM_HOSTCC so the SBOM is reproducible across cross toolchains; some products +# carry their feature -D flags in AM_CFLAGS rather than AM_CPPFLAGS, and some +# outside config.h entirely), # generate SPDX+CDX, validate # the SPDX, then convert to tag-value. The staging tree and temp defines file # are removed unconditionally via `trap`, even on failure. SOURCE_DATE_EPOCH is @@ -157,8 +170,11 @@ sbom: opts_h="$(SBOM_OPTIONS_H)"; \ if test -z "$$opts_h"; then \ opts_h="$$_defines"; \ - $(CC) -dM -E $(DEFAULT_INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) \ + sbom_cpp=""; \ + for f in $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS); do \ + case "$$f" in -D*|-U*|-I*) sbom_cpp="$$sbom_cpp $$f";; esac; \ + done; \ + $(SBOM_HOSTCC) -dM -E $(DEFAULT_INCLUDES) $$sbom_cpp \ $(if $(wildcard $(SBOM_CONFIG_H)),-include $(SBOM_CONFIG_H)) \ -x c /dev/null > "$$_defines"; \ fi; \