+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.
#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;
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;
"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
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)
{
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)
#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
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",
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
.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.
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
#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);
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
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;
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;
/* 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