2 * Parse spec file and build package.
7 #include <rpm/rpmcli.h>
8 #include <rpm/rpmtag.h>
9 #include <rpm/rpmlib.h> /* rpmrc, MACHTABLE .. */
10 #include <rpm/rpmbuild.h>
12 #include <rpm/rpmps.h>
13 #include <rpm/rpmte.h>
14 #include <rpm/rpmts.h>
15 #include <rpm/rpmfileutil.h>
16 #include <rpm/rpmlog.h>
23 static int checkSpec(rpmts ts, Header h)
28 if (!headerIsEntry(h, RPMTAG_REQUIRENAME)
29 && !headerIsEntry(h, RPMTAG_CONFLICTNAME))
32 rc = rpmtsAddInstallElement(ts, h, NULL, 0, NULL);
36 ps = rpmtsProblems(ts);
37 if (rc == 0 && rpmpsNumProblems(ps) > 0) {
38 rpmlog(RPMLOG_ERR, _("Failed build dependencies:\n"));
44 /* XXX nuke the added package. */
52 static int isSpecFile(const char * specfile)
60 f = fopen(specfile, "r");
61 if (f == NULL || ferror(f)) {
62 rpmlog(RPMLOG_ERR, _("Unable to open spec file %s: %s\n"),
63 specfile, strerror(errno));
66 count = fread(buf, sizeof(buf[0]), sizeof(buf), f);
70 for (s = buf; count--; s++) {
81 if (checking && !(isprint(*s) || isspace(*s))) return 0;
84 if (checking && !(isprint(*s) || isspace(*s)) && *(unsigned char *)s < 32) return 0;
94 static int buildForTarget(rpmts ts, const char * arg, BTA_t ba)
96 const char * passPhrase = ba->passPhrase;
97 const char * cookie = ba->cookie;
98 int buildAmount = ba->buildAmount;
99 char * buildRootURL = NULL;
100 const char * specFile;
101 const char * specURL;
108 rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
111 if (ba->buildRootOverride)
112 buildRootURL = rpmGenPath(NULL, ba->buildRootOverride, NULL);
114 /* FIX: static zcmds heartburn */
115 if (ba->buildMode == 't') {
120 rpmCompressedMagic res = COMPRESSED_OTHER;
121 static const char *zcmds[] =
122 { "cat", "gunzip", "bunzip2", "cat" };
124 specDir = rpmGetPath("%{_specdir}", NULL);
126 tmpSpecFile = (char *) rpmGetPath("%{_specdir}/", "rpm-spec.XXXXXX", NULL);
127 #if defined(HAVE_MKSTEMP)
128 (void) close(mkstemp(tmpSpecFile));
130 (void) mktemp(tmpSpecFile);
133 (void) rpmFileIsCompressed(arg, &res);
135 cmd = alloca(strlen(arg) + 50 + strlen(tmpSpecFile));
136 sprintf(cmd, "%s < '%s' | tar xOvf - Specfile 2>&1 > '%s'",
137 zcmds[res & 0x3], arg, tmpSpecFile);
138 if (!(fp = popen(cmd, "r"))) {
139 rpmlog(RPMLOG_ERR, _("Failed to open tar pipe: %m\n"));
140 specDir = _free(specDir);
141 tmpSpecFile = _free(tmpSpecFile);
144 if ((!fgets(buf, sizeof(buf) - 1, fp)) || !strchr(buf, '/')) {
148 sprintf(cmd, "%s < '%s' | tar xOvf - --wildcards \\*.spec 2>&1 > '%s'",
149 zcmds[res & 0x3], arg, tmpSpecFile);
150 if (!(fp = popen(cmd, "r"))) {
151 rpmlog(RPMLOG_ERR, _("Failed to open tar pipe: %m\n"));
152 specDir = _free(specDir);
153 tmpSpecFile = _free(tmpSpecFile);
156 if (!fgets(buf, sizeof(buf) - 1, fp)) {
158 rpmlog(RPMLOG_ERR, _("Failed to read spec file from %s\n"),
160 (void) unlink(tmpSpecFile);
161 specDir = _free(specDir);
162 tmpSpecFile = _free(tmpSpecFile);
169 while (*cmd != '\0') {
170 if (*cmd == '/') s = cmd + 1;
176 /* remove trailing \n */
177 s = cmd + strlen(cmd) - 1;
180 specURL = s = alloca(strlen(specDir) + strlen(cmd) + 5);
181 sprintf(s, "%s/%s", specDir, cmd);
182 res = rename(tmpSpecFile, s);
183 specDir = _free(specDir);
186 rpmlog(RPMLOG_ERR, _("Failed to rename %s to %s: %m\n"),
188 (void) unlink(tmpSpecFile);
189 tmpSpecFile = _free(tmpSpecFile);
192 tmpSpecFile = _free(tmpSpecFile);
194 /* Make the directory which contains the tarball the source
195 directory for this run */
198 if (!getcwd(buf, BUFSIZ)) {
199 rpmlog(RPMLOG_ERR, _("getcwd failed: %m\n"));
207 cmd = buf + strlen(buf) - 1;
208 while (*cmd != '/') cmd--;
211 addMacro(NULL, "_sourcedir", NULL, buf, RMIL_TARBALL);
216 specut = urlPath(specURL, &specFile);
217 if (*specFile != '/') {
218 char *s = alloca(BUFSIZ);
219 if (!getcwd(s, BUFSIZ)) {
220 rpmlog(RPMLOG_ERR, _("getcwd failed: %m\n"));
229 if (specut != URL_IS_DASH) {
231 if (stat(specURL, &st) < 0) {
232 rpmlog(RPMLOG_ERR, _("failed to stat %s: %m\n"), specURL);
236 if (! S_ISREG(st.st_mode)) {
237 rpmlog(RPMLOG_ERR, _("File %s is not a regular file.\n"),
243 /* Try to verify that the file is actually a specfile */
244 if (!isSpecFile(specURL)) {
246 _("File %s does not appear to be a specfile.\n"), specURL);
252 /* Parse the spec file */
253 #define _anyarch(_f) \
254 (((_f)&(RPMBUILD_PREP|RPMBUILD_BUILD|RPMBUILD_INSTALL|RPMBUILD_PACKAGEBINARY)) == 0)
255 if (parseSpec(ts, specURL, ba->rootdir, buildRootURL, 0, passPhrase,
256 cookie, _anyarch(buildAmount), ba->force))
262 if ((spec = rpmtsSetSpec(ts, NULL)) == NULL) {
267 /* Assemble source header from parsed components */
268 initSourceHeader(spec);
270 /* Check build prerequisites */
271 if (!ba->noDeps && checkSpec(ts, spec->sourceHeader)) {
276 if (buildSpec(ts, spec, buildAmount, ba->noBuild)) {
281 if (ba->buildMode == 't')
282 (void) unlink(specURL);
286 spec = freeSpec(spec);
287 buildRootURL = _free(buildRootURL);
291 int build(rpmts ts, const char * arg, BTA_t ba, const char * rcfile)
295 char * targets = ba->targets;
296 #define buildCleanMask (RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC)
297 int cleanFlags = ba->buildAmount & buildCleanMask;
298 rpmVSFlags vsflags, ovsflags;
300 vsflags = rpmExpandNumeric("%{_vsflags_build}");
301 if (ba->qva_flags & VERIFY_DIGEST)
302 vsflags |= _RPMVSF_NODIGESTS;
303 if (ba->qva_flags & VERIFY_SIGNATURE)
304 vsflags |= _RPMVSF_NOSIGNATURES;
305 if (ba->qva_flags & VERIFY_HDRCHK)
306 vsflags |= RPMVSF_NOHDRCHK;
307 ovsflags = rpmtsSetVSFlags(ts, vsflags);
309 if (targets == NULL) {
310 rc = buildForTarget(ts, arg, ba);
314 /* parse up the build operators */
316 printf(_("Building target platforms: %s\n"), targets);
318 ba->buildAmount &= ~buildCleanMask;
319 for (t = targets; *t != '\0'; t = te) {
321 if ((te = strchr(t, ',')) == NULL)
323 target = alloca(te-t+1);
324 strncpy(target, t, (te-t));
328 else /* XXX Perform clean-up after last target build. */
329 ba->buildAmount |= cleanFlags;
331 printf(_("Building for target %s\n"), target);
333 /* Read in configuration for target. */
336 (void) rpmReadConfigFiles(rcfile, target);
337 rc = buildForTarget(ts, arg, ba);
343 vsflags = rpmtsSetVSFlags(ts, ovsflags);
344 /* Restore original configuration. */
347 (void) rpmReadConfigFiles(rcfile, NULL);