diff --git a/build/parsePreamble.c b/build/parsePreamble.c index a23e5a8f65..afc0603f53 100644 --- a/build/parsePreamble.c +++ b/build/parsePreamble.c @@ -797,8 +797,9 @@ static int addBuildOption(rpmSpec spec, const char *sect, const char *opt) return rc; } -static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag, - const char *macro, const char *lang) +static rpmRC handlePreambleTag(rpmSpec spec, enum parseStages stage, + Package pkg, rpmTagVal tag, + const char *macro, const char *lang) { char * field = spec->line; char * end; @@ -1009,6 +1010,14 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag, BANames = _free(BANames); goto exit; } + if (stage == GENERATED && + (BACount != 1 || !rstreq(BANames[0], "noarch"))) { + rpmlog(RPMLOG_ERR, + _("line %d: Only noarch is allowed after the build: %s\n"), + spec->lineNum, spec->line); + BANames = _free(BANames); + goto exit; + } spec->BACount = BACount; spec->BANames = BANames; } else { @@ -1179,7 +1188,7 @@ static int findPreambleTag(rpmSpec spec,rpmTagVal * tag, return 0; } -int parsePreamble(rpmSpec spec, int initialPackage) +int parsePreamble(rpmSpec spec, int initialPackage, enum parseStages stage) { int nextPart = PART_ERROR; int res = PART_ERROR; /* assume failure */ @@ -1248,7 +1257,29 @@ int parsePreamble(rpmSpec spec, int initialPackage) spec->lineNum, spec->line); goto exit; } - if (handlePreambleTag(spec, pkg, tag, macro, lang)) { + if (stage == GENERATED) { + switch (tag) { + case RPMTAG_SOURCE: + case RPMTAG_PATCH: + case RPMTAG_NOSOURCE: + case RPMTAG_NOPATCH: + case RPMTAG_EXCLUDEARCH: + case RPMTAG_EXCLUSIVEARCH: + case RPMTAG_EXCLUDEOS: + case RPMTAG_EXCLUSIVEOS: + case RPMTAG_BUILDROOT: + case RPMTAG_BUILDCONFLICTS: + case RPMTAG_BUILDOPTION: + case RPMTAG_BUILDPREREQ: + case RPMTAG_BUILDREQUIRES: + case RPMTAG_BUILDSYSTEM: + rpmlog(RPMLOG_ERR, _("line %d: Tag not allowed after build is done: %s\n"), + spec->lineNum, spec->line); + goto exit; + default: ; + } + } + if (handlePreambleTag(spec, stage, pkg, tag, macro, lang)) { goto exit; } if (spec->BANames && !spec->recursing) { diff --git a/build/parseSpec.c b/build/parseSpec.c index 6baaffde5c..146deceba3 100644 --- a/build/parseSpec.c +++ b/build/parseSpec.c @@ -100,6 +100,18 @@ int isPart(const char *line) return (p->token ? p->part : PART_NONE); } +static const char * partName(int part) +{ + const struct PartRec *p; + + for (p = partList; p->token != NULL; p++) { + if (p->part == part) { + return p->token; + } + } + return NULL; +} + /** */ static int matchTok(const char *token, const char *line) @@ -1022,7 +1034,7 @@ static rpmRC parseSpecSection(rpmSpec *specptr, enum parseStages stage) parsePart = parseEmpty(spec, prevParsePart); break; case PART_PREAMBLE: - parsePart = parsePreamble(spec, initialPackage); + parsePart = parsePreamble(spec, initialPackage, stage); initialPackage = 0; break; case PART_PATCHLIST: @@ -1111,6 +1123,25 @@ static rpmRC parseSpecSection(rpmSpec *specptr, enum parseStages stage) goto errxit; } + if (stage == GENERATED) { + switch (parsePart) { + case PART_PREP: + case PART_BUILD: + case PART_INSTALL: + case PART_CHECK: + case PART_CLEAN: /* ???? */ + case PART_BUILDARCHITECTURES: + case PART_PATCHLIST: + case PART_SOURCELIST: + case PART_BUILDREQUIRES: + case PART_CONF: + rpmlog(RPMLOG_ERR, _("Section %s is not allowed after build is done!\n"), partName(parsePart)); + goto errxit; + break; + default: + ; + } + } if (parsePart == PART_BUILDARCHITECTURES) { int index; int x; diff --git a/docs/manual/dynamic_specs.md b/docs/manual/dynamic_specs.md index 44e6ca2fc4..2084028707 100644 --- a/docs/manual/dynamic_specs.md +++ b/docs/manual/dynamic_specs.md @@ -34,3 +34,14 @@ interpreted right away. [Example](https://github.com/rpm-software-management/rpm/blob/master/tests/data/SPECS/dynamic.spec) from our tests set. + +As dynamic spec parts are generate during build they cannot include +directives that are needed for or influence building. This includes +all build scripts, sources and patches, Build dependencies, tags +regarding the build environment (**ExcludeArch**, **ExclusiveArch**, +**ExcludeOS**, **ExclusiveOS**), **BuildArch** except for declaring +sub packages **noarch** and **BuildSystem**. These will create an +error if encountered in a dynamically generated spec part. + +While declaring macros used in the build scripts are not an error they +won't have an influence on the build for obvious reasons. diff --git a/tests/data/SPECS/dynamic.spec b/tests/data/SPECS/dynamic.spec index ce31ed2828..511675d051 100644 --- a/tests/data/SPECS/dynamic.spec +++ b/tests/data/SPECS/dynamic.spec @@ -41,6 +41,8 @@ echo "LicenseToKill: True" >> %{specpartsdir}/mainpkg.specpart echo "%package docs" >> %{specpartsdir}/docs.specpart %{?!FAIL:echo "Summary: Documentation for dynamic spec" >> %{specpartsdir}/docs.specpart} echo "BuildArch: noarch" >> %{specpartsdir}/docs.specpart +%{?FORBIDDENTAG:echo "BuildRequires: python3" >> %{specpartsdir}/docs.specpart} +%{?FORBIDDENSECTION:echo "%check" >> %{specpartsdir}/docs.specpart} echo "%description docs" >> %{specpartsdir}/docs.specpart echo "Test for dynamically generated spec files" >> %{specpartsdir}/docs.specpart echo "%files docs" >> $RPM_SPECPARTS_DIR/docs.specpart diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at index c47a532e9b..0857e76d8d 100644 --- a/tests/rpmbuild.at +++ b/tests/rpmbuild.at @@ -2764,6 +2764,40 @@ error: parsing failed RPMTEST_CLEANUP +# ------------------------------ +# Check failing dynamic spec generation +AT_SETUP([rpmbuild with dynamic spec generation fail]) +AT_KEYWORDS([build]) +RPMDB_INIT +RPMTEST_CHECK([ + +runroot rpmbuild --quiet -D "FULLDYNAMIC 1" -D "FORBIDDENSECTION 1" -ba /data/SPECS/dynamic.spec +], +[1], +[], +[error: Section %check is not allowed after build is done! +error: parsing failed +]) + +RPMTEST_CLEANUP + +# ------------------------------ +# Check failing dynamic spec generation +AT_SETUP([rpmbuild with dynamic spec generation fail]) +AT_KEYWORDS([build]) +RPMDB_INIT +RPMTEST_CHECK([ + +runroot rpmbuild --quiet -D "FULLDYNAMIC 1" -D "FORBIDDENTAG 1" -ba /data/SPECS/dynamic.spec +], +[1], +[], +[error: line 4: Tag not allowed after build is done: BuildRequires: python3 +error: parsing failed +]) + +RPMTEST_CLEANUP + # ------------------------------ # Check source name with space