Realize the remaining bits of direct rpmdb interface are dead too
[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 <rpm/rpmbuild.h>
9 #include <rpm/rpmlog.h>
10 #include <rpm/rpmfileutil.h>
11
12 #include "debug.h"
13
14 static int _build_debug = 0;
15
16 /**
17  */
18 rpmRC doRmSource(rpmSpec spec)
19 {
20     struct Source *p;
21     Package pkg;
22     int rc = 0;
23     
24     for (p = spec->sources; p != NULL; p = p->next) {
25         if (! (p->flags & RPMBUILD_ISNO)) {
26             char *fn = rpmGetPath("%{_sourcedir}/", p->source, NULL);
27             rc = unlink(fn);
28             fn = _free(fn);
29             if (rc) goto exit;
30         }
31     }
32
33     for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
34         for (p = pkg->icon; p != NULL; p = p->next) {
35             if (! (p->flags & RPMBUILD_ISNO)) {
36                 char *fn = rpmGetPath("%{_sourcedir}/", p->source, NULL);
37                 rc = unlink(fn);
38                 fn = _free(fn);
39                 if (rc) goto exit;
40             }
41         }
42     }
43 exit:
44     return !rc ? RPMRC_OK : RPMRC_FAIL;
45 }
46
47 /*
48  * @todo Single use by %%doc in files.c prevents static.
49  */
50 rpmRC doScript(rpmSpec spec, rpmBuildFlags what, const char *name, StringBuf sb, int test)
51 {
52     const char * rootDir = spec->rootDir;
53     char *scriptName = NULL;
54     char * buildDir = rpmGenPath(rootDir, "%{_builddir}", "");
55     char * buildCmd = NULL;
56     char * buildTemplate = NULL;
57     char * buildPost = NULL;
58     const char * mTemplate = NULL;
59     const char * mCmd = NULL;
60     const char * mPost = NULL;
61     int argc = 0;
62     const char **argv = NULL;
63     FILE * fp = NULL;
64
65     FD_t fd;
66     FD_t xfd;
67     pid_t pid;
68     pid_t child;
69     int status;
70     rpmRC rc;
71     
72     switch (what) {
73     case RPMBUILD_PREP:
74         name = "%prep";
75         sb = spec->prep;
76         mTemplate = "%{__spec_prep_template}";
77         mPost = "%{__spec_prep_post}";
78         mCmd = "%{__spec_prep_cmd}";
79         break;
80     case RPMBUILD_BUILD:
81         name = "%build";
82         sb = spec->build;
83         mTemplate = "%{__spec_build_template}";
84         mPost = "%{__spec_build_post}";
85         mCmd = "%{__spec_build_cmd}";
86         break;
87     case RPMBUILD_INSTALL:
88         name = "%install";
89         sb = spec->install;
90         mTemplate = "%{__spec_install_template}";
91         mPost = "%{__spec_install_post}";
92         mCmd = "%{__spec_install_cmd}";
93         break;
94     case RPMBUILD_CHECK:
95         name = "%check";
96         sb = spec->check;
97         mTemplate = "%{__spec_check_template}";
98         mPost = "%{__spec_check_post}";
99         mCmd = "%{__spec_check_cmd}";
100         break;
101     case RPMBUILD_CLEAN:
102         name = "%clean";
103         sb = spec->clean;
104         mTemplate = "%{__spec_clean_template}";
105         mPost = "%{__spec_clean_post}";
106         mCmd = "%{__spec_clean_cmd}";
107         break;
108     case RPMBUILD_RMBUILD:
109         name = "--clean";
110         mTemplate = "%{__spec_clean_template}";
111         mPost = "%{__spec_clean_post}";
112         mCmd = "%{__spec_clean_cmd}";
113         break;
114     case RPMBUILD_STRINGBUF:
115     default:
116         mTemplate = "%{___build_template}";
117         mPost = "%{___build_post}";
118         mCmd = "%{___build_cmd}";
119         break;
120     }
121     if (name == NULL)   /* XXX shouldn't happen */
122         name = "???";
123
124     if ((what != RPMBUILD_RMBUILD) && sb == NULL) {
125         rc = RPMRC_OK;
126         goto exit;
127     }
128     
129     fd = rpmMkTempFile(rootDir, &scriptName);
130     if (fd == NULL || Ferror(fd)) {
131         rpmlog(RPMLOG_ERR, _("Unable to open temp file.\n"));
132         rc = RPMRC_FAIL;
133         goto exit;
134     }
135
136     if (fdGetFILE(fd) == NULL)
137         xfd = Fdopen(fd, "w.fpio");
138     else
139         xfd = fd;
140
141     if ((fp = fdGetFILE(xfd)) == NULL) {
142         rc = RPMRC_FAIL;
143         goto exit;
144     }
145     
146     if (*rootDir == '\0') rootDir = "/";
147
148     buildTemplate = rpmExpand(mTemplate, NULL);
149     buildPost = rpmExpand(mPost, NULL);
150
151     (void) fputs(buildTemplate, fp);
152
153     if (what != RPMBUILD_PREP && what != RPMBUILD_RMBUILD && spec->buildSubdir)
154         fprintf(fp, "cd '%s'\n", spec->buildSubdir);
155
156     if (what == RPMBUILD_RMBUILD) {
157         if (spec->buildSubdir)
158             fprintf(fp, "rm -rf '%s'\n", spec->buildSubdir);
159     } else if (sb != NULL)
160         fprintf(fp, "%s", getStringBuf(sb));
161
162     (void) fputs(buildPost, fp);
163     
164     (void) Fclose(xfd);
165
166     if (test) {
167         rc = RPMRC_OK;
168         goto exit;
169     }
170     
171 if (_build_debug)
172 fprintf(stderr, "*** rootDir %s buildDir %s\n", rootDir, buildDir);
173     if (buildDir && buildDir[0] != '/') {
174         rc = RPMRC_FAIL;
175         goto exit;
176     }
177
178     buildCmd = rpmExpand(mCmd, " ", scriptName, NULL);
179     (void) poptParseArgvString(buildCmd, &argc, &argv);
180
181     rpmlog(RPMLOG_NOTICE, _("Executing(%s): %s\n"), name, buildCmd);
182     if (!(child = fork())) {
183
184         errno = 0;
185         (void) execvp(argv[0], (char *const *)argv);
186
187         rpmlog(RPMLOG_ERR, _("Exec of %s failed (%s): %s\n"),
188                 scriptName, name, strerror(errno));
189
190         _exit(127); /* exit 127 for compatibility with bash(1) */
191     }
192
193     pid = waitpid(child, &status, 0);
194
195     if (!WIFEXITED(status) || WEXITSTATUS(status)) {
196         rpmlog(RPMLOG_ERR, _("Bad exit status from %s (%s)\n"),
197                  scriptName, name);
198         rc = RPMRC_FAIL;
199     } else
200         rc = RPMRC_OK;
201     
202 exit:
203     if (scriptName) {
204         if (rc == RPMRC_OK)
205             (void) unlink(scriptName);
206         scriptName = _free(scriptName);
207     }
208     argv = _free(argv);
209     buildCmd = _free(buildCmd);
210     buildTemplate = _free(buildTemplate);
211     buildPost = _free(buildPost);
212     buildDir = _free(buildDir);
213
214     return rc;
215 }
216
217 rpmRC buildSpec(rpmts ts, rpmSpec spec, int what, int test)
218 {
219     rpmRC rc = RPMRC_OK;
220
221     if (!spec->recursing && spec->BACount) {
222         int x;
223         /* When iterating over BANames, do the source    */
224         /* packaging on the first run, and skip RMSOURCE altogether */
225         if (spec->BASpecs != NULL)
226         for (x = 0; x < spec->BACount; x++) {
227             if ((rc = buildSpec(ts, spec->BASpecs[x],
228                                 (what & ~RPMBUILD_RMSOURCE) |
229                                 (x ? 0 : (what & RPMBUILD_PACKAGESOURCE)),
230                                 test))) {
231                 goto exit;
232             }
233         }
234     } else {
235         if ((what & RPMBUILD_PREP) &&
236             (rc = doScript(spec, RPMBUILD_PREP, NULL, NULL, test)))
237                 goto exit;
238
239         if ((what & RPMBUILD_BUILD) &&
240             (rc = doScript(spec, RPMBUILD_BUILD, NULL, NULL, test)))
241                 goto exit;
242
243         if ((what & RPMBUILD_INSTALL) &&
244             (rc = doScript(spec, RPMBUILD_INSTALL, NULL, NULL, test)))
245                 goto exit;
246
247         if ((what & RPMBUILD_CHECK) &&
248             (rc = doScript(spec, RPMBUILD_CHECK, NULL, NULL, test)))
249                 goto exit;
250
251         if ((what & RPMBUILD_PACKAGESOURCE) &&
252             (rc = processSourceFiles(spec)))
253                 goto exit;
254
255         if (((what & RPMBUILD_INSTALL) || (what & RPMBUILD_PACKAGEBINARY) ||
256             (what & RPMBUILD_FILECHECK)) &&
257             (rc = processBinaryFiles(spec, what & RPMBUILD_INSTALL, test)))
258                 goto exit;
259
260         if (((what & RPMBUILD_PACKAGESOURCE) && !test) &&
261             (rc = packageSources(spec)))
262                 return rc;
263
264         if (((what & RPMBUILD_PACKAGEBINARY) && !test) &&
265             (rc = packageBinaries(spec)))
266                 goto exit;
267         
268         if ((what & RPMBUILD_CLEAN) &&
269             (rc = doScript(spec, RPMBUILD_CLEAN, NULL, NULL, test)))
270                 goto exit;
271
272         if ((what & RPMBUILD_RMBUILD) &&
273             (rc = doScript(spec, RPMBUILD_RMBUILD, NULL, NULL, test)))
274                 goto exit;
275     }
276
277     if (what & RPMBUILD_RMSOURCE)
278         doRmSource(spec);
279
280     if (what & RPMBUILD_RMSPEC)
281         (void) unlink(spec->specFile);
282
283 exit:
284     if (rc != RPMRC_OK && rpmlogGetNrecs() > 0) {
285         rpmlog(RPMLOG_NOTICE, _("\n\nRPM build errors:\n"));
286         rpmlogPrint(NULL);
287     }
288
289     return rc;
290 }