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