rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

build.c
Go to the documentation of this file.
1
6 #include "system.h"
7
8 #include <rpmio_internal.h> /* XXX fdGetFp */
9 #include <rpmcb.h>
10 #define _RPMTAG_INTERNAL
11 #include <rpmbuild.h>
12 #include "signature.h" /* XXX rpmTempFile */
13
14 #include "debug.h"
15
16 /*@unchecked@*/
17 static int _build_debug = 0;
18
21 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
22 const char * getSourceDir(rpmfileAttrs attr, const char *filename)
23 #else
24 const char * getSourceDir(rpmfileAttrs attr)
25 #endif
26 {
27 const char * dir = NULL;
28 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
29 const char *fn;
30
31 /* support splitted source directories, i.e., source files which
32 are alternatively placed into the .spec directory and picked
33 up from there, too. */
34 if (attr & (RPMFILE_SOURCE|RPMFILE_PATCH|RPMFILE_ICON) && filename != NULL)
35 {
36 fn = rpmGetPath("%{_specdir}/", filename, NULL);
37 if (access(fn, F_OK) == 0)
38 dir = "%{_specdir}/";
39 fn = _free(fn);
40 }
41 if (dir != NULL) {
42 } else
43 #endif
44 if (attr & RPMFILE_SOURCE)
45 dir = "%{_sourcedir}/";
46 else if (attr & RPMFILE_PATCH)
47 dir = "%{_patchdir}/";
48 else if (attr & RPMFILE_ICON)
49 dir = "%{_icondir}/";
50
51 return dir;
52 }
53
54 /*@access urlinfo @*/ /* XXX compared with NULL */
55 /*@access FD_t @*/
56
59 static void doRmSource(Spec spec)
60 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
61 /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
62 {
63 struct Source *sp;
64 int rc;
65
66 #if 0
67 rc = Unlink(spec->specFile);
68 #endif
69
70 for (sp = spec->sources; sp != NULL; sp = sp->next) {
71 const char *dn, *fn;
72 if (sp->flags & RPMFILE_GHOST)
73 continue;
74 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
75 if (! (dn = getSourceDir(sp->flags, sp->source)))
76 #else
77 if (! (dn = getSourceDir(sp->flags)))
78 #endif
79 continue;
80 fn = rpmGenPath(NULL, dn, sp->source);
81 rc = Unlink(fn);
82 fn = _free(fn);
83 }
84 }
85
86 /*
87 * @todo Single use by %%doc in files.c prevents static.
88 */
89 rpmRC doScript(Spec spec, int what, const char *name, rpmiob iob, int test)
90 {
91 const char * rootURL = spec->rootURL;
92 const char * rootDir;
93 const char * scriptName = NULL;
94 const char * buildDirURL = rpmGenPath(rootURL, "%{_builddir}", "");
95 const char * buildScript;
96 const char * buildCmd = NULL;
97 const char * buildTemplate = NULL;
98 const char * buildPost = NULL;
99 const char * mTemplate = NULL;
100 const char * mCmd = NULL;
101 const char * mPost = NULL;
102 int argc = 0;
103 const char **argv = NULL;
104 FILE * fp = NULL;
105 urlinfo u = NULL;
106
107 FD_t fd;
108 FD_t xfd;
109 pid_t pid;
110 pid_t child;
111 int status;
112 rpmRC rc;
113 size_t i;
114
115 switch (what) {
116 case RPMBUILD_PREP:
117 name = "%prep";
118 iob = spec->prep;
119 mTemplate = "%{__spec_prep_template}";
120 mPost = "%{__spec_prep_post}";
121 mCmd = "%{__spec_prep_cmd}";
122 break;
123 case RPMBUILD_BUILD:
124 name = "%build";
125 iob = spec->build;
126 mTemplate = "%{__spec_build_template}";
127 mPost = "%{__spec_build_post}";
128 mCmd = "%{__spec_build_cmd}";
129 break;
130 case RPMBUILD_INSTALL:
131 name = "%install";
132 iob = spec->install;
133 mTemplate = "%{__spec_install_template}";
134 mPost = "%{__spec_install_post}";
135 mCmd = "%{__spec_install_cmd}";
136 break;
137 case RPMBUILD_CHECK:
138 name = "%check";
139 iob = spec->check;
140 mTemplate = "%{__spec_check_template}";
141 mPost = "%{__spec_check_post}";
142 mCmd = "%{__spec_check_cmd}";
143 break;
144 case RPMBUILD_CLEAN:
145 name = "%clean";
146 iob = spec->clean;
147 mTemplate = "%{__spec_clean_template}";
148 mPost = "%{__spec_clean_post}";
149 mCmd = "%{__spec_clean_cmd}";
150 break;
151 case RPMBUILD_RMBUILD:
152 name = "--clean";
153 mTemplate = "%{__spec_clean_template}";
154 mPost = "%{__spec_clean_post}";
155 mCmd = "%{__spec_clean_cmd}";
156 break;
157 /* support "%track" script/section */
158 case RPMBUILD_TRACK:
159 name = "%track";
160 iob = NULL;
161 if (spec->foo)
162 for (i = 0; i < spec->nfoo; i++) {
163 if (spec->foo[i].str == NULL || spec->foo[i].iob == NULL)
164 continue;
165 if (xstrcasecmp(spec->foo[i].str, "track"))
166 continue;
167 iob = spec->foo[i].iob;
168 /*@loopbreak@*/ break;
169 }
170 mTemplate = "%{__spec_track_template}";
171 mPost = "%{__spec_track_post}";
172 mCmd = "%{__spec_track_cmd}";
173 break;
174 case RPMBUILD_STRINGBUF:
175 default:
176 mTemplate = "%{___build_template}";
177 mPost = "%{___build_post}";
178 mCmd = "%{___build_cmd}";
179 break;
180 }
181 if (name == NULL) /* XXX shouldn't happen */
182 name = "???";
183
184 if ((what != RPMBUILD_RMBUILD) && iob == NULL) {
185 rc = RPMRC_OK;
186 goto exit;
187 }
188
189 if (rpmTempFile(rootURL, &scriptName, &fd) || fd == NULL || Ferror(fd)) {
190 rpmlog(RPMLOG_ERR, _("Unable to open temp file.\n"));
191 rc = RPMRC_FAIL;
192 goto exit;
193 }
194
195 if (fdGetFp(fd) == NULL)
196 xfd = Fdopen(fd, "w.fpio");
197 else
198 xfd = fd;
199
200 /*@-type@*/ /* FIX: cast? */
201 if ((fp = fdGetFp(xfd)) == NULL) {
202 rc = RPMRC_FAIL;
203 goto exit;
204 }
205 /*@=type@*/
206
207 (void) urlPath(rootURL, &rootDir);
208 if (*rootDir == '\0') rootDir = "/";
209
210 (void) urlPath(scriptName, &buildScript);
211
212 buildTemplate = rpmExpand(mTemplate, NULL);
213 buildPost = rpmExpand(mPost, NULL);
214
215 (void) fputs(buildTemplate, fp);
216
217 /* support "%track" script/section */
218 if (what != RPMBUILD_PREP && what != RPMBUILD_RMBUILD && spec->buildSubdir && what != RPMBUILD_TRACK)
219 fprintf(fp, "cd '%s'\n", spec->buildSubdir);
220
221 if (what == RPMBUILD_RMBUILD) {
222 if (spec->buildSubdir)
223 fprintf(fp, "rm -rf '%s'\n", spec->buildSubdir);
224 } else if (iob != NULL)
225 fprintf(fp, "%s", rpmiobStr(iob));
226
227 (void) fputs(buildPost, fp);
228
229 (void) Fclose(xfd);
230
231 if (test) {
232 rc = RPMRC_OK;
233 goto exit;
234 }
235
236 if (_build_debug)
237 fprintf(stderr, "*** rootURL %s buildDirURL %s\n", rootURL, buildDirURL);
238 if (buildDirURL && buildDirURL[0] != '/' &&
239 (urlSplit(buildDirURL, &u) != 0)) {
240 rc = RPMRC_FAIL;
241 goto exit;
242 }
243 if (u != NULL) {
244 switch (u->urltype) {
245 case URL_IS_HTTPS:
246 case URL_IS_HTTP:
247 case URL_IS_FTP:
248 if (_build_debug)
249 fprintf(stderr, "*** addMacros\n");
250 addMacro(spec->macros, "_remsh", NULL, "%{__remsh}", RMIL_SPEC);
251 addMacro(spec->macros, "_remhost", NULL, u->host, RMIL_SPEC);
252 if (strcmp(rootDir, "/"))
253 addMacro(spec->macros, "_remroot", NULL, rootDir, RMIL_SPEC);
254 break;
255 case URL_IS_UNKNOWN:
256 case URL_IS_DASH:
257 case URL_IS_PATH:
258 case URL_IS_HKP:
259 default:
260 break;
261 }
262 }
263
264 buildCmd = rpmExpand(mCmd, " ", buildScript, NULL);
265 (void) poptParseArgvString(buildCmd, &argc, &argv);
266
267 if (what != RPMBUILD_TRACK) /* support "%track" script/section */
268 rpmlog(RPMLOG_NOTICE, _("Executing(%s): %s\n"), name, buildCmd);
269 if (!(child = fork())) {
270
271 /*@-mods@*/
272 errno = 0;
273 /*@=mods@*/
274 (void) execvp(argv[0], (char *const *)argv);
275
276 rpmlog(RPMLOG_ERR, _("Exec of %s failed (%s): %s\n"),
277 scriptName, name, strerror(errno));
278
279 _exit(-1);
280 }
281
282 pid = waitpid(child, &status, 0);
283
284 if (!WIFEXITED(status) || WEXITSTATUS(status)) {
285 rpmlog(RPMLOG_ERR, _("Bad exit status from %s (%s)\n"),
286 scriptName, name);
287 rc = RPMRC_FAIL;
288 } else
289 rc = RPMRC_OK;
290
291 exit:
292 if (scriptName) {
293 #if defined(RPM_VENDOR_OPENPKG) /* always-remove-tempfiles */
294 /* Unconditionally remove temporary files ("rpm-tmp.XXXXX") which
295 were generated for the executed scripts. In OpenPKG we run the
296 scripts in debug mode ("set -x") anyway, so we never need to
297 see the whole generated script -- not even if it breaks. Instead
298 we would just have temporary files staying around forever. */
299 #else
300 if (rc == RPMRC_OK)
301 #endif
302 (void) Unlink(scriptName);
303 scriptName = _free(scriptName);
304 }
305 if (u != NULL) {
306 switch (u->urltype) {
307 case URL_IS_HTTPS:
308 case URL_IS_HTTP:
309 case URL_IS_FTP:
310 if (_build_debug)
311 fprintf(stderr, "*** delMacros\n");
312 delMacro(spec->macros, "_remsh");
313 delMacro(spec->macros, "_remhost");
314 if (strcmp(rootDir, "/"))
315 delMacro(spec->macros, "_remroot");
316 break;
317 case URL_IS_UNKNOWN:
318 case URL_IS_DASH:
319 case URL_IS_PATH:
320 case URL_IS_HKP:
321 default:
322 break;
323 }
324 }
325 argv = _free(argv);
326 buildCmd = _free(buildCmd);
327 buildTemplate = _free(buildTemplate);
328 buildPost = _free(buildPost);
329 buildDirURL = _free(buildDirURL);
330
331 return rc;
332 }
333
334 rpmRC buildSpec(rpmts ts, Spec spec, int what, int test)
335 {
336 rpmRC rc = RPMRC_OK;
337
338 if (!spec->recursing && spec->BACount) {
339 int x;
340 /* When iterating over BANames, do the source */
341 /* packaging on the first run, and skip RMSOURCE altogether */
342 if (spec->BASpecs != NULL)
343 for (x = 0; x < spec->BACount; x++) {
344 if ((rc = buildSpec(ts, spec->BASpecs[x],
345 (what & ~RPMBUILD_RMSOURCE) |
346 (x ? 0 : (what & RPMBUILD_PACKAGESOURCE)),
347 test))) {
348 goto exit;
349 }
350 }
351 } else {
352 /* support "%track" script/section */
353 if ((what & RPMBUILD_TRACK) &&
354 (rc = doScript(spec, RPMBUILD_TRACK, NULL, NULL, test)))
355 goto exit;
356
357 if ((what & RPMBUILD_PREP) &&
358 (rc = doScript(spec, RPMBUILD_PREP, NULL, NULL, test)))
359 goto exit;
360
361 if ((what & RPMBUILD_BUILD) &&
362 (rc = doScript(spec, RPMBUILD_BUILD, NULL, NULL, test)))
363 goto exit;
364
365 if ((what & RPMBUILD_INSTALL) &&
366 (rc = doScript(spec, RPMBUILD_INSTALL, NULL, NULL, test)))
367 goto exit;
368
369 if ((what & RPMBUILD_CHECK) &&
370 (rc = doScript(spec, RPMBUILD_CHECK, NULL, NULL, test)))
371 goto exit;
372
373 if ((what & RPMBUILD_PACKAGESOURCE) &&
374 (rc = processSourceFiles(spec)))
375 goto exit;
376
377 if (((what & RPMBUILD_INSTALL) || (what & RPMBUILD_PACKAGEBINARY) ||
378 (what & RPMBUILD_FILECHECK)) &&
379 (rc = processBinaryFiles(spec, what & RPMBUILD_INSTALL, test)))
380 goto exit;
381
382 if (((what & RPMBUILD_PACKAGESOURCE) && !test) &&
383 (rc = packageSources(spec)))
384 return rc;
385
386 if (((what & RPMBUILD_PACKAGEBINARY) && !test) &&
387 (rc = packageBinaries(spec)))
388 goto exit;
389
390 if ((what & RPMBUILD_CLEAN) &&
391 (rc = doScript(spec, RPMBUILD_CLEAN, NULL, NULL, test)))
392 goto exit;
393
394 if ((what & RPMBUILD_RMBUILD) &&
395 (rc = doScript(spec, RPMBUILD_RMBUILD, NULL, NULL, test)))
396 goto exit;
397 }
398
399 if (what & RPMBUILD_RMSOURCE)
400 doRmSource(spec);
401
402 if (what & RPMBUILD_RMSPEC)
403 (void) Unlink(spec->specFile);
404
405 #if defined(RPM_VENDOR_OPENPKG) /* auto-remove-source-directories */
406 /* In OpenPKG we use per-package %{_sourcedir} and %{_specdir}
407 definitions (macros have trailing ".../%{name}"). On removal of
408 source(s) and .spec file, this per-package directory would be kept
409 (usually <prefix>/RPM/SRC/<name>/), because RPM does not know about
410 this OpenPKG convention. So, let RPM try(!) to remove the two
411 directories (if they are empty) and just ignore removal failures
412 (if they are still not empty). */
413 if (what & RPMBUILD_RMSOURCE) {
414 const char *pn;
415 pn = rpmGetPath("%{_sourcedir}", NULL);
416 Rmdir(pn); /* ignore error, it is ok if it fails (usually with ENOTEMPTY) */
417 pn = _free(pn);
418 }
419 if (what & RPMBUILD_RMSPEC) {
420 const char *pn;
421 pn = rpmGetPath("%{_specdir}", NULL);
422 Rmdir(pn); /* ignore error, it is ok if it fails (usually with ENOTEMPTY) */
423 pn = _free(pn);
424 }
425 #endif
426
427 exit:
428 if (rc != RPMRC_OK && rpmlogGetNrecs() > 0) {
429 rpmlog(RPMLOG_NOTICE, _("\n\nRPM build errors:\n"));
430 rpmlogPrint(NULL);
431 }
432
433 return rc;
434 }