source: trunk/third/pkgconfig/main.c @ 17209

Revision 17209, 14.2 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17208, which included commits to RCS files with non-trunk default branches.
Line 
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include "pkg.h"
6#include "parse.h"
7
8#include "popt.h"
9#include <stdlib.h>
10#include <string.h>
11#include <ctype.h>
12#include <stdio.h>
13
14#ifdef G_OS_WIN32
15#define STRICT
16#include <windows.h>
17#undef STRICT
18#endif
19
20static int want_debug_spew = 0;
21static int want_verbose_errors = 0;
22static int want_stdout_errors = 0;
23
24void
25debug_spew (const char *format, ...)
26{
27  va_list args;
28  gchar *str;
29  FILE* stream;
30 
31  g_return_if_fail (format != NULL);
32 
33  if (!want_debug_spew)
34    return;
35 
36  va_start (args, format);
37  str = g_strdup_vprintf (format, args);
38  va_end (args);
39
40  if (want_stdout_errors)
41    stream = stdout;
42  else
43    stream = stderr;
44 
45  fputs (str, stream);
46  fflush (stream);
47 
48  g_free (str);
49}
50
51void
52verbose_error (const char *format, ...)
53{
54  va_list args;
55  gchar *str;
56
57  g_return_if_fail (format != NULL);
58 
59  if (!want_verbose_errors)
60    return;
61 
62  va_start (args, format);
63  str = g_strdup_vprintf (format, args);
64  va_end (args);
65
66  fputs (str, stderr);
67  fflush (stdout);
68 
69  g_free (str);
70}
71
72#define DEFINE_VARIABLE 1
73
74static void
75popt_callback (poptContext con,
76               enum poptCallbackReason reason,
77               const struct poptOption * opt,
78               const char * arg, void * data)
79{
80  debug_spew ("Option --%s seen\n", opt->longName);
81 
82  if (opt->val == DEFINE_VARIABLE)
83    {
84      char *varname;
85      char *varval;
86      char *tmp;
87
88      tmp = g_strdup (arg);
89
90      varname = tmp;
91      while (*varname && isspace ((guchar)*varname))
92        ++varname;
93
94      varval = varname;
95      while (*varval && *varval != '=' && *varval != ' ')
96        ++varval;
97
98      while (*varval && (*varval == '=' || *varval == ' '))
99        {
100          *varval = '\0';
101          ++varval;
102        }
103
104      if (*varval == '\0')
105        {
106          fprintf (stderr, "--define-variable argument does not have a value for the variable\n");
107
108          exit (1);
109        }
110
111      define_global_variable (varname, varval);
112
113      g_free (tmp);
114    }
115}
116
117static gboolean
118pkg_uninstalled (Package *pkg)
119{
120  /* See if > 0 pkgs were uninstalled */
121  GSList *tmp;
122
123  if (pkg->uninstalled)
124    return TRUE;
125 
126  tmp = pkg->requires;
127  while (tmp != NULL)
128    {
129      Package *pkg = tmp->data;
130     
131      if (pkg_uninstalled (pkg))
132        return TRUE;
133     
134      tmp = g_slist_next (tmp);
135    }
136
137  return FALSE;
138}
139
140int
141main (int argc, char **argv)
142{
143  static int want_my_version = 0;
144  static int want_version = 0;
145  static int want_libs = 0;
146  static int want_cflags = 0;
147  static int want_l_libs = 0;
148  static int want_L_libs = 0;
149  static int want_I_cflags = 0;
150  static int want_list = 0;
151  static int result;
152  static int want_uninstalled = 0;
153  static char *variable_name = NULL;
154  static int want_exists = 0;
155  static char *required_atleast_version = NULL;
156  static char *required_exact_version = NULL;
157  static char *required_max_version = NULL;
158  static char *required_pkgconfig_version = NULL;
159  static int want_silence_errors = 0;
160  GString *str;
161  GSList *packages = NULL;
162  char *search_path;
163  char *pcbuilddir;
164  gboolean need_newline;
165 
166  const char *pkgname;
167  Package *pkg;
168
169  poptContext opt_context;
170 
171  struct poptOption options_table[] = {
172    { NULL, 0, POPT_ARG_CALLBACK, popt_callback, 0, NULL, NULL },
173    { "version", 0, POPT_ARG_NONE, &want_my_version, 0,
174      "output version of pkg-config" },
175    { "modversion", 0, POPT_ARG_NONE, &want_version, 0,
176      "output version for package" },
177    { "atleast-pkgconfig-version", 0, POPT_ARG_STRING, &required_pkgconfig_version, 0,
178      "require given version of pkg-config", "VERSION" },
179    { "libs", 0, POPT_ARG_NONE, &want_libs, 0,
180      "output all linker flags" },
181    { "libs-only-l", 0, POPT_ARG_NONE, &want_l_libs, 0,
182      "output -l flags" },
183    { "libs-only-L", 0, POPT_ARG_NONE, &want_L_libs, 0,
184      "output -L flags" },
185    { "cflags", 0, POPT_ARG_NONE, &want_cflags, 0,
186      "output all pre-processor and compiler flags" },
187    { "cflags-only-I", 0, POPT_ARG_NONE, &want_I_cflags, 0,
188      "output -I flags" },
189    { "variable", 0, POPT_ARG_STRING, &variable_name, 0,
190      "get the value of a variable", "VARIABLENAME" },
191    { "define-variable", 0, POPT_ARG_STRING, NULL, DEFINE_VARIABLE,
192      "set the value of a variable", "VARIABLENAME=VARIABLEVALUE" },
193    { "exists", 0, POPT_ARG_NONE, &want_exists, 0,
194      "return 0 if the module(s) exist" },
195    { "uninstalled", 0, POPT_ARG_NONE, &want_uninstalled, 0,
196      "return 0 if the uninstalled version of one or more module(s) or their dependencies will be used" },
197    { "atleast-version", 0, POPT_ARG_STRING, &required_atleast_version, 0,
198      "return 0 if the module is at least version VERSION", "VERSION" },
199    { "exact-version", 0, POPT_ARG_STRING, &required_exact_version, 0,
200      "return 0 if the module is at exactly version VERSION", "VERSION" },
201    { "max-version", 0, POPT_ARG_STRING, &required_max_version, 0,
202      "return 0 if the module is at no newer than version VERSION", "VERSION" },
203    { "list-all", 0, POPT_ARG_NONE, &want_list, 0,
204      "list all known packages" },
205    { "debug", 0, POPT_ARG_NONE, &want_debug_spew, 0,
206      "show verbose debug information" },
207    { "print-errors", 0, POPT_ARG_NONE, &want_verbose_errors, 0,
208      "show verbose information about missing or conflicting packages" },
209    { "silence-errors", 0, POPT_ARG_NONE, &want_silence_errors, 0,
210      "show verbose information about missing or conflicting packages" },
211    { "errors-to-stdout", 0, POPT_ARG_NONE, &want_stdout_errors, 0,
212      "print errors from --print-errors to stdout not stderr" },
213#ifdef G_OS_WIN32
214    { "dont-define-prefix", 0, POPT_ARG_NONE, &dont_define_prefix, 0,
215      "don't try to override the value of prefix for each .pc file found with "
216      "a guesstimated value based on the location of the .pc file" },
217    { "prefix-variable", 0, POPT_ARG_STRING, &prefix_variable, 0,
218      "set the name of the variable that pkg-config automatically sets", "PREFIX" },
219    { "msvc-syntax", 0, POPT_ARG_NONE, &msvc_syntax, 0,
220      "output -l and -L flags for the Microsoft compiler (cl)" },
221#endif
222    POPT_AUTOHELP
223    { NULL, 0, 0, NULL, 0 }
224  };
225
226  /* This is here so that we get debug spew from the start,
227   * during arg parsing
228   */
229  if (getenv ("PKG_CONFIG_DEBUG_SPEW"))
230    {
231      want_debug_spew = TRUE;
232      want_verbose_errors = TRUE;
233      want_silence_errors = FALSE;
234      debug_spew ("PKG_CONFIG_DEBUG_SPEW variable enabling debug spew\n");
235    }
236 
237  search_path = getenv ("PKG_CONFIG_PATH");
238  if (search_path)
239    {
240      char **search_dirs;
241      char **iter;
242
243      search_dirs = g_strsplit (search_path, G_SEARCHPATH_SEPARATOR_S, -1);
244
245      iter = search_dirs;
246      while (*iter)
247        {
248          debug_spew ("Adding directory '%s' from PKG_CONFIG_PATH\n",
249                      *iter);
250          add_search_dir (*iter);
251
252          ++iter;
253        }
254
255      g_strfreev (search_dirs);
256    }
257
258#ifdef G_OS_WIN32
259  {
260    /* Add search directories from the Registry */
261
262    HKEY roots[] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
263    gchar *root_names[] = { "HKEY_CURRENT_USER", "HKEY_LOCAL_MACHINE" };
264    HKEY key;
265    int i;
266    gulong max_value_name_len, max_value_len;
267
268    for (i = 0; i < G_N_ELEMENTS (roots); i++)
269      {
270        key = NULL;
271        if (RegOpenKeyEx (roots[i], "Software\\" PACKAGE "\\PKG_CONFIG_PATH", 0,
272                          KEY_QUERY_VALUE, &key) == ERROR_SUCCESS &&
273            RegQueryInfoKey (key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
274                             &max_value_name_len, &max_value_len,
275                             NULL, NULL) == ERROR_SUCCESS)
276          {
277            int index = 0;
278            gchar *value_name = g_malloc (max_value_name_len + 1);
279            gchar *value = g_malloc (max_value_len + 1);
280           
281            while (TRUE)
282              {
283                gulong type;
284                gulong value_name_len = max_value_name_len + 1;
285                gulong value_len = max_value_len + 1;
286               
287                if (RegEnumValue (key, index++, value_name, &value_name_len,
288                                  NULL, &type,
289                                  value, &value_len) != ERROR_SUCCESS)
290                  break;
291               
292                if (type != REG_SZ)
293                  continue;
294
295                value_name[value_name_len] = '\0';
296                value[value_len] = '\0';
297                debug_spew ("Adding directory '%s' from %s\\Software\\"
298                            PACKAGE "\\PKG_CONFIG_PATH\\%s\n",
299                            value, root_names[i], value_name);
300                add_search_dir (value);
301              }
302          }
303        if (key != NULL)
304          RegCloseKey (key);
305      }
306  }
307#endif
308
309  pcbuilddir = getenv ("PKG_CONFIG_TOP_BUILD_DIR");
310  if (pcbuilddir)
311    {
312      define_global_variable ("pc_top_builddir", pcbuilddir);
313    }
314  else
315    {
316      /* Default appropriate for automake */
317      define_global_variable ("pc_top_builddir", "$(top_builddir)");
318    }
319
320  if (getenv ("PKG_CONFIG_DISABLE_UNINSTALLED"))
321    {
322      debug_spew ("disabling auto-preference for uninstalled packages\n");
323      disable_uninstalled = TRUE;
324    }
325 
326  opt_context = poptGetContext (NULL, argc, argv,
327                                options_table, 0);
328
329  result = poptGetNextOpt (opt_context);
330  if (result != -1)
331    {
332      fprintf(stderr, "%s: %s\n",
333              poptBadOption(opt_context, POPT_BADOPTION_NOALIAS),
334              poptStrerror(result));
335      return 1;
336    }
337
338
339  /* Error printing is determined as follows:
340   *     - for --cflags, --libs, etc. it's on by default
341   *       and --silence-errors can turn it off
342   *     - for --exists, --max-version, etc. and no options
343   *       at all, it's off by default and --print-errors
344   *       will turn it on
345   */
346
347  if (want_my_version ||
348      want_version ||
349      want_libs ||
350      want_cflags ||
351      want_l_libs ||
352      want_L_libs ||
353      want_I_cflags ||
354      want_list)
355    {
356      debug_spew ("Error printing enabled by default due to use of --version, --libs, --cflags, --libs-only-l, --libs-only-L, --cflags-only-I, or --list. Value of --silence-errors: %d\n", want_silence_errors);
357
358      if (want_silence_errors && getenv ("PKG_CONFIG_DEBUG_SPEW") == NULL)
359        want_verbose_errors = FALSE;
360      else
361        want_verbose_errors = TRUE;
362    }
363  else
364    {
365      debug_spew ("Error printing disabled by default, value of --print-errors: %d\n",
366                  want_verbose_errors);
367
368      /* Leave want_verbose_errors unchanged, reflecting --print-errors */
369    }
370 
371  if (want_verbose_errors)
372    debug_spew ("Error printing enabled\n");
373  else
374    debug_spew ("Error printing disabled\n");
375 
376  if (want_my_version)
377    {
378      printf ("%s\n", VERSION);
379      return 0;
380    }
381
382  if (required_pkgconfig_version)
383    {
384      if (compare_versions (VERSION, required_pkgconfig_version) >= 0)
385        return 0;
386      else
387        return 1;
388    }
389 
390  package_init ();
391
392  if (want_list)
393    {
394      print_package_list ();
395      return 0;
396    }
397 
398  str = g_string_new ("");
399  while (1)
400    {
401      pkgname = poptGetArg (opt_context);
402      if (pkgname == NULL)
403        break;
404
405      g_string_append (str, pkgname);
406      g_string_append (str, " ");
407    }
408
409  g_strstrip (str->str); 
410 
411  {
412    GSList *reqs;
413    GSList *iter;
414   
415    reqs = parse_module_list (NULL, str->str,
416                              "(command line arguments)");     
417   
418    iter = reqs;
419   
420    while (iter != NULL)
421      {
422        Package *req;
423        RequiredVersion *ver = iter->data;
424
425        req = get_package (ver->name);
426
427        if (req == NULL)
428          {
429            verbose_error ("No package '%s' found\n", ver->name);
430            return 1;
431          }
432
433        if (!version_test (ver->comparison, req->version, ver->version))
434          {
435            verbose_error ("Requested '%s %s %s' but version of %s is %s\n",
436                           ver->name,
437                           comparison_to_str (ver->comparison),
438                           ver->version,
439                           req->name,
440                           req->version);
441             
442            return 1;
443          }
444
445        packages = g_slist_prepend (packages, req);
446       
447        iter = g_slist_next (iter);
448      }
449  }
450
451  g_string_free (str, TRUE);
452 
453  packages = g_slist_reverse (packages);
454
455  if (packages == NULL)
456    {     
457      fprintf (stderr, "Must specify package names on the command line\n");
458     
459      exit (1);
460    }
461 
462  if (want_exists)
463    return 0; /* if we got here, all the packages existed. */
464
465  if (want_uninstalled)
466    {
467      /* See if > 0 pkgs (including dependencies recursively) were uninstalled */
468      GSList *tmp;
469      tmp = packages;
470      while (tmp != NULL)
471        {
472          Package *pkg = tmp->data;
473
474          if (pkg_uninstalled (pkg))
475            return 0;
476
477          tmp = g_slist_next (tmp);
478        }
479
480      return 1;
481    }
482 
483  if (want_version)
484    {
485      GSList *tmp;
486      tmp = packages;
487      while (tmp != NULL)
488        {
489          Package *pkg = tmp->data;
490
491          printf ("%s\n", pkg->version);
492
493          tmp = g_slist_next (tmp);
494        }
495    }
496
497  if (required_exact_version)
498    {
499      Package *pkg = packages->data;
500     
501      if (compare_versions (pkg->version, required_exact_version) == 0)
502        return 0;
503      else
504        return 1;
505    }
506  else if (required_atleast_version)
507    {
508      Package *pkg = packages->data;
509     
510      if (compare_versions (pkg->version, required_atleast_version) >= 0)
511        return 0;
512      else
513        return 1;
514    }
515  else if (required_max_version)
516    {
517      Package *pkg = packages->data;
518     
519      if (compare_versions (pkg->version, required_max_version) <= 0)
520        return 0;
521      else
522        return 1;
523    }
524 
525  /* Print all flags; then print a newline at the end. */
526  need_newline = FALSE;
527
528  if (variable_name)
529    {
530      char *str = packages_get_var (packages, variable_name);
531      printf ("%s", str);
532      g_free (str);
533      need_newline = TRUE;
534    }
535 
536  if (want_I_cflags)
537    {
538      char *str = packages_get_I_cflags (packages);
539      printf ("%s ", str);
540      g_free (str);
541      need_newline = TRUE;
542    }
543  else if (want_cflags)
544    {
545      char *str = packages_get_all_cflags (packages);
546      printf ("%s ", str);
547      g_free (str);
548      need_newline = TRUE;
549    }
550 
551  if (want_l_libs)
552    {
553      char *str = packages_get_l_libs (packages);
554      printf ("%s ", str);
555      g_free (str);
556      need_newline = TRUE;
557    }
558  else if (want_L_libs)
559    {
560      char *str = packages_get_L_libs (packages);
561      printf ("%s ", str);
562      g_free (str);
563      need_newline = TRUE;
564    }
565  else if (want_libs)
566    {
567      char *str = packages_get_all_libs (packages);
568      printf ("%s ", str);
569      g_free (str);
570      need_newline = TRUE;
571    }
572
573  if (need_newline)
574    printf ("\n");
575 
576  return 0;
577}
Note: See TracBrowser for help on using the repository browser.