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