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