- Main Page
- Related Pages
- Modules
- Data Structures
- Files

# build/build.c

Go to the documentation of this file.

    00001
    00006 #include "system.h"
    00007
    00008 #include <rpmio_internal.h>     /* XXX fdGetFp */
    00009 #define _RPMTAG_INTERNAL
    00010 #include <rpmbuild.h>
    00011 #include "signature.h"          /* XXX rpmTempFile */
    00012
    00013 #include "debug.h"
    00014
    00015 /*@unchecked@*/
    00016 static int _build_debug = 0;
    00017
    00020 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
    00021 const char * getSourceDir(rpmfileAttrs attr, const char *filename)
    00022 #else
    00023 const char * getSourceDir(rpmfileAttrs attr)
    00024 #endif
    00025 {
    00026     const char * dir = NULL;
    00027 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
    00028     const char *fn;
    00029
    00030     /*  support splitted source directories, i.e., source files which
    00031         are alternatively placed into the .spec directory and picked
    00032         up from there, too. */
    00033     if (attr & (RPMFILE_SOURCE|RPMFILE_PATCH|RPMFILE_ICON) && filename != NULL)
    00034     {
    00035         fn = rpmGetPath("%{_specdir}/", filename, NULL);
    00036         if (access(fn, F_OK) == 0)
    00037                 dir = "%{_specdir}/";
    00038         fn = _free(fn);
    00039     }
    00040     if (dir != NULL) {
    00041     } else
    00042 #endif
    00043     if (attr & RPMFILE_SOURCE)
    00044         dir = "%{_sourcedir}/";
    00045     else if (attr & RPMFILE_PATCH)
    00046         dir = "%{_patchdir}/";
    00047     else if (attr & RPMFILE_ICON)
    00048         dir = "%{_icondir}/";
    00049
    00050     return dir;
    00051 }
    00052
    00053 /*@access StringBuf @*/
    00054 /*@access urlinfo @*/           /* XXX compared with NULL */
    00055 /*@access FD_t @*/
    00056
    00059 static void doRmSource(Spec spec)
    00060         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
    00061         /*@modifies rpmGlobalMacroContext, fileSystem, internalState  @*/
    00062 {
    00063     struct Source *sp;
    00064     int rc;
    00065
    00066 #if 0
    00067     rc = Unlink(spec->specFile);
    00068 #endif
    00069
    00070     for (sp = spec->sources; sp != NULL; sp = sp->next) {
    00071         const char *dn, *fn;
    00072     if (sp->flags & RPMFILE_GHOST)
    00073         continue;
    00074 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
    00075     if (! (dn = getSourceDir(sp->flags, sp->source)))
    00076 #else
    00077     if (! (dn = getSourceDir(sp->flags)))
    00078 #endif
    00079         continue;
    00080         fn = rpmGenPath(NULL, dn, sp->source);
    00081         rc = Unlink(fn);
    00082         fn = _free(fn);
    00083     }
    00084 }
    00085
    00086 /*
    00087  * @todo Single use by %%doc in files.c prevents static.
    00088  */
    00089 rpmRC doScript(Spec spec, int what, const char *name, StringBuf sb, int test)
    00090 {
    00091     const char * rootURL = spec->rootURL;
    00092     const char * rootDir;
    00093     const char *scriptName = NULL;
    00094     const char * buildDirURL = rpmGenPath(rootURL, "%{_builddir}", "");
    00095     const char * buildScript;
    00096     const char * buildCmd = NULL;
    00097     const char * buildTemplate = NULL;
    00098     const char * buildPost = NULL;
    00099     const char * mTemplate = NULL;
    00100     const char * mCmd = NULL;
    00101     const char * mPost = NULL;
    00102     int argc = 0;
    00103     const char **argv = NULL;
    00104     FILE * fp = NULL;
    00105     urlinfo u = NULL;
    00106
    00107     FD_t fd;
    00108     FD_t xfd;
    00109     pid_t pid;
    00110     pid_t child;
    00111     int status;
    00112     rpmRC rc;
    00113     int i;
    00114
    00115     switch (what) {
    00116     case RPMBUILD_PREP:
    00117         name = "%prep";
    00118         sb = spec->prep;
    00119         mTemplate = "%{__spec_prep_template}";
    00120         mPost = "%{__spec_prep_post}";
    00121         mCmd = "%{__spec_prep_cmd}";
    00122         break;
    00123     case RPMBUILD_BUILD:
    00124         name = "%build";
    00125         sb = spec->build;
    00126         mTemplate = "%{__spec_build_template}";
    00127         mPost = "%{__spec_build_post}";
    00128         mCmd = "%{__spec_build_cmd}";
    00129         break;
    00130     case RPMBUILD_INSTALL:
    00131         name = "%install";
    00132         sb = spec->install;
    00133         mTemplate = "%{__spec_install_template}";
    00134         mPost = "%{__spec_install_post}";
    00135         mCmd = "%{__spec_install_cmd}";
    00136         break;
    00137     case RPMBUILD_CHECK:
    00138         name = "%check";
    00139         sb = spec->check;
    00140         mTemplate = "%{__spec_check_template}";
    00141         mPost = "%{__spec_check_post}";
    00142         mCmd = "%{__spec_check_cmd}";
    00143         break;
    00144     case RPMBUILD_CLEAN:
    00145         name = "%clean";
    00146         sb = spec->clean;
    00147         mTemplate = "%{__spec_clean_template}";
    00148         mPost = "%{__spec_clean_post}";
    00149         mCmd = "%{__spec_clean_cmd}";
    00150         break;
    00151     case RPMBUILD_RMBUILD:
    00152         name = "--clean";
    00153         mTemplate = "%{__spec_clean_template}";
    00154         mPost = "%{__spec_clean_post}";
    00155         mCmd = "%{__spec_clean_cmd}";
    00156         break;
    00157     /* support "%track" script/section */
    00158     case RPMBUILD_TRACK:
    00159         name = "%track";
    00160         sb = NULL;
    00161         if (spec->foo)
    00162         for (i = 0; i < spec->nfoo; i++) {
    00163             if (spec->foo[i].str == NULL || spec->foo[i].val == NULL)
    00164                 continue;
    00165             if (xstrcasecmp(spec->foo[i].str, "track"))
    00166                 continue;
    00167             sb = spec->foo[i].val;
    00168             break;
    00169         }
    00170         mTemplate = "%{__spec_track_template}";
    00171         mPost = "%{__spec_track_post}";
    00172         mCmd = "%{__spec_track_cmd}";
    00173         break;
    00174     case RPMBUILD_STRINGBUF:
    00175     default:
    00176         mTemplate = "%{___build_template}";
    00177         mPost = "%{___build_post}";
    00178         mCmd = "%{___build_cmd}";
    00179         break;
    00180     }
    00181     if (name == NULL)   /* XXX shouldn't happen */
    00182         name = "???";
    00183
    00184     if ((what != RPMBUILD_RMBUILD) && sb == NULL) {
    00185         rc = RPMRC_OK;
    00186         goto exit;
    00187     }
    00188
    00189     if (rpmTempFile(rootURL, &scriptName, &fd) || fd == NULL || Ferror(fd)) {
    00190         rpmlog(RPMLOG_ERR, _("Unable to open temp file.\n"));
    00191         rc = RPMRC_FAIL;
    00192         goto exit;
    00193     }
    00194
    00195     if (fdGetFp(fd) == NULL)
    00196         xfd = Fdopen(fd, "w.fpio");
    00197     else
    00198         xfd = fd;
    00199
    00200     /*@-type@*/ /* FIX: cast? */
    00201     if ((fp = fdGetFp(xfd)) == NULL) {
    00202         rc = RPMRC_FAIL;
    00203         goto exit;
    00204     }
    00205     /*@=type@*/
    00206
    00207     (void) urlPath(rootURL, &rootDir);
    00208     if (*rootDir == '\0') rootDir = "/";
    00209
    00210     (void) urlPath(scriptName, &buildScript);
    00211
    00212     buildTemplate = rpmExpand(mTemplate, NULL);
    00213     buildPost = rpmExpand(mPost, NULL);
    00214
    00215     (void) fputs(buildTemplate, fp);
    00216
    00217     /* support "%track" script/section */
    00218     if (what != RPMBUILD_PREP && what != RPMBUILD_RMBUILD && spec->buildSubdir && what != RPMBUILD_TRACK)
    00219         fprintf(fp, "cd '%s'\n", spec->buildSubdir);
    00220
    00221     if (what == RPMBUILD_RMBUILD) {
    00222         if (spec->buildSubdir)
    00223             fprintf(fp, "rm -rf '%s'\n", spec->buildSubdir);
    00224     } else if (sb != NULL)
    00225         fprintf(fp, "%s", getStringBuf(sb));
    00226
    00227     (void) fputs(buildPost, fp);
    00228
    00229     (void) Fclose(xfd);
    00230
    00231     if (test) {
    00232         rc = RPMRC_OK;
    00233         goto exit;
    00234     }
    00235
    00236 if (_build_debug)
    00237 fprintf(stderr, "*** rootURL %s buildDirURL %s\n", rootURL, buildDirURL);
    00238     if (buildDirURL && buildDirURL[0] != '/' &&
    00239         (urlSplit(buildDirURL, &u) != 0)) {
    00240         rc = RPMRC_FAIL;
    00241         goto exit;
    00242     }
    00243     if (u != NULL) {
    00244         switch (u->urltype) {
    00245         case URL_IS_HTTPS:
    00246         case URL_IS_HTTP:
    00247         case URL_IS_FTP:
    00248 if (_build_debug)
    00249 fprintf(stderr, "*** addMacros\n");
    00250             addMacro(spec->macros, "_remsh", NULL, "%{__remsh}", RMIL_SPEC);
    00251             addMacro(spec->macros, "_remhost", NULL, u->host, RMIL_SPEC);
    00252             if (strcmp(rootDir, "/"))
    00253                 addMacro(spec->macros, "_remroot", NULL, rootDir, RMIL_SPEC);
    00254             break;
    00255         case URL_IS_UNKNOWN:
    00256         case URL_IS_DASH:
    00257         case URL_IS_PATH:
    00258         case URL_IS_HKP:
    00259         default:
    00260             break;
    00261         }
    00262     }
    00263
    00264     buildCmd = rpmExpand(mCmd, " ", buildScript, NULL);
    00265     (void) poptParseArgvString(buildCmd, &argc, &argv);
    00266
    00267     if (what != RPMBUILD_TRACK)         /* support "%track" script/section */
    00268         rpmlog(RPMLOG_NOTICE, _("Executing(%s): %s\n"), name, buildCmd);
    00269     if (!(child = fork())) {
    00270
    00271         /*@-mods@*/
    00272         errno = 0;
    00273         /*@=mods@*/
    00274         (void) execvp(argv[0], (char *const *)argv);
    00275
    00276         rpmlog(RPMLOG_ERR, _("Exec of %s failed (%s): %s\n"),
    00277                 scriptName, name, strerror(errno));
    00278
    00279         _exit(-1);
    00280     }
    00281
    00282     pid = waitpid(child, &status, 0);
    00283
    00284     if (!WIFEXITED(status) || WEXITSTATUS(status)) {
    00285         rpmlog(RPMLOG_ERR, _("Bad exit status from %s (%s)\n"),
    00286                  scriptName, name);
    00287         rc = RPMRC_FAIL;
    00288     } else
    00289         rc = RPMRC_OK;
    00290
    00291 exit:
    00292     if (scriptName) {
    00293 #if defined(RPM_VENDOR_OPENPKG) /* always-remove-tempfiles */
    00294         /* Unconditionally remove temporary files ("rpm-tmp.XXXXX") which
    00295            were generated for the executed scripts. In OpenPKG we run the
    00296            scripts in debug mode ("set -x") anyway, so we never need to
    00297            see the whole generated script -- not even if it breaks.  Instead
    00298            we would just have temporary files staying around forever. */
    00299 #else
    00300         if (rc == RPMRC_OK)
    00301 #endif
    00302             (void) Unlink(scriptName);
    00303         scriptName = _free(scriptName);
    00304     }
    00305     if (u != NULL) {
    00306         switch (u->urltype) {
    00307         case URL_IS_HTTPS:
    00308         case URL_IS_HTTP:
    00309         case URL_IS_FTP:
    00310 if (_build_debug)
    00311 fprintf(stderr, "*** delMacros\n");
    00312             delMacro(spec->macros, "_remsh");
    00313             delMacro(spec->macros, "_remhost");
    00314             if (strcmp(rootDir, "/"))
    00315                 delMacro(spec->macros, "_remroot");
    00316             break;
    00317         case URL_IS_UNKNOWN:
    00318         case URL_IS_DASH:
    00319         case URL_IS_PATH:
    00320         case URL_IS_HKP:
    00321         default:
    00322             break;
    00323         }
    00324     }
    00325     argv = _free(argv);
    00326     buildCmd = _free(buildCmd);
    00327     buildTemplate = _free(buildTemplate);
    00328     buildPost = _free(buildPost);
    00329     buildDirURL = _free(buildDirURL);
    00330
    00331     return rc;
    00332 }
    00333
    00334 rpmRC buildSpec(rpmts ts, Spec spec, int what, int test)
    00335 {
    00336     rpmRC rc = RPMRC_OK;
    00337
    00338     if (!spec->recursing && spec->BACount) {
    00339         int x;
    00340         /* When iterating over BANames, do the source    */
    00341         /* packaging on the first run, and skip RMSOURCE altogether */
    00342         if (spec->BASpecs != NULL)
    00343         for (x = 0; x < spec->BACount; x++) {
    00344             if ((rc = buildSpec(ts, spec->BASpecs[x],
    00345                                 (what & ~RPMBUILD_RMSOURCE) |
    00346                                 (x ? 0 : (what & RPMBUILD_PACKAGESOURCE)),
    00347                                 test))) {
    00348                 goto exit;
    00349             }
    00350         }
    00351     } else {
    00352         /* support "%track" script/section */
    00353         if ((what & RPMBUILD_TRACK) &&
    00354             (rc = doScript(spec, RPMBUILD_TRACK, NULL, NULL, test)))
    00355                 goto exit;
    00356
    00357         if ((what & RPMBUILD_PREP) &&
    00358             (rc = doScript(spec, RPMBUILD_PREP, NULL, NULL, test)))
    00359                 goto exit;
    00360
    00361         if ((what & RPMBUILD_BUILD) &&
    00362             (rc = doScript(spec, RPMBUILD_BUILD, NULL, NULL, test)))
    00363                 goto exit;
    00364
    00365         if ((what & RPMBUILD_INSTALL) &&
    00366             (rc = doScript(spec, RPMBUILD_INSTALL, NULL, NULL, test)))
    00367                 goto exit;
    00368
    00369         if ((what & RPMBUILD_CHECK) &&
    00370             (rc = doScript(spec, RPMBUILD_CHECK, NULL, NULL, test)))
    00371                 goto exit;
    00372
    00373         if ((what & RPMBUILD_PACKAGESOURCE) &&
    00374             (rc = processSourceFiles(spec)))
    00375                 goto exit;
    00376
    00377         if (((what & RPMBUILD_INSTALL) || (what & RPMBUILD_PACKAGEBINARY) ||
    00378             (what & RPMBUILD_FILECHECK)) &&
    00379             (rc = processBinaryFiles(spec, what & RPMBUILD_INSTALL, test)))
    00380                 goto exit;
    00381
    00382         if (((what & RPMBUILD_PACKAGESOURCE) && !test) &&
    00383             (rc = packageSources(spec)))
    00384                 return rc;
    00385
    00386         if (((what & RPMBUILD_PACKAGEBINARY) && !test) &&
    00387             (rc = packageBinaries(spec)))
    00388                 goto exit;
    00389
    00390         if ((what & RPMBUILD_CLEAN) &&
    00391             (rc = doScript(spec, RPMBUILD_CLEAN, NULL, NULL, test)))
    00392                 goto exit;
    00393
    00394         if ((what & RPMBUILD_RMBUILD) &&
    00395             (rc = doScript(spec, RPMBUILD_RMBUILD, NULL, NULL, test)))
    00396                 goto exit;
    00397     }
    00398
    00399     if (what & RPMBUILD_RMSOURCE)
    00400         doRmSource(spec);
    00401
    00402     if (what & RPMBUILD_RMSPEC)
    00403         (void) Unlink(spec->specFile);
    00404
    00405 #if defined(RPM_VENDOR_OPENPKG) /* auto-remove-source-directories */
    00406     /* In OpenPKG we use per-package %{_sourcedir} and %{_specdir}
    00407        definitions (macros have trailing ".../%{name}"). On removal of
    00408        source(s) and .spec file, this per-package directory would be kept
    00409        (usually <prefix>/RPM/SRC/<name>/), because RPM does not know about
    00410        this OpenPKG convention. So, let RPM try(!) to remove the two
    00411        directories (if they are empty) and just ignore removal failures
    00412        (if they are still not empty). */
    00413     if (what & RPMBUILD_RMSOURCE) {
    00414         const char *pn;
    00415         pn = rpmGetPath("%{_sourcedir}", NULL);
    00416         Rmdir(pn); /* ignore error, it is ok if it fails (usually with ENOTEMPTY) */
    00417         pn = _free(pn);
    00418     }
    00419     if (what & RPMBUILD_RMSPEC) {
    00420         const char *pn;
    00421         pn = rpmGetPath("%{_specdir}", NULL);
    00422         Rmdir(pn); /* ignore error, it is ok if it fails (usually with ENOTEMPTY) */
    00423         pn = _free(pn);
    00424     }
    00425 #endif
    00426
    00427 exit:
    00428     if (rc != RPMRC_OK && rpmlogGetNrecs() > 0) {
    00429         rpmlog(RPMLOG_NOTICE, _("\n\nRPM build errors:\n"));
    00430         rpmlogPrint(NULL);
    00431     }
    00432
    00433     return rc;
    00434 }