From d86ec30f0aef0139309a48555054cb5cb69be477 Mon Sep 17 00:00:00 2001 From: Arch Librarian Date: Thu, 14 Jul 2005 13:04:37 +0000 Subject: [PATCH] 2001-10-25 Tor Lillqvist Author: tml Date: 2001-10-24 21:22:33 GMT 2001-10-25 Tor Lillqvist 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 | 21 ++++++++++++++ main.c | 82 +++++++++++++++++++++++++++++++++++++--------------- parse.c | 50 ++++++++++++++++++++++++++++++++ pkg-config.1 | 30 +++++++++++++------ pkg.c | 18 +++++++++--- pkg.h | 8 +++++ 6 files changed, 173 insertions(+), 36 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4da4ed9..2083a72 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2001-10-25 Tor Lillqvist + + 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 * Makefile.am (EXTRA_DIST): Distribute README.win32. diff --git a/main.c b/main.c index e2985f4..6a6b357 100644 --- a/main.c +++ b/main.c @@ -11,6 +11,12 @@ #include #include +#ifdef G_OS_WIN32 +#define STRICT +#include +#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 481bc40..370043f 100644 --- a/parse.c +++ b/parse.c @@ -14,6 +14,11 @@ #endif #include +#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", diff --git a/pkg-config.1 b/pkg-config.1 index e6a94d6..19549d6 100644 --- a/pkg-config.1 +++ b/pkg-config.1 @@ -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 1686db5..686aced 100644 --- a/pkg.c +++ b/pkg.c @@ -22,12 +22,13 @@ #include #endif #include +#include #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 74a1340..587f6d6 100644 --- 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 -- 2.39.5