mirror of
https://gitlab.freedesktop.org/pkg-config/pkg-config.git
synced 2025-12-20 04:20:04 +01:00
Optimization to load only needed .pc files
Currently pkg-config scans all .pc files from the search path during initialization. That makes some of the code simpler and works fine when there are not many .pc files on the system. When there are a lot of .pc files, then this represents a lot of wasted effort. Rework the package gathering so that it happens as needed. To support the --list-all mode, the scanning at initialization can still be done. https://bugs.freedesktop.org/show_bug.cgi?id=98215
This commit is contained in:
parent
a38d5c58a1
commit
c53385b5db
3 changed files with 59 additions and 98 deletions
2
main.c
2
main.c
|
|
@ -643,7 +643,7 @@ main (int argc, char **argv)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
package_init ();
|
package_init (want_list);
|
||||||
|
|
||||||
if (want_list)
|
if (want_list)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
153
pkg.c
153
pkg.c
|
|
@ -43,11 +43,8 @@
|
||||||
static void verify_package (Package *pkg);
|
static void verify_package (Package *pkg);
|
||||||
|
|
||||||
static GHashTable *packages = NULL;
|
static GHashTable *packages = NULL;
|
||||||
static GHashTable *locations = NULL;
|
|
||||||
static GHashTable *path_positions = NULL;
|
|
||||||
static GHashTable *globals = NULL;
|
static GHashTable *globals = NULL;
|
||||||
static GList *search_dirs = NULL;
|
static GList *search_dirs = NULL;
|
||||||
static int scanned_dir_count = 0;
|
|
||||||
|
|
||||||
gboolean disable_uninstalled = FALSE;
|
gboolean disable_uninstalled = FALSE;
|
||||||
gboolean ignore_requires = FALSE;
|
gboolean ignore_requires = FALSE;
|
||||||
|
|
@ -121,6 +118,8 @@ name_ends_in_uninstalled (const char *str)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Package *
|
||||||
|
internal_get_package (const char *name, gboolean warn);
|
||||||
|
|
||||||
/* Look for .pc files in the given directory and add them into
|
/* Look for .pc files in the given directory and add them into
|
||||||
* locations, ignoring duplicates
|
* locations, ignoring duplicates
|
||||||
|
|
@ -129,7 +128,7 @@ static void
|
||||||
scan_dir (char *dirname)
|
scan_dir (char *dirname)
|
||||||
{
|
{
|
||||||
GDir *dir;
|
GDir *dir;
|
||||||
const gchar *d_name;
|
const gchar *filename;
|
||||||
|
|
||||||
int dirnamelen = strlen (dirname);
|
int dirnamelen = strlen (dirname);
|
||||||
/* Use a copy of dirname cause Win32 opendir doesn't like
|
/* Use a copy of dirname cause Win32 opendir doesn't like
|
||||||
|
|
@ -161,59 +160,20 @@ scan_dir (char *dirname)
|
||||||
dir = g_dir_open (dirname_copy, 0 , NULL);
|
dir = g_dir_open (dirname_copy, 0 , NULL);
|
||||||
g_free (dirname_copy);
|
g_free (dirname_copy);
|
||||||
|
|
||||||
scanned_dir_count += 1;
|
|
||||||
|
|
||||||
if (!dir)
|
if (!dir)
|
||||||
{
|
{
|
||||||
debug_spew ("Cannot open directory #%i '%s' in package search path: %s\n",
|
debug_spew ("Cannot open directory '%s' in package search path: %s\n",
|
||||||
scanned_dir_count, dirname, g_strerror (errno));
|
dirname, g_strerror (errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_spew ("Scanning directory #%i '%s'\n", scanned_dir_count, dirname);
|
debug_spew ("Scanning directory '%s'\n", dirname);
|
||||||
|
|
||||||
while ((d_name = g_dir_read_name(dir)))
|
while ((filename = g_dir_read_name(dir)))
|
||||||
{
|
{
|
||||||
int len = strlen (d_name);
|
char *path = g_build_filename (dirname, filename, NULL);
|
||||||
|
internal_get_package (path, FALSE);
|
||||||
if (ends_in_dotpc (d_name))
|
g_free (path);
|
||||||
{
|
|
||||||
char *pkgname = g_malloc (len - EXT_LEN + 1);
|
|
||||||
|
|
||||||
debug_spew ("File '%s' appears to be a .pc file\n", d_name);
|
|
||||||
|
|
||||||
strncpy (pkgname, d_name, len - EXT_LEN);
|
|
||||||
pkgname[len-EXT_LEN] = '\0';
|
|
||||||
|
|
||||||
if (g_hash_table_lookup (locations, pkgname))
|
|
||||||
{
|
|
||||||
debug_spew ("File '%s' ignored, we already know about package '%s'\n", d_name, pkgname);
|
|
||||||
g_free (pkgname);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char *filename = g_malloc (dirnamelen + 1 + len + 1);
|
|
||||||
strncpy (filename, dirname, dirnamelen);
|
|
||||||
filename[dirnamelen] = G_DIR_SEPARATOR;
|
|
||||||
strcpy (filename + dirnamelen + 1, d_name);
|
|
||||||
|
|
||||||
if (g_file_test(filename, G_FILE_TEST_IS_REGULAR) == TRUE) {
|
|
||||||
g_hash_table_insert (locations, pkgname, filename);
|
|
||||||
g_hash_table_insert (path_positions, pkgname,
|
|
||||||
GINT_TO_POINTER (scanned_dir_count));
|
|
||||||
debug_spew ("Will find package '%s' in file '%s'\n",
|
|
||||||
pkgname, filename);
|
|
||||||
} else {
|
|
||||||
debug_spew ("Ignoring '%s' while looking for '%s'; not a "
|
|
||||||
"regular file.\n", pkgname, filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
debug_spew ("Ignoring file '%s' in search directory; not a .pc file\n",
|
|
||||||
d_name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
g_dir_close (dir);
|
g_dir_close (dir);
|
||||||
}
|
}
|
||||||
|
|
@ -243,31 +203,31 @@ add_virtual_pkgconfig_package (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
package_init ()
|
package_init (gboolean want_list)
|
||||||
{
|
{
|
||||||
static gboolean initted = FALSE;
|
if (packages)
|
||||||
|
return;
|
||||||
if (!initted)
|
|
||||||
{
|
|
||||||
initted = TRUE;
|
|
||||||
|
|
||||||
packages = g_hash_table_new (g_str_hash, g_str_equal);
|
packages = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
locations = g_hash_table_new (g_str_hash, g_str_equal);
|
|
||||||
path_positions = g_hash_table_new (g_str_hash, g_str_equal);
|
|
||||||
|
|
||||||
add_virtual_pkgconfig_package ();
|
|
||||||
|
|
||||||
g_list_foreach (search_dirs, (GFunc)scan_dir, NULL);
|
if (want_list)
|
||||||
}
|
g_list_foreach (search_dirs, (GFunc)scan_dir, NULL);
|
||||||
|
else
|
||||||
|
/* Should not add virtual pkgconfig package when listing to be
|
||||||
|
* compatible with old code that only listed packages from real
|
||||||
|
* files */
|
||||||
|
add_virtual_pkgconfig_package ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Package *
|
static Package *
|
||||||
internal_get_package (const char *name, gboolean warn)
|
internal_get_package (const char *name, gboolean warn)
|
||||||
{
|
{
|
||||||
Package *pkg = NULL;
|
Package *pkg = NULL;
|
||||||
char *key;
|
char *key = NULL;
|
||||||
const char *location;
|
char *location = NULL;
|
||||||
|
unsigned int path_position = 0;
|
||||||
GList *iter;
|
GList *iter;
|
||||||
|
GList *dir_iter;
|
||||||
|
|
||||||
pkg = g_hash_table_lookup (packages, name);
|
pkg = g_hash_table_lookup (packages, name);
|
||||||
|
|
||||||
|
|
@ -280,7 +240,8 @@ internal_get_package (const char *name, gboolean warn)
|
||||||
if ( ends_in_dotpc (name) )
|
if ( ends_in_dotpc (name) )
|
||||||
{
|
{
|
||||||
debug_spew ("Considering '%s' to be a filename rather than a package name\n", name);
|
debug_spew ("Considering '%s' to be a filename rather than a package name\n", name);
|
||||||
location = name;
|
location = g_strdup (name);
|
||||||
|
key = g_strdup (name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -303,7 +264,18 @@ internal_get_package (const char *name, gboolean warn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
location = g_hash_table_lookup (locations, name);
|
for (dir_iter = search_dirs; dir_iter != NULL;
|
||||||
|
dir_iter = g_list_next (dir_iter))
|
||||||
|
{
|
||||||
|
path_position++;
|
||||||
|
location = g_strdup_printf ("%s%c%s.pc", (char*)dir_iter->data,
|
||||||
|
G_DIR_SEPARATOR, name);
|
||||||
|
if (g_file_test (location, G_FILE_TEST_IS_REGULAR))
|
||||||
|
break;
|
||||||
|
g_free (location);
|
||||||
|
location = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (location == NULL)
|
if (location == NULL)
|
||||||
|
|
@ -317,21 +289,13 @@ internal_get_package (const char *name, gboolean warn)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (location != name)
|
if (key == NULL)
|
||||||
key = g_strdup (name);
|
key = g_strdup (name);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* need to strip package name out of the filename */
|
/* need to strip package name out of the filename */
|
||||||
int len = strlen (name);
|
key = g_path_get_basename (name);
|
||||||
const char *end = name + (len - EXT_LEN);
|
key[strlen (key) - EXT_LEN] = '\0';
|
||||||
const char *start = end;
|
|
||||||
|
|
||||||
while (start != name && *start != G_DIR_SEPARATOR)
|
|
||||||
--start;
|
|
||||||
|
|
||||||
g_assert (end >= start);
|
|
||||||
|
|
||||||
key = g_strndup (start, end - start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_spew ("Reading '%s' from file '%s'\n", name, location);
|
debug_spew ("Reading '%s' from file '%s'\n", name, location);
|
||||||
|
|
@ -339,17 +303,18 @@ internal_get_package (const char *name, gboolean warn)
|
||||||
ignore_private_libs, ignore_requires_private);
|
ignore_private_libs, ignore_requires_private);
|
||||||
g_free (key);
|
g_free (key);
|
||||||
|
|
||||||
|
if (pkg != NULL && strstr (location, "uninstalled.pc"))
|
||||||
|
pkg->uninstalled = TRUE;
|
||||||
|
|
||||||
|
g_free (location);
|
||||||
|
|
||||||
if (pkg == NULL)
|
if (pkg == NULL)
|
||||||
{
|
{
|
||||||
debug_spew ("Failed to parse '%s'\n", location);
|
debug_spew ("Failed to parse '%s'\n", location);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strstr (location, "uninstalled.pc"))
|
pkg->path_position = path_position;
|
||||||
pkg->uninstalled = TRUE;
|
|
||||||
|
|
||||||
pkg->path_position =
|
|
||||||
GPOINTER_TO_INT (g_hash_table_lookup (path_positions, pkg->key));
|
|
||||||
|
|
||||||
debug_spew ("Path position of '%s' is %d\n",
|
debug_spew ("Path position of '%s' is %d\n",
|
||||||
pkg->key, pkg->path_position);
|
pkg->key, pkg->path_position);
|
||||||
|
|
@ -1170,19 +1135,15 @@ max_len_foreach (gpointer key, gpointer value, gpointer data)
|
||||||
static void
|
static void
|
||||||
packages_foreach (gpointer key, gpointer value, gpointer data)
|
packages_foreach (gpointer key, gpointer value, gpointer data)
|
||||||
{
|
{
|
||||||
Package *pkg = get_package (key);
|
Package *pkg = value;
|
||||||
|
char *pad;
|
||||||
|
|
||||||
if (pkg != NULL)
|
pad = g_strnfill (GPOINTER_TO_INT (data) - strlen (pkg->key), ' ');
|
||||||
{
|
|
||||||
char *pad;
|
|
||||||
|
|
||||||
pad = g_strnfill (GPOINTER_TO_INT (data) - strlen (pkg->key), ' ');
|
|
||||||
|
|
||||||
printf ("%s%s%s - %s\n",
|
printf ("%s%s%s - %s\n",
|
||||||
pkg->key, pad, pkg->name, pkg->description);
|
pkg->key, pad, pkg->name, pkg->description);
|
||||||
|
|
||||||
g_free (pad);
|
g_free (pad);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1193,8 +1154,8 @@ print_package_list (void)
|
||||||
ignore_requires = TRUE;
|
ignore_requires = TRUE;
|
||||||
ignore_requires_private = TRUE;
|
ignore_requires_private = TRUE;
|
||||||
|
|
||||||
g_hash_table_foreach (locations, max_len_foreach, &mlen);
|
g_hash_table_foreach (packages, max_len_foreach, &mlen);
|
||||||
g_hash_table_foreach (locations, packages_foreach, GINT_TO_POINTER (mlen + 1));
|
g_hash_table_foreach (packages, packages_foreach, GINT_TO_POINTER (mlen + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
2
pkg.h
2
pkg.h
|
|
@ -98,7 +98,7 @@ char * packages_get_var (GList *pkgs,
|
||||||
|
|
||||||
void add_search_dir (const char *path);
|
void add_search_dir (const char *path);
|
||||||
void add_search_dirs (const char *path, const char *separator);
|
void add_search_dirs (const char *path, const char *separator);
|
||||||
void package_init (void);
|
void package_init (gboolean want_list);
|
||||||
int compare_versions (const char * a, const char *b);
|
int compare_versions (const char * a, const char *b);
|
||||||
gboolean version_test (ComparisonType comparison,
|
gboolean version_test (ComparisonType comparison,
|
||||||
const char *a,
|
const char *a,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue