]> err.no Git - pkg-config/commitdiff
2001-10-25 Tor Lillqvist <tml@iki.fi>
authorArch Librarian <arch@canonical.com>
Thu, 14 Jul 2005 13:04:37 +0000 (13:04 +0000)
committerArch Librarian <arch@canonical.com>
Thu, 14 Jul 2005 13:04:37 +0000 (13:04 +0000)
Author: tml
Date: 2001-10-24 21:22:33 GMT
2001-10-25  Tor Lillqvist  <tml@iki.fi>

Improve Windows behaviour: Make it even easier to install
developer packages in random locations, without having to modify
the .pc files. Don't set "prefix" globally, instead override it
for each .pc file parsed, if the path where the .pc file is seems
to be the standard .../lib/pkgconfig.

* main.c (main): Add search directories also from two Registry
keys, in addition to the PKG_CONFIG_PATH environment
variable. Don't define prefix globally.

* parse.c (parse_line): Instead, if a .pc file is in
/foo/bar/lib/pkgconfig, define prefix as /foo/bar for that package
only.

* pkg.c: Case-fold file names on Windows, in case they have been
uppercasified by some tool.

* pkg-config.1: Document Windows behaviour.

ChangeLog
main.c
parse.c
pkg-config.1
pkg.c
pkg.h

index 4da4ed92b247180eb59eec72a19a2e4b17513e7c..2083a72af6748f8f727246c7c47b992a4a013e1a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2001-10-25  Tor Lillqvist  <tml@iki.fi>
+
+       Improve Windows behaviour: Make it even easier to install
+       developer packages in random locations, without having to modify
+       the .pc files. Don't set "prefix" globally, instead override it
+       for each .pc file parsed, if the path where the .pc file is seems
+       to be the standard .../lib/pkgconfig.
+
+       * main.c (main): Add search directories also from two Registry
+       keys, in addition to the PKG_CONFIG_PATH environment
+       variable. Don't define prefix globally.
+
+       * parse.c (parse_line): Instead, if a .pc file is in
+       /foo/bar/lib/pkgconfig, define prefix as /foo/bar for that package
+       only.
+
+       * pkg.c: Case-fold file names on Windows, in case they have been
+       uppercasified by some tool.
+
+       * pkg-config.1: Document Windows behaviour.
+
 2001-10-21  Tor Lillqvist  <tml@iki.fi>
 
        * Makefile.am (EXTRA_DIST): Distribute README.win32.
diff --git a/main.c b/main.c
index e2985f40a872fb072d0ebce4b4f8d945d7d85e0a..6a6b357289ee88877c8e24aabf218eb51d097d77 100644 (file)
--- a/main.c
+++ b/main.c
 #include <ctype.h>
 #include <stdio.h>
 
+#ifdef G_OS_WIN32
+#define STRICT
+#include <windows.h>
+#undef STRICT
+#endif
+
 static int want_debug_spew = 0;
 static int want_verbose_errors = 0;
 static int want_stdout_errors = 0;
@@ -144,14 +150,12 @@ main (int argc, char **argv)
   static int want_list = 0;
   static int result;
   static int want_uninstalled = 0;
-  static int dont_define_prefix = 0;
   static char *variable_name = NULL;
   static int want_exists = 0;
   static char *required_atleast_version = NULL;
   static char *required_exact_version = NULL;
   static char *required_max_version = NULL;
   static char *required_pkgconfig_version = NULL;
-  static char *prefix_variable = NULL;
   static int want_silence_errors = 0;
   GString *str;
   GSList *packages = NULL;
@@ -208,7 +212,8 @@ main (int argc, char **argv)
       "print errors from --print-errors to stdout not stderr" },
 #ifdef G_OS_WIN32
     { "dont-define-prefix", 0, POPT_ARG_NONE, &dont_define_prefix, 0,
-      "don't set the value of prefix based on where pkg-config.exe is installed" },
+      "don't try to override the value of prefix for each .pc file found with "
+      "a guesstimated value based on the location of the .pc file" },
     { "prefix-variable", 0, POPT_ARG_STRING, &prefix_variable, 0,
       "set the name of the variable that pkg-config automatically sets", "PREFIX" },
 #endif
@@ -248,6 +253,57 @@ main (int argc, char **argv)
       g_strfreev (search_dirs);
     }
 
+#ifdef G_OS_WIN32
+  {
+    /* Add search directories from the Registry */
+
+    HKEY roots[] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
+    gchar *root_names[] = { "HKEY_CURRENT_USER", "HKEY_LOCAL_MACHINE" };
+    HKEY key;
+    int i;
+    gulong max_value_name_len, max_value_len;
+
+    for (i = 0; i < G_N_ELEMENTS (roots); i++)
+      {
+       key = NULL;
+       if (RegOpenKeyEx (roots[i], "Software\\" PACKAGE "\\PKG_CONFIG_PATH", 0,
+                         KEY_QUERY_VALUE, &key) == ERROR_SUCCESS &&
+           RegQueryInfoKey (key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                            &max_value_name_len, &max_value_len,
+                            NULL, NULL) == ERROR_SUCCESS)
+         {
+           int index = 0;
+           gchar *value_name = g_malloc (max_value_name_len + 1);
+           gchar *value = g_malloc (max_value_len + 1);
+           
+           while (TRUE)
+             {
+               gulong type;
+               gulong value_name_len = max_value_name_len + 1;
+               gulong value_len = max_value_len + 1;
+               
+               if (RegEnumValue (key, index++, value_name, &value_name_len,
+                                 NULL, &type,
+                                 value, &value_len) != ERROR_SUCCESS)
+                 break;
+               
+               if (type != REG_SZ)
+                 continue;
+
+               value_name[value_name_len] = '\0';
+               value[value_len] = '\0';
+               debug_spew ("Adding directory '%s' from %s\\Software\\"
+                           PACKAGE "\\PKG_CONFIG_PATH\\%s\n",
+                           value, root_names[i], value_name);
+               add_search_dir (value);
+             }
+         }
+       if (key != NULL)
+         RegCloseKey (key);
+      }
+  }
+#endif
+
   pcbuilddir = getenv ("PKG_CONFIG_TOP_BUILD_DIR");
   if (pcbuilddir)
     {
@@ -329,26 +385,6 @@ main (int argc, char **argv)
         return 1;
     }
   
-#ifdef G_OS_WIN32
-  if (!dont_define_prefix)
-    {
-      gchar *prefix = g_win32_get_package_installation_directory (PACKAGE " " VERSION, NULL);
-      gchar *p = prefix;
-
-      /* Turn backslashes into slashes or poptParseArgvString() will eat
-       * them when ${prefix} has been expanded in parse_libs().
-       */
-      while (*p)
-       {
-         if (*p == '\\')
-           *p = '/';
-         p++;
-       }
-      define_global_variable (prefix_variable ? prefix_variable : "prefix",
-                             prefix);
-    }
-#endif
-
   package_init ();
 
   if (want_list)
diff --git a/parse.c b/parse.c
index 481bc40cd395cd53f86be80e1adb82a046f146f9..370043f198ced4aacf78e901ef903428804e15a2 100644 (file)
--- a/parse.c
+++ b/parse.c
 #endif
 #include <sys/types.h>
 
+#ifdef G_OS_WIN32
+int dont_define_prefix = FALSE;
+char *prefix_variable = "prefix";
+#endif
+
 /**
  * Read an entire line from a file into a buffer. Lines may
  * be delimited with '\n', '\r', '\n\r', or '\r\n'. The delimiter
@@ -817,6 +822,51 @@ parse_line (Package *pkg, const char *untrimmed, const char *path)
       if (pkg->vars == NULL)
         pkg->vars = g_hash_table_new (g_str_hash, g_str_equal);
 
+#ifdef G_OS_WIN32
+      if (!dont_define_prefix && strcmp (tag, prefix_variable) == 0)
+       {
+         /* This is the prefix variable. Try to guesstimate a value for it
+          * for this package from the location of the .pc file.
+          */
+
+         gchar *prefix = pkg->pcfiledir;
+         const int prefix_len = strlen (prefix);
+         const char *const lib_pkgconfig = "\\lib\\pkgconfig";
+         const int lib_pkgconfig_len = strlen (lib_pkgconfig);
+
+         if (strlen (prefix) > lib_pkgconfig_len &&
+             g_ascii_strcasecmp (prefix + prefix_len - lib_pkgconfig_len,
+                                 lib_pkgconfig) == 0)
+           {
+             /* It ends in lib\pkgconfig. Good. */
+             
+             gchar *p;
+             
+             prefix = g_strdup (prefix);
+             prefix[prefix_len - lib_pkgconfig_len] = '\0';
+             
+             /* Turn backslashes into slashes or
+              * poptParseArgvString() will eat them when ${prefix}
+              * has been expanded in parse_libs().
+              */
+             p = prefix;
+             while (*p)
+               {
+                 if (*p == '\\')
+                   *p = '/';
+                 p++;
+               }
+             varname = g_strdup (tag);
+             debug_spew (" Variable declaration, '%s' overridden with '%s'\n",
+                         tag, prefix);
+             g_hash_table_insert (pkg->vars, varname, prefix);
+             g_free (str);
+             g_free (tag);
+             return;
+           }
+       }
+#endif
+
       if (g_hash_table_lookup (pkg->vars, tag))
         {
           verbose_error ("Duplicate definition of variable '%s' in '%s'\n",
index e6a94d69f392cd4dd63d8917cfcd682725831a0c..19549d6d445c0f897d2797ee99ef2c08e00a45d8 100644 (file)
@@ -34,7 +34,8 @@ program: program.c
 special metadata files. These files are named after the package, 
 with the extension \fI.pc\fP. By default, pkg-config looks in 
 the directory \fIprefix\fP/lib/pkgconfig for these files; it will also
-look in the colon-separated list of directories specified by the 
+look in the colon-separated (on Windows, semicolon-separated) 
+list of directories specified by the 
 PKG_CONFIG_PATH environment variable. 
 
 .PP
@@ -170,23 +171,20 @@ Remember to use \-\-print-errors if you want error messages.
 .TP
 .I "--dont-define-prefix"
 This option is available only on Windows. It prevents \fIpkg-config\fP
-from automatically setting the value of the variable "prefix" to the
-directory where \fIpkg-config\fP was installed. (This directory is
-determined by asking the system where \fIpkg-config.exe\fP is located,
-and if that directory is called \fIbin\fP or \fIlib\fP, using its
-parent directory, otherwise itself.)
+from automatically trying to override the value of the variable
+"prefix" in each .pc file.
 
 .TP
 .I "--prefix-variable=PREFIX"
 Also this option is available only on Windows. It sets the name of the
-variable that \fIpkg-config\fP automatically sets to its own
-installation prefix.
+variable that \fIpkg-config\fP automatically sets as described above.
 
 .SH ENVIRONMENT VARIABLES
 
 .TP
 .I "PKG_CONFIG_PATH"
-A colon-separated list of directories to search for .pc files.
+A colon-separated (on Windows, semicolon-separated)
+list of directories to search for .pc files.
 The default directory will always be searched after searching the
 path; the default is \fIlibdir\fP/pkgconfig where \fIlibdir\fP
 is the libdir where \fIpkg-config\fP was installed.
@@ -214,6 +212,20 @@ Normally if you request the package "foo" and the package
 uninstalled packages.  If this environment variable is set, it
 disables said behavior.
 
+.SH WINDOWS SPECIALITIES
+If a .pc file is found in a path that corresponds to the usual
+conventions (i.e., ends with lib\\pkgconfig), the prefix for that
+package is assumed to be the grandparent of the directory where the .pc file
+was found.
+
+In addition to the \fIPKG_CONFIG_PATH\fP environment variable, the
+Registry keys
+\fIHKEY_CURRENT_USER\\Software\\pkgconfig\\PKG_CONFIG_PATH\fP and
+\fIHKEY_LOCAL_MACHINE\\Software\\pkgconfig\\PKG_CONFIG_PATH\fP can be
+used to specify dorectories to search for .pc files. Each (string)
+value in these keys is treated as a directory where to look for .pc
+files.
+
 .SH AUTOCONF MACROS
 
 .TP
diff --git a/pkg.c b/pkg.c
index 1686db5b3805269122b12bd4efec1f215301c526..686acedfcdb1598e381bace4c17668d98abe1fde 100644 (file)
--- a/pkg.c
+++ b/pkg.c
 #include <unistd.h>
 #endif
 #include <stdlib.h>
+#include <ctype.h>
 
 #ifdef G_OS_WIN32
 /* No hardcoded paths in the binary, thanks */
 #undef PKGLIBDIR
 /* It's OK to leak this, as PKGLIBDIR is invoked only once */
-#define PKGLIBDIR g_strconcat (g_win32_get_package_installation_directory (PACKAGE " " VERSION, NULL), "\\lib\\pkgconfig", NULL)
+#define PKGLIBDIR g_strconcat (g_win32_get_package_installation_directory (PACKAGE, NULL), "\\lib\\pkgconfig", NULL)
 #endif
 
 static void verify_package (Package *pkg);
@@ -45,6 +46,15 @@ add_search_dir (const char *path)
   search_dirs = g_slist_prepend (search_dirs, g_strdup (path));
 }
 
+#ifdef G_OS_WIN32
+/* Guard against .pc file being installed with UPPER CASE name */
+# define FOLD(x) tolower(x)
+# define FOLDCMP(a, b) g_ascii_strcasecmp (a, b)
+#else
+# define FOLD(x) (x)
+# define FOLDCMP(a, b) strcmp (a, b)
+#endif
+
 #define EXT_LEN 3
 
 static gboolean
@@ -54,8 +64,8 @@ ends_in_dotpc (const char *str)
   
   if (len > EXT_LEN &&
       str[len - 3] == '.' &&
-      str[len - 2] == 'p' &&
-      str[len - 1] == 'c')
+      FOLD (str[len - 2]) == 'p' &&
+      FOLD (str[len - 1]) == 'c')
     return TRUE;
   else
     return FALSE;
@@ -70,7 +80,7 @@ name_ends_in_uninstalled (const char *str)
   int len = strlen (str);
   
   if (len > UNINSTALLED_LEN &&
-      strcmp ((str + len - UNINSTALLED_LEN), "uninstalled") == 0)
+      FOLDCMP ((str + len - UNINSTALLED_LEN), "uninstalled") == 0)
     return TRUE;
   else
     return FALSE;
diff --git a/pkg.h b/pkg.h
index 74a13407d66aaaf98dda431d5a4db5debffd006f..587f6d6cc37098289e355a51c11ac0ab6d1b7c8c 100644 (file)
--- a/pkg.h
+++ b/pkg.h
@@ -93,5 +93,13 @@ gboolean name_ends_in_uninstalled (const char *str);
 /* If TRUE, do not automatically prefer uninstalled versions */
 extern gboolean disable_uninstalled;
 
+#ifdef G_OS_WIN32
+/* If TRUE, do not automatically define "prefix"  while
+ * parsing each .pc file */
+extern int dont_define_prefix;
+/* The name of the variable that acts as prefix, unless it is "prefix" */
+extern char *prefix_variable;
+#endif
+
 #endif