From b8bcd4f7491bb91a0b635abb7061d72689c86fbb Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Sun, 18 Mar 2018 11:51:58 -0400 Subject: [PATCH 1/6] Simplify requires lists - Lists of names are useless, better keep list of RequireVersion to always have the context. - Since we keep lists of RequireVersion we no longer need an hash table to map package name to their context. - No longer append requires to requires_private This allows to factor out log of duplicated code and will simplify adding a 3rd category of requires. https://bugs.freedesktop.org/show_bug.cgi?id=105572 --- main.c | 72 +++++++++++--------------- parse.c | 4 +- pkg.c | 153 ++++++++++++++++++++++++-------------------------------- pkg.h | 8 ++- 4 files changed, 97 insertions(+), 140 deletions(-) diff --git a/main.c b/main.c index 9b27d9a..5e95d18 100644 --- a/main.c +++ b/main.c @@ -482,6 +482,30 @@ static const GOptionEntry options_table[] = { { NULL, 0, 0, 0, NULL, NULL, NULL } }; +static void +print_requires (GList *packages, gboolean private) +{ + GList *pkgtmp; + for (pkgtmp = packages; pkgtmp != NULL; pkgtmp = g_list_next (pkgtmp)) + { + Package *pkg = pkgtmp->data; + GList *reqtmp; + + reqtmp = private ? pkg->requires_private : pkg->requires; + for (; reqtmp != NULL; reqtmp = g_list_next (reqtmp)) + { + RequiredVersion *req = reqtmp->data; + Package *deppkg = req->package; + if (req->comparison == ALWAYS_MATCH) + printf ("%s\n", deppkg->key); + else + printf ("%s %s %s\n", deppkg->key, + comparison_to_str(req->comparison), + req->version); + } + } +} + int main (int argc, char **argv) { @@ -763,53 +787,13 @@ main (int argc, char **argv) if (want_requires) { - GList *pkgtmp; - for (pkgtmp = packages; pkgtmp != NULL; pkgtmp = g_list_next (pkgtmp)) - { - Package *pkg = pkgtmp->data; - GList *reqtmp; - - /* process Requires: */ - for (reqtmp = pkg->requires; reqtmp != NULL; reqtmp = g_list_next (reqtmp)) - { - Package *deppkg = reqtmp->data; - RequiredVersion *req; - req = g_hash_table_lookup(pkg->required_versions, deppkg->key); - if ((req == NULL) || (req->comparison == ALWAYS_MATCH)) - printf ("%s\n", deppkg->key); - else - printf ("%s %s %s\n", deppkg->key, - comparison_to_str(req->comparison), - req->version); - } - } + /* process Requires: */ + print_requires (packages, FALSE); } if (want_requires_private) { - GList *pkgtmp; - for (pkgtmp = packages; pkgtmp != NULL; pkgtmp = g_list_next (pkgtmp)) - { - Package *pkg = pkgtmp->data; - GList *reqtmp; - /* process Requires.private: */ - for (reqtmp = pkg->requires_private; reqtmp != NULL; reqtmp = g_list_next (reqtmp)) - { - - Package *deppkg = reqtmp->data; - RequiredVersion *req; - - if (g_list_find (pkg->requires, reqtmp->data)) - continue; - - req = g_hash_table_lookup(pkg->required_versions, deppkg->key); - if ((req == NULL) || (req->comparison == ALWAYS_MATCH)) - printf ("%s\n", deppkg->key); - else - printf ("%s %s %s\n", deppkg->key, - comparison_to_str(req->comparison), - req->version); - } - } + /* process Requires.private: */ + print_requires (packages, TRUE); } /* Print all flags; then print a newline at the end. */ diff --git a/parse.c b/parse.c index 6e9907c..c96305b 100644 --- a/parse.c +++ b/parse.c @@ -546,7 +546,7 @@ parse_requires (Package *pkg, const char *str, const char *path) } trimmed = trim_and_sub (pkg, str, path); - pkg->requires_entries = parse_module_list (pkg, trimmed, path); + pkg->requires = parse_module_list (pkg, trimmed, path); g_free (trimmed); } @@ -565,7 +565,7 @@ parse_requires_private (Package *pkg, const char *str, const char *path) } trimmed = trim_and_sub (pkg, str, path); - pkg->requires_private_entries = parse_module_list (pkg, trimmed, path); + pkg->requires_private = parse_module_list (pkg, trimmed, path); g_free (trimmed); } diff --git a/pkg.c b/pkg.c index f29ecc7..e3e5830 100644 --- a/pkg.c +++ b/pkg.c @@ -219,6 +219,24 @@ package_init (gboolean want_list) add_virtual_pkgconfig_package (); } +static void +internal_get_package_foreach (gpointer data, gpointer user_data) +{ + gboolean warn = GPOINTER_TO_INT (user_data); + RequiredVersion *ver = data; + Package *pkg = ver->owner; + + debug_spew ("Searching for '%s' requirement '%s'\n", + pkg->key, ver->name); + ver->package = internal_get_package (ver->name, warn); + if (ver->package == NULL) + { + verbose_error ("Package '%s', required by '%s', not found\n", + ver->name, pkg->key); + exit (1); + } +} + static Package * internal_get_package (const char *name, gboolean warn) { @@ -226,7 +244,6 @@ internal_get_package (const char *name, gboolean warn) char *key = NULL; char *location = NULL; unsigned int path_position = 0; - GList *iter; GList *dir_iter; pkg = g_hash_table_lookup (packages, name); @@ -323,58 +340,12 @@ internal_get_package (const char *name, gboolean warn) g_hash_table_insert (packages, pkg->key, pkg); /* pull in Requires packages */ - for (iter = pkg->requires_entries; iter != NULL; iter = g_list_next (iter)) - { - Package *req; - RequiredVersion *ver = iter->data; - - debug_spew ("Searching for '%s' requirement '%s'\n", - pkg->key, ver->name); - req = internal_get_package (ver->name, warn); - if (req == NULL) - { - verbose_error ("Package '%s', required by '%s', not found\n", - ver->name, pkg->key); - exit (1); - } - - if (pkg->required_versions == NULL) - pkg->required_versions = g_hash_table_new (g_str_hash, g_str_equal); - - g_hash_table_insert (pkg->required_versions, ver->name, ver); - pkg->requires = g_list_prepend (pkg->requires, req); - } - - /* pull in Requires.private packages */ - for (iter = pkg->requires_private_entries; iter != NULL; - iter = g_list_next (iter)) - { - Package *req; - RequiredVersion *ver = iter->data; - - debug_spew ("Searching for '%s' private requirement '%s'\n", - pkg->key, ver->name); - req = internal_get_package (ver->name, warn); - if (req == NULL) - { - verbose_error ("Package '%s', required by '%s', not found\n", - ver->name, pkg->key); - exit (1); - } - - if (pkg->required_versions == NULL) - pkg->required_versions = g_hash_table_new (g_str_hash, g_str_equal); - - g_hash_table_insert (pkg->required_versions, ver->name, ver); - pkg->requires_private = g_list_prepend (pkg->requires_private, req); - } - - /* make requires_private include a copy of the public requires too */ - pkg->requires_private = g_list_concat (g_list_copy (pkg->requires), - pkg->requires_private); - - pkg->requires = g_list_reverse (pkg->requires); - pkg->requires_private = g_list_reverse (pkg->requires_private); + g_list_foreach (pkg->requires, + internal_get_package_foreach, + GINT_TO_POINTER (warn)); + g_list_foreach (pkg->requires_private, + internal_get_package_foreach, + GINT_TO_POINTER (warn)); verify_package (pkg); @@ -513,7 +484,8 @@ static void recursive_fill_list (Package *pkg, gboolean include_private, GHashTable *visited, GList **listp) { - GList *tmp; + GList *lists[2]; + guint i, nlists; /* * If the package has already been visited, then it is already in 'listp' and @@ -534,9 +506,19 @@ recursive_fill_list (Package *pkg, gboolean include_private, /* Start from the end of the required package list to maintain order since * the recursive list is built by prepending. */ - tmp = include_private ? pkg->requires_private : pkg->requires; - for (tmp = g_list_last (tmp); tmp != NULL; tmp = g_list_previous (tmp)) - recursive_fill_list (tmp->data, include_private, visited, listp); + lists[0] = pkg->requires; + lists[1] = pkg->requires_private; + nlists = include_private ? 2 : 1; + for (i = 0; i < nlists; i++) + { + GList *iter; + for (iter = g_list_last (lists[i]); iter != NULL; iter = g_list_previous (iter)) + { + RequiredVersion *ver = iter->data; + if (ver->package != NULL) + recursive_fill_list (ver->package, include_private, visited, listp); + } + } *listp = g_list_prepend (*listp, pkg); } @@ -640,6 +622,29 @@ static const gchar *msvc_include_envvars[] = { }; #endif +static void +verify_version_foreach (gpointer data, gpointer user_data) +{ + RequiredVersion *ver = data; + Package *req = ver->package; + Package *pkg = ver->owner; + + if (!version_test (ver->comparison, req->version, ver->version)) + { + verbose_error ("Package '%s' requires '%s %s %s' but version of %s is %s\n", + pkg->key, req->key, + comparison_to_str (ver->comparison), + ver->version, + req->key, + req->version); + if (req->url) + verbose_error ("You may find new versions of %s at %s\n", + req->name, req->url); + + exit (1); + } +} + static void verify_package (Package *pkg) { @@ -687,38 +692,8 @@ verify_package (Package *pkg) } /* Make sure we have the right version for all requirements */ - - iter = pkg->requires_private; - - while (iter != NULL) - { - Package *req = iter->data; - RequiredVersion *ver = NULL; - - if (pkg->required_versions) - ver = g_hash_table_lookup (pkg->required_versions, - req->key); - - if (ver) - { - if (!version_test (ver->comparison, req->version, ver->version)) - { - verbose_error ("Package '%s' requires '%s %s %s' but version of %s is %s\n", - pkg->key, req->key, - comparison_to_str (ver->comparison), - ver->version, - req->key, - req->version); - if (req->url) - verbose_error ("You may find new versions of %s at %s\n", - req->name, req->url); - - exit (1); - } - } - - iter = g_list_next (iter); - } + g_list_foreach (pkg->requires, verify_version_foreach, NULL); + g_list_foreach (pkg->requires_private, verify_version_foreach, NULL); /* Make sure we didn't drag in any conflicts via Requires * (inefficient algorithm, who cares) diff --git a/pkg.h b/pkg.h index c6732bd..6373d9c 100644 --- a/pkg.h +++ b/pkg.h @@ -61,6 +61,7 @@ struct RequiredVersion_ ComparisonType comparison; char *version; Package *owner; + Package *package; }; struct Package_ @@ -71,14 +72,11 @@ struct Package_ char *description; char *url; char *pcfiledir; /* directory it was loaded from */ - GList *requires_entries; - GList *requires; - GList *requires_private_entries; - GList *requires_private; + GList *requires; /* list of RequiredVersion */ + GList *requires_private; /* list of RequiredVersion */ GList *libs; GList *cflags; GHashTable *vars; - GHashTable *required_versions; /* hash from name to RequiredVersion */ GList *conflicts; /* list of RequiredVersion */ gboolean uninstalled; /* used the -uninstalled file */ int path_position; /* used to order packages by position in path of their .pc file, lower number means earlier in path */ From 43cd3e7a02f2a6d5f2aa204ed1867da877782e03 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Sun, 18 Mar 2018 15:34:57 -0400 Subject: [PATCH 2/6] Add Require.internal field This field is to be used for purely internal dependencies that are not exposed into the API at all. Those packages are there only for static link. https://bugs.freedesktop.org/show_bug.cgi?id=105572 --- main.c | 17 ++++++++++++---- parse.c | 24 +++++++++++++++++++++++ pkg.c | 61 +++++++++++++++++++++++++++++++++++++++++++-------------- pkg.h | 9 +++++++++ 4 files changed, 92 insertions(+), 19 deletions(-) diff --git a/main.c b/main.c index 5e95d18..6ed8aba 100644 --- a/main.c +++ b/main.c @@ -483,7 +483,7 @@ static const GOptionEntry options_table[] = { }; static void -print_requires (GList *packages, gboolean private) +print_requires (GList *packages, RequireType type) { GList *pkgtmp; for (pkgtmp = packages; pkgtmp != NULL; pkgtmp = g_list_next (pkgtmp)) @@ -491,7 +491,13 @@ print_requires (GList *packages, gboolean private) Package *pkg = pkgtmp->data; GList *reqtmp; - reqtmp = private ? pkg->requires_private : pkg->requires; + if (type == REQUIRE) + reqtmp = pkg->requires; + else if (type == REQUIRE_PRIVATE) + reqtmp = pkg->requires_private; + else + reqtmp = pkg->requires_internal; + for (; reqtmp != NULL; reqtmp = g_list_next (reqtmp)) { RequiredVersion *req = reqtmp->data; @@ -788,12 +794,15 @@ main (int argc, char **argv) if (want_requires) { /* process Requires: */ - print_requires (packages, FALSE); + print_requires (packages, REQUIRE); } if (want_requires_private) { + /* process Requires.internal: */ + print_requires (packages, REQUIRE_INTERNAL); + /* process Requires.private: */ - print_requires (packages, TRUE); + print_requires (packages, REQUIRE_PRIVATE); } /* Print all flags; then print a newline at the end. */ diff --git a/parse.c b/parse.c index c96305b..02a4cf3 100644 --- a/parse.c +++ b/parse.c @@ -569,6 +569,25 @@ parse_requires_private (Package *pkg, const char *str, const char *path) g_free (trimmed); } +static void +parse_requires_internal (Package *pkg, const char *str, const char *path) +{ + char *trimmed; + + if (pkg->requires_internal) + { + verbose_error ("Requires.internal field occurs twice in '%s'\n", path); + if (parse_strict) + exit (1); + else + return; + } + + trimmed = trim_and_sub (pkg, str, path); + pkg->requires_internal = parse_module_list (pkg, trimmed, path); + g_free (trimmed); +} + static void parse_conflicts (Package *pkg, const char *str, const char *path) { @@ -955,6 +974,11 @@ parse_line (Package *pkg, const char *untrimmed, const char *path, if (!ignore_requires_private) parse_requires_private (pkg, p, path); } + else if (strcmp (tag, "Requires.internal") == 0) + { + if (!ignore_requires_private) + parse_requires_internal (pkg, p, path); + } else if (strcmp (tag, "Requires") == 0) { if (ignore_requires == FALSE) diff --git a/pkg.c b/pkg.c index e3e5830..47725d6 100644 --- a/pkg.c +++ b/pkg.c @@ -346,6 +346,9 @@ internal_get_package (const char *name, gboolean warn) g_list_foreach (pkg->requires_private, internal_get_package_foreach, GINT_TO_POINTER (warn)); + g_list_foreach (pkg->requires_internal, + internal_get_package_foreach, + GINT_TO_POINTER (warn)); verify_package (pkg); @@ -481,11 +484,15 @@ packages_sort_by_path_position (GList *list) * any package that it depends on. */ static void -recursive_fill_list (Package *pkg, gboolean include_private, +recursive_fill_list (Package *pkg, gboolean include_private, FlagType flags, GHashTable *visited, GList **listp) { - GList *lists[2]; - guint i, nlists; + GList *lists[N_REQUIRE_TYPES] = { + pkg->requires, + pkg->requires_private, + pkg->requires_internal, + }; + gint type; /* * If the package has already been visited, then it is already in 'listp' and @@ -504,19 +511,42 @@ recursive_fill_list (Package *pkg, gboolean include_private, g_hash_table_replace (visited, pkg->key, pkg->key); } - /* Start from the end of the required package list to maintain order since - * the recursive list is built by prepending. */ - lists[0] = pkg->requires; - lists[1] = pkg->requires_private; - nlists = include_private ? 2 : 1; - for (i = 0; i < nlists; i++) + for (type = 0; type < N_REQUIRE_TYPES; type++) { GList *iter; - for (iter = g_list_last (lists[i]); iter != NULL; iter = g_list_previous (iter)) + FlagType new_flags; + + switch (type) + { + case REQUIRE: + new_flags = flags; + break; + + case REQUIRE_PRIVATE: + /* When we don't include private libs we still want to pull Cflags + * from Require.private. + * See https://bugs.freedesktop.org/show_bug.cgi?id=105572 */ + new_flags = include_private ? flags : flags & CFLAGS_ANY; + break; + + case REQUIRE_INTERNAL: + /* Only pull Libs from Require.internal if we include private libs. + * Don't pull anything otherwise. + * See https://bugs.freedesktop.org/show_bug.cgi?id=105572 */ + new_flags = include_private ? flags & LIBS_ANY : 0; + break; + } + + if (new_flags == 0) + continue; + + /* Start from the end of the required package list to maintain order since + * the recursive list is built by prepending. */ + for (iter = g_list_last (lists[type]); iter != NULL; iter = g_list_previous (iter)) { RequiredVersion *ver = iter->data; if (ver->package != NULL) - recursive_fill_list (ver->package, include_private, visited, listp); + recursive_fill_list (ver->package, include_private, new_flags, visited, listp); } } @@ -570,7 +600,7 @@ fill_list (GList *packages, FlagType type, * the recursive list is built by prepending. */ visited = g_hash_table_new (g_str_hash, g_str_equal); for (tmp = g_list_last (packages); tmp != NULL; tmp = g_list_previous (tmp)) - recursive_fill_list (tmp->data, include_private, visited, &expanded); + recursive_fill_list (tmp->data, include_private, type, visited, &expanded); g_hash_table_destroy (visited); spew_package_list ("post-recurse", expanded); @@ -694,12 +724,13 @@ verify_package (Package *pkg) /* Make sure we have the right version for all requirements */ g_list_foreach (pkg->requires, verify_version_foreach, NULL); g_list_foreach (pkg->requires_private, verify_version_foreach, NULL); + g_list_foreach (pkg->requires_internal, verify_version_foreach, NULL); /* Make sure we didn't drag in any conflicts via Requires * (inefficient algorithm, who cares) */ visited = g_hash_table_new (g_str_hash, g_str_equal); - recursive_fill_list (pkg, TRUE, visited, &requires); + recursive_fill_list (pkg, TRUE, FLAGS_ANY, visited, &requires); g_hash_table_destroy (visited); conflicts = pkg->conflicts; @@ -911,14 +942,14 @@ packages_get_flags (GList *pkgs, FlagType flags) /* sort packages in path order for -L/-I, dependency order otherwise */ if (flags & CFLAGS_OTHER) { - cur = get_multi_merged (pkgs, CFLAGS_OTHER, FALSE, TRUE); + cur = get_multi_merged (pkgs, CFLAGS_OTHER, FALSE, !ignore_private_libs); debug_spew ("adding CFLAGS_OTHER string \"%s\"\n", cur); g_string_append (str, cur); g_free (cur); } if (flags & CFLAGS_I) { - cur = get_multi_merged (pkgs, CFLAGS_I, TRUE, TRUE); + cur = get_multi_merged (pkgs, CFLAGS_I, TRUE, !ignore_private_libs); debug_spew ("adding CFLAGS_I string \"%s\"\n", cur); g_string_append (str, cur); g_free (cur); diff --git a/pkg.h b/pkg.h index 6373d9c..584a6e2 100644 --- a/pkg.h +++ b/pkg.h @@ -55,6 +55,14 @@ struct Flag_ char *arg; }; +typedef enum +{ + REQUIRE, + REQUIRE_PRIVATE, + REQUIRE_INTERNAL, + N_REQUIRE_TYPES +} RequireType; + struct RequiredVersion_ { char *name; @@ -74,6 +82,7 @@ struct Package_ char *pcfiledir; /* directory it was loaded from */ GList *requires; /* list of RequiredVersion */ GList *requires_private; /* list of RequiredVersion */ + GList *requires_internal; /* list of RequiredVersion */ GList *libs; GList *cflags; GHashTable *vars; From edb96ea0eadea96c2743ce3ffd526babacee8b9c Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 19 Mar 2018 10:52:57 -0400 Subject: [PATCH 3/6] Add test for Requires.internal https://bugs.freedesktop.org/show_bug.cgi?id=105572 --- check/check-print-options | 4 +++- check/check-requires-private | 8 ++++---- check/internal-dep.pc | 6 ++++++ check/requires-test.pc | 1 + 4 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 check/internal-dep.pc diff --git a/check/check-print-options b/check/check-print-options index 198e5a1..0f98c78 100755 --- a/check/check-print-options +++ b/check/check-print-options @@ -31,7 +31,8 @@ RESULT="public-dep >= 1" run_test --print-requires requires-test # --print-requires-private -RESULT="private-dep >= 1" +RESULT="internal-dep >= 1 +private-dep >= 1" run_test --print-requires-private requires-test # --list-all, limit to a subdirectory @@ -51,6 +52,7 @@ run_test --modversion --version simple # --print-requires/--print-requires-private allowed together RESULT="public-dep >= 1 +internal-dep >= 1 private-dep >= 1" run_test --print-requires --print-requires-private requires-test run_test --print-requires-private --print-requires requires-test diff --git a/check/check-requires-private b/check/check-requires-private index dc69baf..66e3ef7 100755 --- a/check/check-requires-private +++ b/check/check-requires-private @@ -4,7 +4,7 @@ set -e . ${srcdir}/common -# expect cflags from requires-test and public-dep +# expect cflags from requires-test, public-dep and private-dep but not internal-dep RESULT="-I/requires-test/include -I/private-dep/include -I/public-dep/include" run_test --cflags requires-test run_test --static --cflags requires-test @@ -15,9 +15,9 @@ if [ "$list_indirect_deps" = no ]; then run_test --libs requires-test fi -# expect libs for requires-test, public-dep and private-dep in static case -RESULT="-L/requires-test/lib -L/private-dep/lib -L/public-dep/lib \ --lrequires-test -lprivate-dep -lpublic-dep" +# expect libs for requires-test, public-dep, private-dep and internal-dep in static case +RESULT="-L/requires-test/lib -L/internal-dep/lib -L/private-dep/lib -L/public-dep/lib \ +-lrequires-test -linternal-dep -lprivate-dep -lpublic-dep" if [ "$list_indirect_deps" = yes ]; then run_test --libs requires-test fi diff --git a/check/internal-dep.pc b/check/internal-dep.pc new file mode 100644 index 0000000..87a051b --- /dev/null +++ b/check/internal-dep.pc @@ -0,0 +1,6 @@ +Name: Requires test package +Description: Dummy pkgconfig test package for testing Requires/Requires.private +Version: 1.0.0 +Libs: -L/internal-dep/lib -linternal-dep +Cflags: -I/internal-dep/include + diff --git a/check/requires-test.pc b/check/requires-test.pc index e483db2..5339f4e 100644 --- a/check/requires-test.pc +++ b/check/requires-test.pc @@ -3,6 +3,7 @@ Description: Dummy pkgconfig test package for testing Requires/Requires.private Version: 1.0.0 Requires: public-dep >= 1 Requires.private: private-dep >= 1 +Requires.internal: internal-dep >= 1 Libs: -L/requires-test/lib -lrequires-test Cflags: -I/requires-test/include From 1579a87b3b81244fe56b63d1e51f7d2b068f0757 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 19 Mar 2018 11:16:29 -0400 Subject: [PATCH 4/6] Update the guide to include Requires.internal https://bugs.freedesktop.org/show_bug.cgi?id=105572 --- pkg-config-guide.html | 48 ++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/pkg-config-guide.html b/pkg-config-guide.html index c666fe5..9ebce3f 100644 --- a/pkg-config-guide.html +++ b/pkg-config-guide.html @@ -121,13 +121,23 @@ Libs: -L${libdir} -lfoo
  • Requires: A list of packages required by this package. The versions of these packages may be specified using the comparison operators - =, <, >, <= or >=.
  • + =, <, >, <= or >=. This is to be used when an application + using this package will have to use symbols and APIs from a dependent + library.
  • Requires.private: A list of private packages required by this package but not exposed to applications. The version specific rules from - the Requires field also apply here.
  • + the Requires field also apply here. This is to be used when an + application using this package needs header files from a dependent library + but is not likely to call any of their symbols. -
  • Conflicts: An optional field describing packages that this one +
  • Requires.internal: A list of internal packages required by this + package but not exposed to applications. The version specific rules from + the Requires field also apply here. This is to be used when + this package uses a library as internal implementation detail but is not + exposed neither in its API nor ABI.
  • + +
  • Conflicts: An op tional field describing packages that this one conflicts with. The version specific rules from the Requires field also apply here. This field also takes multiple instances of the same package. E.g., Conflicts: bar < 1.2.3, bar >= 1.3.0.
  • @@ -186,25 +196,25 @@ includedir=${prefix}/include Cflags: -I${includedir}/foo

    The most important pkg-config metadata fields are - Requires, Requires.private, Cflags, Libs - and Libs.private. They will define the metadata used by external - projects to compile and link with the library.

    + Requires, Requires.private, Requires.internal, + Cflags, Libs and Libs.private. They will define + the metadata used by external projects to compile and link with the library.

    -

    Requires and Requires.private define other modules - needed by the library. It is usually preferred to use the private variant of - Requires to avoid exposing unnecessary libraries to the program - that is linking with your library. If the program will not be using the - symbols of the required library, it should not be linking directly to that - library. See the discussion of +

    Requires, Requires.private and Requires.internal + define other modules needed by the library. It is usually preferred to use the + private variant of Requires to avoid exposing unnecessary libraries + to the program that is linking with your library. If the program will not be + using the symbols of the required library, it should not be linking directly + to that library. See the discussion of overlinking for a more thorough explanation.

    Since pkg-config always exposes the link flags of the Requires libraries, these modules will become direct dependencies of the program. On the other hand, libraries from Requires.private - will only be included when static linking. For this reason, it is usually - only appropriate to add modules from the same package in Requires. -

    + and Requires.internal will only be included when static linking. For + this reason, it is usually only appropriate to add modules from the same + package in Requires.

    The Libs field contains the link flags necessary to use that library. In addition, Libs and Libs.private contain link @@ -404,10 +414,10 @@ myapp_LDADD = $(X_LIBS) expose libx data types in its public API. What do I put in my z.pc file? -

    Again, add the module to Requires.private if it supports - pkg-config. In this case, the compiler flags will be emitted - unnecessarily, but it ensures that the linker flags will be present when - linking statically. If libx does not support pkg-config, +

    Add the module to Requires.internal if it supports + pkg-config. Unlike Requires.private the compiler flags + will not be emitted, but it ensures that the linker flags will be present + when linking statically. If libx does not support pkg-config, add the necessary linker flags to Libs.private.

    From 398e790cc1893af669f6cbf49abf1b567844d622 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 22 Mar 2018 09:42:24 -0400 Subject: [PATCH 5/6] Ignore Requires.internal if we only want cflags `pkg-config --cflags --libs dep` should not fail if internal packages are missing. https://bugs.freedesktop.org/show_bug.cgi?id=105572 --- check/check-requires-private | 3 +++ check/requires-notfound-test.pc | 9 +++++++++ main.c | 4 ++++ parse.c | 10 ++++++---- parse.h | 3 ++- pkg.c | 17 ++++++++++++++++- pkg.h | 2 ++ 7 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 check/requires-notfound-test.pc diff --git a/check/check-requires-private b/check/check-requires-private index 66e3ef7..586b33e 100755 --- a/check/check-requires-private +++ b/check/check-requires-private @@ -7,12 +7,15 @@ set -e # expect cflags from requires-test, public-dep and private-dep but not internal-dep RESULT="-I/requires-test/include -I/private-dep/include -I/public-dep/include" run_test --cflags requires-test +run_test --cflags requires-notfound-test run_test --static --cflags requires-test +run_test --static --cflags requires-notfound-test # expect libs for just requires-test and public-dep RESULT="-L/requires-test/lib -L/public-dep/lib -lrequires-test -lpublic-dep" if [ "$list_indirect_deps" = no ]; then run_test --libs requires-test + run_test --libs requires-notfound-test fi # expect libs for requires-test, public-dep, private-dep and internal-dep in static case diff --git a/check/requires-notfound-test.pc b/check/requires-notfound-test.pc new file mode 100644 index 0000000..dfe46b6 --- /dev/null +++ b/check/requires-notfound-test.pc @@ -0,0 +1,9 @@ +Name: Requires test package +Description: Dummy pkgconfig test package for testing Requires/Requires.private +Version: 1.0.0 +Requires: public-dep >= 1 +Requires.private: private-dep >= 1 +Requires.internal: notfound-dep >= 1 +Libs: -L/requires-test/lib -lrequires-test +Cflags: -I/requires-test/include + diff --git a/main.c b/main.c index 6ed8aba..65497a7 100644 --- a/main.c +++ b/main.c @@ -650,6 +650,10 @@ main (int argc, char **argv) (want_static_lib_list && (pkg_flags & LIBS_ANY))) enable_requires_private(); + if (want_requires_private || want_exists || + (want_static_lib_list && (pkg_flags & LIBS_ANY))) + enable_requires_internal(); + /* ignore Requires if no Cflags or Libs are requested */ if (pkg_flags == 0 && !want_requires && !want_exists) diff --git a/parse.c b/parse.c index 02a4cf3..6d6b171 100644 --- a/parse.c +++ b/parse.c @@ -926,7 +926,8 @@ parse_url (Package *pkg, const char *str, const char *path) static void parse_line (Package *pkg, const char *untrimmed, const char *path, gboolean ignore_requires, gboolean ignore_private_libs, - gboolean ignore_requires_private) + gboolean ignore_requires_private, + gboolean ignore_requires_internal) { char *str; char *p; @@ -976,7 +977,7 @@ parse_line (Package *pkg, const char *untrimmed, const char *path, } else if (strcmp (tag, "Requires.internal") == 0) { - if (!ignore_requires_private) + if (!ignore_requires_internal) parse_requires_internal (pkg, p, path); } else if (strcmp (tag, "Requires") == 0) @@ -1113,7 +1114,8 @@ Package* parse_package_file (const char *key, const char *path, gboolean ignore_requires, gboolean ignore_private_libs, - gboolean ignore_requires_private) + gboolean ignore_requires_private, + gboolean ignore_requires_internal) { FILE *f; Package *pkg; @@ -1158,7 +1160,7 @@ parse_package_file (const char *key, const char *path, one_line = TRUE; parse_line (pkg, str->str, path, ignore_requires, ignore_private_libs, - ignore_requires_private); + ignore_requires_private, ignore_requires_internal); g_string_truncate (str, 0); } diff --git a/parse.h b/parse.h index db1bf86..6736f58 100644 --- a/parse.h +++ b/parse.h @@ -25,7 +25,8 @@ Package *parse_package_file (const char *key, const char *path, gboolean ignore_requires, gboolean ignore_private_libs, - gboolean ignore_requires_private); + gboolean ignore_requires_private, + gboolean ignore_requires_internal); GList *parse_module_list (Package *pkg, const char *str, const char *path); diff --git a/pkg.c b/pkg.c index 47725d6..c1f09f1 100644 --- a/pkg.c +++ b/pkg.c @@ -49,6 +49,7 @@ static GList *search_dirs = NULL; gboolean disable_uninstalled = FALSE; gboolean ignore_requires = FALSE; gboolean ignore_requires_private = TRUE; +gboolean ignore_requires_internal = TRUE; gboolean ignore_private_libs = TRUE; void @@ -317,7 +318,8 @@ internal_get_package (const char *name, gboolean warn) debug_spew ("Reading '%s' from file '%s'\n", name, location); pkg = parse_package_file (key, location, ignore_requires, - ignore_private_libs, ignore_requires_private); + ignore_private_libs, ignore_requires_private, + ignore_requires_internal); g_free (key); if (pkg != NULL && strstr (location, "uninstalled.pc")) @@ -1195,6 +1197,7 @@ print_package_list (void) ignore_requires = TRUE; ignore_requires_private = TRUE; + ignore_requires_internal = TRUE; g_hash_table_foreach (packages, max_len_foreach, &mlen); g_hash_table_foreach (packages, packages_foreach, GINT_TO_POINTER (mlen + 1)); @@ -1235,3 +1238,15 @@ disable_requires_private(void) { ignore_requires_private = TRUE; } + +void +enable_requires_internal(void) +{ + ignore_requires_internal = FALSE; +} + +void +disable_requires_internal(void) +{ + ignore_requires_internal = TRUE; +} diff --git a/pkg.h b/pkg.h index 584a6e2..18bde7e 100644 --- a/pkg.h +++ b/pkg.h @@ -129,6 +129,8 @@ void enable_requires(void); void disable_requires(void); void enable_requires_private(void); void disable_requires_private(void); +void enable_requires_internal(void); +void disable_requires_internal(void); /* If TRUE, do not automatically prefer uninstalled versions */ extern gboolean disable_uninstalled; From 09eddd6d6e2ee19d8f7844a26670a57b5073f28c Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 22 Mar 2018 09:44:43 -0400 Subject: [PATCH 6/6] m4: Fix autoreconf Patch copied from debian package. https://bugs.freedesktop.org/show_bug.cgi?id=105572 --- glib/m4macros/glib-gettext.m4 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/glib/m4macros/glib-gettext.m4 b/glib/m4macros/glib-gettext.m4 index 5217fd8..155b1d8 100644 --- a/glib/m4macros/glib-gettext.m4 +++ b/glib/m4macros/glib-gettext.m4 @@ -313,7 +313,7 @@ msgstr "" # on various variables needed by the Makefile.in.in installed by # glib-gettextize. dnl -glib_DEFUN([GLIB_GNU_GETTEXT], +AU_DEFUN([GLIB_GNU_GETTEXT], [AC_REQUIRE([AC_PROG_CC])dnl GLIB_LC_MESSAGES @@ -383,7 +383,8 @@ glib_DEFUN([GLIB_GNU_GETTEXT], rm -f po/POTFILES sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ < $srcdir/po/POTFILES.in > po/POTFILES - ]) + ], + [[$0: This macro is deprecated. You should use upstream gettext instead.]]) # AM_GLIB_DEFINE_LOCALEDIR(VARIABLE) # -------------------------------