pkg: reintroduce less aggressive flags deduplication

Stripping non-consecutives options was dropped in 9adfd9ebfc, in
order to prevent the alteration of the command semantics.

To mitigate cases when the generated flags list is too long, the
deduplication is reintroduced but limited only to a few cases (-L, -l,
-I) for which semantics is not altered by a repetition of the same
flag.

Address issue:
https://gitlab.freedesktop.org/pkg-config/pkg-config/-/issues/75
This commit is contained in:
Stefano Sabatini 2022-11-21 10:20:51 +01:00
parent 3455bb83b2
commit 9a6c72edca
3 changed files with 39 additions and 14 deletions

View file

@ -9,7 +9,7 @@ run_test --cflags flag-dup-1 flag-dup-2
run_test --cflags flag-dup-2 flag-dup-1
RESULT="-L/path/lib -lpath2 -Wl,--whole-archive -lm --Wl,--no-whole-archive \
-Xlinker -R -Xlinker /path/lib -lpath1 -Wl,--whole-archive -lm \
-Xlinker -R -Xlinker /path/lib -lpath1 -Wl,--whole-archive \
--Wl,--no-whole-archive -Xlinker -R -Xlinker /path/lib"
run_test --libs flag-dup-1 flag-dup-2
run_test --libs flag-dup-2 flag-dup-1

View file

@ -16,8 +16,7 @@ PKG_CONFIG_LIBDIR=${srcdir}/gtk
RESULT="-DGSEAL_ENABLE -pthread -I/gtk/include/gtk-3.0 \
-I/gtk/include/pango-1.0 -I/gtk/include/atk-1.0 -I/gtk/include/cairo \
-I/gtk/include/pixman-1 -I/gtk/include -I/gtk/include/gdk-pixbuf-2.0 \
-I/gtk/include -I/gtk/include/pango-1.0 -I/gtk/include/glib-2.0 \
-I/gtk/lib/glib-2.0/include -I/gtk/include/freetype2 -I/gtk/include"
-I/gtk/include/glib-2.0 -I/gtk/lib/glib-2.0/include -I/gtk/include/freetype2"
run_test --cflags gtk+-3.0
run_test --cflags --static gtk+-3.0
@ -29,8 +28,9 @@ run_test --cflags --static gtk+-3.0
# -lglib-2.0
RESULT="-L/gtk/lib -lgtk-3 -lgdk-3 -lpangocairo-1.0 -latk-1.0 -lcairo-gobject \
-lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0 \
-lgthread-2.0 -pthread -lrt -lgmodule-2.0 -pthread -lrt -lglib-2.0 -lfreetype \
-lgthread-2.0 -pthread -lrt -lgmodule-2.0 -pthread -lglib-2.0 -lfreetype \
-lfontconfig"
if [ "$list_indirect_deps" = no ]; then
run_test --libs gtk+-3.0
fi
@ -49,10 +49,10 @@ fi
# -lpango-1.0 -lfontconfig -lexpat -lfreetype -lgobject-2.0 -lffi \
# -lgmodule-2.0 -ldl -lgthread-2.0 -lglib-2.0 -lrt
RESULT="-L/gtk/lib -lgtk-3 -lgdk-3 -lpangocairo-1.0 -latk-1.0 -lcairo-gobject \
-lcairo -lz -lpixman-1 -lpng12 -lz -lm -lXrender -lX11 -lpthread -lxcb -lXau \
-lgdk_pixbuf-2.0 -lm -lpng12 -lz -lm -lgio-2.0 -lz -lresolv -lpangoft2-1.0 \
-lcairo -lz -lpixman-1 -lpng12 -lm -lXrender -lX11 -lpthread -lxcb -lXau \
-lgdk_pixbuf-2.0 -lgio-2.0 -lresolv -lpangoft2-1.0 \
-lpango-1.0 -lgobject-2.0 -lffi -lgthread-2.0 -pthread -lrt -lgmodule-2.0 \
-pthread -lrt -ldl -lglib-2.0 -lrt -lfreetype -lfontconfig -lexpat -lfreetype"
-pthread -ldl -lglib-2.0 -lfreetype -lfontconfig -lexpat"
if [ "$list_indirect_deps" = yes ]; then
run_test --libs gtk+-3.0
fi

39
pkg.c
View file

@ -393,30 +393,55 @@ get_package_quiet (const char *name)
return internal_get_package (name, FALSE);
}
#define SAFE_DEDUPLICABLE_FLAGS "LlI"
/* Strip consecutive duplicate arguments in the flag list. */
static GList *
flag_list_strip_duplicates (GList *list)
{
GHashTable *table;
GList *tmp;
/* Start at the 2nd element of the list so we don't have to check for an
* existing previous element. */
for (tmp = g_list_next (list); tmp != NULL; tmp = g_list_next (tmp))
table = g_hash_table_new (g_str_hash, g_str_equal);
for (tmp = list; tmp != NULL; tmp = g_list_next (tmp))
{
Flag *cur = tmp->data;
Flag *prev = tmp->prev->data;
Flag *flag = tmp->data;
Flag *prev_flag = tmp->prev ? tmp->prev->data : NULL;
gboolean remove = FALSE;
if (cur->type == prev->type && g_strcmp0 (cur->arg, prev->arg) == 0)
debug_spew ("Seeing if arg %s is duplicate\n", flag->arg);
if (prev_flag && flag->type == prev_flag->type &&
g_strcmp0 (flag->arg, prev_flag->arg) == 0)
{
remove = TRUE;
}
else if (flag->arg[0] != '-' || !strchr(SAFE_DEDUPLICABLE_FLAGS, flag->arg[1]))
{
debug_spew ("arg %s cannot be safely de-duplicated\n", flag->arg);
}
else if (!g_hash_table_lookup_extended (table, flag->arg, NULL, NULL))
{
/* Unique flag. Track it and and move to the next. */
g_hash_table_replace (table, flag->arg, flag->arg);
}
else
{
remove = TRUE;
}
if (remove)
{
/* Remove the duplicate flag from the list and move to the last
* element to prepare for the next iteration. */
GList *dup = tmp;
debug_spew (" removing duplicate \"%s\"\n", cur->arg);
debug_spew (" removing duplicate \"%s\"\n", flag->arg);
tmp = g_list_previous (tmp);
list = g_list_remove_link (list, dup);
}
}
g_hash_table_destroy (table);
return list;
}