Automated merge with ssh://pmatilai@login.linux.duke.edu//home/groups/rpm/hg/rpm/
[platform/upstream/rpm.git] / build / build.c
1 /** \ingroup rpmbuild
2  * \file build/build.c
3  *  Top-level build dispatcher.
4  */
5
6 #include "system.h"
7
8 #include <rpmio_internal.h>
9 #include <rpmbuild.h>
10 #include "misc.h"       /* XXX for makeTempFile */
11
12 #include "debug.h"
13
14 static int _build_debug = 0;
15
16 /**
17  */
18 static void doRmSource(Spec spec)
19 {
20     struct Source *p;
21     Package pkg;
22     int rc;
23     
24 #if 0
25     rc = Unlink(spec->specFile);
26 #endif
27
28     for (p = spec->sources; p != NULL; p = p->next) {
29         if (! (p->flags & RPMBUILD_ISNO)) {
30             const char *fn = rpmGetPath("%{_sourcedir}/", p->source, NULL);
31             rc = Unlink(fn);
32             fn = _free(fn);
33         }
34     }
35
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                 const char *fn = rpmGetPath("%{_sourcedir}/", p->source, NULL);
40                 rc = Unlink(fn);
41                 fn = _free(fn);
42             }
43         }
44     }
45 }
46
47 /*
48  * @todo Single use by %%doc in files.c prevents static.
49  */
50 int doScript(Spec spec, int what, const char *name, StringBuf sb, int test)
51 {
52     const char * rootURL = spec->rootURL;
53     const char * rootDir;
54     const char *scriptName = NULL;
55     const char * buildDirURL = rpmGenPath(rootURL, "%{_builddir}", "");
56     const char * buildScript;
57     const char * buildCmd = NULL;
58     const char * buildTemplate = NULL;
59     const char * buildPost = NULL;
60     const char * mTemplate = NULL;
61     const char * mCmd = NULL;
62     const char * mPost = NULL;
63     int argc = 0;
64     const char **argv = NULL;
65     FILE * fp = NULL;
66     urlinfo u = NULL;
67
68     FD_t fd;
69     FD_t xfd;
70     int child;
71     int status;
72     int rc;
73     
74     switch (what) {
75     case RPMBUILD_PREP:
76         name = "%prep";
77         sb = spec->prep;
78         mTemplate = "%{__spec_prep_template}";
79         mPost = "%{__spec_prep_post}";
80         mCmd = "%{__spec_prep_cmd}";
81         break;
82     case RPMBUILD_BUILD:
83         name = "%build";
84         sb = spec->build;
85         mTemplate = "%{__spec_build_template}";
86         mPost = "%{__spec_build_post}";
87         mCmd = "%{__spec_build_cmd}";
88         break;
89     case RPMBUILD_INSTALL:
90         name = "%install";
91         sb = spec->install;
92         mTemplate = "%{__spec_install_template}";
93         mPost = "%{__spec_install_post}";
94         mCmd = "%{__spec_install_cmd}";
95         break;
96     case RPMBUILD_CHECK:
97         name = "%check";
98         sb = spec->check;
99         mTemplate = "%{__spec_check_template}";
100         mPost = "%{__spec_check_post}";
101         mCmd = "%{__spec_check_cmd}";
102         break;
103     case RPMBUILD_CLEAN:
104         name = "%clean";
105         sb = spec->clean;
106         mTemplate = "%{__spec_clean_template}";
107         mPost = "%{__spec_clean_post}";
108         mCmd = "%{__spec_clean_cmd}";
109         break;
110     case RPMBUILD_RMBUILD:
111         name = "--clean";
112         mTemplate = "%{__spec_clean_template}";
113         mPost = "%{__spec_clean_post}";
114         mCmd = "%{__spec_clean_cmd}";
115         break;
116     case RPMBUILD_STRINGBUF:
117     default:
118         mTemplate = "%{___build_template}";
119         mPost = "%{___build_post}";
120         mCmd = "%{___build_cmd}";
121         break;
122     }
123     if (name == NULL)   /* XXX shouldn't happen */
124         name = "???";
125
126     if ((what != RPMBUILD_RMBUILD) && sb == NULL) {
127         rc = 0;
128         goto exit;
129     }
130     
131     if (makeTempFile(rootURL, &scriptName, &fd) || fd == NULL || Ferror(fd)) {
132         rpmError(RPMERR_SCRIPT, _("Unable to open temp file.\n"));
133         rc = RPMERR_SCRIPT;
134         goto exit;
135     }
136
137 #ifdef HAVE_FCHMOD
138     switch (rootut) {
139     case URL_IS_PATH:
140     case URL_IS_UNKNOWN:
141         (void)fchmod(Fileno(fd), 0600);
142         break;
143     default:
144         break;
145     }
146 #endif
147
148     if (fdGetFp(fd) == NULL)
149         xfd = Fdopen(fd, "w.fpio");
150     else
151         xfd = fd;
152
153     /* FIX: cast? */
154     if ((fp = fdGetFp(xfd)) == NULL) {
155         rc = RPMERR_SCRIPT;
156         goto exit;
157     }
158     
159     (void) urlPath(rootURL, &rootDir);
160     if (*rootDir == '\0') rootDir = "/";
161
162     (void) urlPath(scriptName, &buildScript);
163
164     buildTemplate = rpmExpand(mTemplate, NULL);
165     buildPost = rpmExpand(mPost, NULL);
166
167     (void) fputs(buildTemplate, fp);
168
169     if (what != RPMBUILD_PREP && what != RPMBUILD_RMBUILD && spec->buildSubdir)
170         fprintf(fp, "cd '%s'\n", spec->buildSubdir);
171
172     if (what == RPMBUILD_RMBUILD) {
173         if (spec->buildSubdir)
174             fprintf(fp, "rm -rf '%s'\n", spec->buildSubdir);
175     } else if (sb != NULL)
176         fprintf(fp, "%s", getStringBuf(sb));
177
178     (void) fputs(buildPost, fp);
179     
180     (void) Fclose(xfd);
181
182     if (test) {
183         rc = 0;
184         goto exit;
185     }
186     
187 if (_build_debug)
188 fprintf(stderr, "*** rootURL %s buildDirURL %s\n", rootURL, buildDirURL);
189     if (buildDirURL && buildDirURL[0] != '/' &&
190         (urlSplit(buildDirURL, &u) != 0)) {
191         rc = RPMERR_SCRIPT;
192         goto exit;
193     }
194     if (u != NULL) {
195         switch (u->urltype) {
196         case URL_IS_HTTPS:
197         case URL_IS_HTTP:
198         case URL_IS_FTP:
199 if (_build_debug)
200 fprintf(stderr, "*** addMacros\n");
201             addMacro(spec->macros, "_remsh", NULL, "%{__remsh}", RMIL_SPEC);
202             addMacro(spec->macros, "_remhost", NULL, u->host, RMIL_SPEC);
203             if (strcmp(rootDir, "/"))
204                 addMacro(spec->macros, "_remroot", NULL, rootDir, RMIL_SPEC);
205             break;
206         case URL_IS_UNKNOWN:
207         case URL_IS_DASH:
208         case URL_IS_PATH:
209         case URL_IS_HKP:
210         default:
211             break;
212         }
213     }
214
215     buildCmd = rpmExpand(mCmd, " ", buildScript, NULL);
216     (void) poptParseArgvString(buildCmd, &argc, &argv);
217
218     rpmMessage(RPMMESS_NORMAL, _("Executing(%s): %s\n"), name, buildCmd);
219     if (!(child = fork())) {
220
221         errno = 0;
222         (void) execvp(argv[0], (char *const *)argv);
223
224         rpmError(RPMERR_SCRIPT, _("Exec of %s failed (%s): %s\n"),
225                 scriptName, name, strerror(errno));
226
227         _exit(-1);
228     }
229
230     rc = waitpid(child, &status, 0);
231
232     if (!WIFEXITED(status) || WEXITSTATUS(status)) {
233         rpmError(RPMERR_SCRIPT, _("Bad exit status from %s (%s)\n"),
234                  scriptName, name);
235         rc = RPMERR_SCRIPT;
236     } else
237         rc = 0;
238     
239 exit:
240     if (scriptName) {
241         if (!rc)
242             (void) Unlink(scriptName);
243         scriptName = _free(scriptName);
244     }
245     if (u != NULL) {
246         switch (u->urltype) {
247         case URL_IS_HTTPS:
248         case URL_IS_HTTP:
249         case URL_IS_FTP:
250 if (_build_debug)
251 fprintf(stderr, "*** delMacros\n");
252             delMacro(spec->macros, "_remsh");
253             delMacro(spec->macros, "_remhost");
254             if (strcmp(rootDir, "/"))
255                 delMacro(spec->macros, "_remroot");
256             break;
257         case URL_IS_UNKNOWN:
258         case URL_IS_DASH:
259         case URL_IS_PATH:
260         case URL_IS_HKP:
261         default:
262             break;
263         }
264         u = urlFree(u);
265     }
266     argv = _free(argv);
267     buildCmd = _free(buildCmd);
268     buildTemplate = _free(buildTemplate);
269     buildPost = _free(buildPost);
270     buildDirURL = _free(buildDirURL);
271
272     return rc;
273 }
274
275 int buildSpec(rpmts ts, Spec spec, int what, int test)
276 {
277     int rc = 0;
278
279     if (!spec->recursing && spec->BACount) {
280         int x;
281         /* When iterating over BANames, do the source    */
282         /* packaging on the first run, and skip RMSOURCE altogether */
283         if (spec->BASpecs != NULL)
284         for (x = 0; x < spec->BACount; x++) {
285             if ((rc = buildSpec(ts, spec->BASpecs[x],
286                                 (what & ~RPMBUILD_RMSOURCE) |
287                                 (x ? 0 : (what & RPMBUILD_PACKAGESOURCE)),
288                                 test))) {
289                 goto exit;
290             }
291         }
292     } else {
293         if ((what & RPMBUILD_PREP) &&
294             (rc = doScript(spec, RPMBUILD_PREP, NULL, NULL, test)))
295                 goto exit;
296
297         if ((what & RPMBUILD_BUILD) &&
298             (rc = doScript(spec, RPMBUILD_BUILD, NULL, NULL, test)))
299                 goto exit;
300
301         if ((what & RPMBUILD_INSTALL) &&
302             (rc = doScript(spec, RPMBUILD_INSTALL, NULL, NULL, test)))
303                 goto exit;
304
305         if ((what & RPMBUILD_CHECK) &&
306             (rc = doScript(spec, RPMBUILD_CHECK, NULL, NULL, test)))
307                 goto exit;
308
309         if ((what & RPMBUILD_PACKAGESOURCE) &&
310             (rc = processSourceFiles(spec)))
311                 goto exit;
312
313         if (((what & RPMBUILD_INSTALL) || (what & RPMBUILD_PACKAGEBINARY) ||
314             (what & RPMBUILD_FILECHECK)) &&
315             (rc = processBinaryFiles(spec, what & RPMBUILD_INSTALL, test)))
316                 goto exit;
317
318         if (((what & RPMBUILD_PACKAGESOURCE) && !test) &&
319             (rc = packageSources(spec)))
320                 return rc;
321
322         if (((what & RPMBUILD_PACKAGEBINARY) && !test) &&
323             (rc = packageBinaries(spec)))
324                 goto exit;
325         
326         if ((what & RPMBUILD_CLEAN) &&
327             (rc = doScript(spec, RPMBUILD_CLEAN, NULL, NULL, test)))
328                 goto exit;
329
330         if ((what & RPMBUILD_RMBUILD) &&
331             (rc = doScript(spec, RPMBUILD_RMBUILD, NULL, NULL, test)))
332                 goto exit;
333     }
334
335     if (what & RPMBUILD_RMSOURCE)
336         doRmSource(spec);
337
338     if (what & RPMBUILD_RMSPEC)
339         (void) Unlink(spec->specFile);
340
341 exit:
342     if (rc && rpmlogGetNrecs() > 0) {
343         rpmMessage(RPMMESS_NORMAL, _("\n\nRPM build errors:\n"));
344         rpmlogPrint(NULL);
345     }
346
347     return rc;
348 }