• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

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 }

Generated on Mon Nov 29 2010 05:18:41 for rpm by  doxygen 1.7.2