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

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