3 * Top-level build dispatcher.
11 #include <rpm/rpmlog.h>
12 #include <rpm/rpmfileutil.h>
13 #include "build/rpmbuild_internal.h"
14 #include "build/rpmbuild_misc.h"
15 #include "lib/rpmug.h"
21 static rpmRC doRmSource(rpmSpec spec)
27 for (p = spec->sources; p != NULL; p = p->next) {
28 if (! (p->flags & RPMBUILD_ISNO)) {
29 char *fn = rpmGetPath("%{_sourcedir}/", p->source, NULL);
36 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
37 for (p = pkg->icon; p != NULL; p = p->next) {
38 if (! (p->flags & RPMBUILD_ISNO)) {
39 char *fn = rpmGetPath("%{_sourcedir}/", p->source, NULL);
47 return !rc ? RPMRC_OK : RPMRC_FAIL;
51 * @todo Single use by %%doc in files.c prevents static.
53 rpmRC doScript(rpmSpec spec, rpmBuildFlags what, const char *name,
54 const char *sb, int test)
56 char *scriptName = NULL;
57 char * buildDir = rpmGenPath(spec->rootDir, "%{_builddir}", "");
58 char * buildCmd = NULL;
59 char * buildTemplate = NULL;
60 char * buildPost = NULL;
61 const char * mTemplate = NULL;
62 const char * mCmd = NULL;
63 const char * mPost = NULL;
65 const char **argv = NULL;
72 rpmRC rc = RPMRC_FAIL; /* assume failure */
76 mTemplate = "%{__spec_prep_template}";
77 mPost = "%{__spec_prep_post}";
78 mCmd = "%{__spec_prep_cmd}";
81 mTemplate = "%{__spec_build_template}";
82 mPost = "%{__spec_build_post}";
83 mCmd = "%{__spec_build_cmd}";
85 case RPMBUILD_INSTALL:
86 mTemplate = "%{__spec_install_template}";
87 mPost = "%{__spec_install_post}";
88 mCmd = "%{__spec_install_cmd}";
91 mTemplate = "%{__spec_check_template}";
92 mPost = "%{__spec_check_post}";
93 mCmd = "%{__spec_check_cmd}";
96 mTemplate = "%{__spec_clean_template}";
97 mPost = "%{__spec_clean_post}";
98 mCmd = "%{__spec_clean_cmd}";
100 case RPMBUILD_RMBUILD:
101 mTemplate = "%{__spec_clean_template}";
102 mPost = "%{__spec_clean_post}";
103 mCmd = "%{__spec_clean_cmd}";
105 case RPMBUILD_STRINGBUF:
107 mTemplate = "%{___build_template}";
108 mPost = "%{___build_post}";
109 mCmd = "%{___build_cmd}";
113 if ((what != RPMBUILD_RMBUILD) && sb == NULL) {
118 fd = rpmMkTempFile(spec->rootDir, &scriptName);
120 rpmlog(RPMLOG_ERR, _("Unable to open temp file: %s\n"), Fstrerror(fd));
124 if ((fp = fdopen(Fileno(fd), "w")) == NULL) {
125 rpmlog(RPMLOG_ERR, _("Unable to open stream: %s\n"), strerror(errno));
129 buildTemplate = rpmExpand(mTemplate, NULL);
130 buildPost = rpmExpand(mPost, NULL);
132 (void) fputs(buildTemplate, fp);
134 if (what != RPMBUILD_PREP && what != RPMBUILD_RMBUILD && spec->buildSubdir)
135 fprintf(fp, "cd '%s'\n", spec->buildSubdir);
137 if (what == RPMBUILD_RMBUILD) {
138 if (spec->buildSubdir)
139 fprintf(fp, "rm -rf '%s'\n", spec->buildSubdir);
140 } else if (sb != NULL)
141 fprintf(fp, "%s", sb);
143 (void) fputs(buildPost, fp);
151 if (buildDir && buildDir[0] != '/') {
155 buildCmd = rpmExpand(mCmd, " ", scriptName, NULL);
156 (void) poptParseArgvString(buildCmd, &argc, &argv);
158 rpmlog(RPMLOG_NOTICE, _("Executing(%s): %s\n"), name, buildCmd);
159 if (!(child = fork())) {
161 (void) execvp(argv[0], (char *const *)argv);
163 rpmlog(RPMLOG_ERR, _("Exec of %s failed (%s): %s\n"),
164 scriptName, name, strerror(errno));
166 _exit(127); /* exit 127 for compatibility with bash(1) */
169 pid = waitpid(child, &status, 0);
172 rpmlog(RPMLOG_ERR, _("Error executing scriptlet %s (%s)\n"),
177 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
178 rpmlog(RPMLOG_ERR, _("Bad exit status from %s (%s)\n"),
186 if (rc == RPMRC_OK && !rpmIsDebug())
187 (void) unlink(scriptName);
199 static rpmRC buildSpec(BTA_t buildArgs, rpmSpec spec, int what)
202 int test = (what & RPMBUILD_NOBUILD);
203 char *cookie = buildArgs->cookie ? xstrdup(buildArgs->cookie) : NULL;
205 if (rpmExpandNumeric("%{?source_date_epoch_from_changelog}") &&
206 getenv("SOURCE_DATE_EPOCH") == NULL) {
207 /* Use date of first (== latest) changelog entry */
208 Header h = spec->packages->header;
210 if (headerGet(h, RPMTAG_CHANGELOGTIME, &td, (HEADERGET_MINMEM|HEADERGET_RAW))) {
212 snprintf(sdestr, sizeof(sdestr), "%lli",
213 (long long) rpmtdGetNumber(&td));
214 rpmlog(RPMLOG_NOTICE, _("setting %s=%s\n"), "SOURCE_DATE_EPOCH", sdestr);
215 setenv("SOURCE_DATE_EPOCH", sdestr, 0);
220 /* XXX TODO: rootDir is only relevant during build, eliminate from spec */
221 spec->rootDir = buildArgs->rootdir;
222 if (!spec->recursing && spec->BACount) {
224 /* When iterating over BANames, do the source */
225 /* packaging on the first run, and skip RMSOURCE altogether */
226 if (spec->BASpecs != NULL)
227 for (x = 0; x < spec->BACount; x++) {
228 if ((rc = buildSpec(buildArgs, spec->BASpecs[x],
229 (what & ~RPMBUILD_RMSOURCE) |
230 (x ? 0 : (what & RPMBUILD_PACKAGESOURCE))))) {
235 int didBuild = (what & (RPMBUILD_PREP|RPMBUILD_BUILD|RPMBUILD_INSTALL));
237 if ((what & RPMBUILD_PREP) &&
238 (rc = doScript(spec, RPMBUILD_PREP, "%prep",
239 getStringBuf(spec->prep), test)))
242 if ((what & RPMBUILD_BUILD) &&
243 (rc = doScript(spec, RPMBUILD_BUILD, "%build",
244 getStringBuf(spec->build), test)))
247 if ((what & RPMBUILD_INSTALL) &&
248 (rc = doScript(spec, RPMBUILD_INSTALL, "%install",
249 getStringBuf(spec->install), test)))
252 if ((what & RPMBUILD_CHECK) &&
253 (rc = doScript(spec, RPMBUILD_CHECK, "%check",
254 getStringBuf(spec->check), test)))
257 if ((what & RPMBUILD_PACKAGESOURCE) &&
258 (rc = processSourceFiles(spec, buildArgs->pkgFlags)))
261 if (((what & RPMBUILD_INSTALL) || (what & RPMBUILD_PACKAGEBINARY) ||
262 (what & RPMBUILD_FILECHECK)) &&
263 (rc = processBinaryFiles(spec, buildArgs->pkgFlags,
264 what & RPMBUILD_INSTALL, test)))
267 if (((what & RPMBUILD_INSTALL) || (what & RPMBUILD_PACKAGEBINARY)) &&
268 (rc = processBinaryPolicies(spec, test)))
271 if (((what & RPMBUILD_PACKAGESOURCE) && !test) &&
272 (rc = packageSources(spec, &cookie)))
275 if (((what & RPMBUILD_PACKAGEBINARY) && !test) &&
276 (rc = packageBinaries(spec, cookie, (didBuild == 0))))
279 if ((what & RPMBUILD_CLEAN) &&
280 (rc = doScript(spec, RPMBUILD_CLEAN, "%clean",
281 getStringBuf(spec->clean), test)))
284 if ((what & RPMBUILD_RMBUILD) &&
285 (rc = doScript(spec, RPMBUILD_RMBUILD, "--clean", NULL, test)))
289 if (what & RPMBUILD_RMSOURCE)
292 if (what & RPMBUILD_RMSPEC)
293 (void) unlink(spec->specFile);
297 spec->rootDir = NULL;
298 if (rc != RPMRC_OK && rpmlogGetNrecs() > 0) {
299 rpmlog(RPMLOG_NOTICE, _("\n\nRPM build errors:\n"));
307 rpmRC rpmSpecBuild(rpmSpec spec, BTA_t buildArgs)
309 /* buildSpec() can recurse with different buildAmount, pass it separately */
310 return buildSpec(buildArgs, spec, buildArgs->buildAmount);