2 * Parses RPM spec file into Makefile fragment. See
4 * http://fedora.redhat.com/docs/drafts/rpm-guide-en/ch-programming-c.html
6 * Mark Huang <mlhuang@cs.princeton.edu>
7 * Copyright (C) 2006 The Trustees of Princeton University
17 #include <rpm/rpmlib.h>
18 #include <rpm/rpmts.h>
19 #include <rpm/rpmcli.h>
20 #include <rpm/rpmbuild.h>
21 #include <rpm/rpmspec.h>
23 extern size_t strnlen(const char *s, size_t maxlen);
25 /* the structure describing the options we take and the defaults */
26 static struct poptOption optionsTable[] = {
27 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
28 "Common options for all rpm modes and executables:",
36 /* Stolen from rpm/build/spec.c:rpmspecQuery() */
38 rpmspecGet(rpmts ts, const char * arg)
40 char * buildRoot = NULL;
42 char * passPhrase = "";
47 if (parseSpec(ts, arg, "/", buildRoot, recursing, passPhrase,
48 cookie, anyarch, force)) {
49 fprintf(stderr, "query of specfile %s failed, can't parse\n", arg);
57 main(int argc, char *argv[])
63 struct Source *source;
65 const char *name, *version, *release, *arch, *unused;
66 const char *package_name;
68 /* BEGIN: support to pull out --target from the args list */
72 int tlen = strlen("--target");
75 /* walk argv list looking for --target */
76 while ((args+1)<argc) {
77 if(strncmp(argv[args],"--target",tlen)==0){
80 /* get arch component of the --target option */
81 dash = (char**)strchr(argv[args+1],'-');
82 if (dash != NULL) *dash=NULL;
84 /* copy arch component of --target option to target */
85 alen = strnlen(argv[args+1],32);
86 target = (char*)malloc(alen+1);
87 if (target == NULL) return errno;
88 strncpy(target,argv[args+1],alen);
91 /* change argc, argv to take out the "--target xxx" */
92 for (i=args;i<argc;i++) argv[i]=argv[i+2];
100 argv[2]=argv[argc-1];
103 /* END: support to pull out --target from the args list */
105 /* Parse common options for all rpm modes and executables */
106 context = rpmcliInit(argc, argv, optionsTable);
108 /* Create transaction state */
111 /* Parse spec file. The rpmcli functions don't allow you to
112 * access the Spec structure directly, so we call our own
113 * version of rpmSpecQuery() directly. */
114 spec = rpmspecGet(ts, argv[1]);
115 package_name = argv[2];
122 for (source = spec->sources; source; source = source->next) {
123 char fullSource[PATH_MAX];
125 strncpy(fullSource, source->fullSource, sizeof(fullSource));
126 printf("%s.tarballs += SOURCES/%s\n", package_name, basename(fullSource));
127 /* computes the SOURCEDIR variable by removing .tar.gz or .tar.bz2 */
129 char *suffixes[] = {".tar.gz",".tgz",".tar.bz2", NULL};
133 for (suffix=suffixes ; *suffix ; suffix++) {
134 printf("# trying %s\n",*suffix);
135 suffix_index=strstr(fullSource,*suffix);
137 char sourcename[PATH_MAX];
138 size_t len = (size_t)(suffix_index-fullSource);
139 strncpy(sourcename,fullSource,len);
140 sourcename[len]='\0';
141 printf ("%s.source := SOURCES/%s\n",package_name,basename(sourcename));
142 printf ("%s.codebase := CODEBASES/%s\n",package_name,package_name);
150 /* Get SRPM name from name of first package */
151 pkg = spec->packages;
152 name = version = release = NULL;
153 (void) headerNVR(pkg->header, &name, &version, &release);
154 if (name && version && release)
155 printf("%s.srpm := SRPMS/%s-%s-%s.src.rpm\n",
156 package_name, name, version, release);
158 /* Print non-empty packages */
159 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
160 name = version = release = arch = NULL;
161 (void) headerNEVRA(pkg->header, &name, &unused, &version, &release, &arch);
162 if (name && version && release && arch) {
163 if (target != NULL) {
164 if (strcmp(arch,target)!=0) {
168 /* skip empty packages */
170 /* attach (add) rpm path to package */
171 printf("%s.rpms += RPMS/%s/%s-%s-%s.%s.rpm\n",
172 package_name, arch, name, version, release, arch);
174 printf("%s.rpmnames += %s\n",
176 /* attach path to rpm name */
177 printf("%s.rpm-path := RPMS/%s/%s-%s-%s.%s.rpm\n",
178 name,arch, name, version, release, arch);
179 /* attach package to rpm name for backward resolution - should be unique */
180 printf("%s.package := %s\n",
186 /* export some macros to make */
188 char *macros[] = { "release" , "name" , "version" , "subversion" , NULL } ;
190 char *macro=malloc(32);
191 for (nav=macros; *nav; nav++) {
192 sprintf(macro,"%%{%s}",*nav);
193 char *value = rpmExpand(macro,NULL);
194 printf ("%s.rpm-%s := %s\n",package_name,*nav,value);
199 printf ("%s.rpm-arch := %s\n",package_name,target);
201 spec = freeSpec(spec);
205 context = rpmcliFini(context);