2005-05-21 Tollef Fog Heen <tfheen@err.no>

Author: tfheen
Date: 2005-05-21 09:14:47 GMT
2005-05-21  Tollef Fog Heen  <tfheen@err.no>

    * check/check-libs-private: New test to check for support for
    private libraries.

    * check/simple.pc (prefix): Add Libs.private header.

    * check/Makefile.am (TESTS): Add check-libs-private test

    * pkg.h: Adjust function prototypes.

    * pkg.c: Add global ignore_private_libs variable.
    (scan_dir): Use the correct free function.  Stop leaking file
    descriptors.
    (package_get_l_libs, packages_get_l_libs, package_get_L_libs,
    packages_get_L_libs): Stop the recursive silliness and go back to
    old behaviour.
    (packages_get_all_libs): Adjust parameters to packages_get_*_libs
    (enable_private_libs, disable_private_libs): Trivial helper
    functions.

    * pkg-config.1: Update documentation wrt search path (Debian
    #308942), update docs for Libs.private and add the problematic
    handling of mixing = and non-= arguments to the bugs section.

    * parse.h: Adjust parameters for parse_package_file to get private
    libs or not.

    * parse.c (trim_and_sub): Fix memory leak.
    (_do_parse_libs): New function including what's common between
    parse_libs and parse_private_libs.
    (parse_libs_private): New function.  Handle private libraries.
    (parse_line): Add . to the list of valid characters in headers (so
    Libs.private works correctly.
    (parse_line): Fix memory leaks.
    (parse_line): Handle Libs.private.
    (parse_package_file): Fix memory leak.

    * main.c (main): Fix memory leak.

    * NEWS: Document changes to inter-library handling.

    * main.c (main): Handle inter-library dependencies old-style, but
    do private libraries too.  Adjust parameters to
    packages_get_*_libs.

    * configure.in: Change comment wrt inter-library handling to talk
    about private libraries instead.
This commit is contained in:
Arch Librarian 2005-07-14 13:07:18 +00:00
parent c22e6a1838
commit 20d118d57a
12 changed files with 254 additions and 126 deletions

View file

@ -1,3 +1,52 @@
2005-05-21 Tollef Fog Heen <tfheen@err.no>
* check/check-libs-private: New test to check for support for
private libraries.
* check/simple.pc (prefix): Add Libs.private header.
* check/Makefile.am (TESTS): Add check-libs-private test
* pkg.h: Adjust function prototypes.
* pkg.c: Add global ignore_private_libs variable.
(scan_dir): Use the correct free function. Stop leaking file
descriptors.
(package_get_l_libs, packages_get_l_libs, package_get_L_libs,
packages_get_L_libs): Stop the recursive silliness and go back to
old behaviour.
(packages_get_all_libs): Adjust parameters to packages_get_*_libs
(enable_private_libs, disable_private_libs): Trivial helper
functions.
* pkg-config.1: Update documentation wrt search path (Debian
#308942), update docs for Libs.private and add the problematic
handling of mixing = and non-= arguments to the bugs section.
* parse.h: Adjust parameters for parse_package_file to get private
libs or not.
* parse.c (trim_and_sub): Fix memory leak.
(_do_parse_libs): New function including what's common between
parse_libs and parse_private_libs.
(parse_libs_private): New function. Handle private libraries.
(parse_line): Add . to the list of valid characters in headers (so
Libs.private works correctly.
(parse_line): Fix memory leaks.
(parse_line): Handle Libs.private.
(parse_package_file): Fix memory leak.
* main.c (main): Fix memory leak.
* NEWS: Document changes to inter-library handling.
* main.c (main): Handle inter-library dependencies old-style, but
do private libraries too. Adjust parameters to
packages_get_*_libs.
* configure.in: Change comment wrt inter-library handling to talk
about private libraries instead.
2005-04-22 Tollef Fog Heen <tfheen@err.no>
* main.c (main): Re-add PKG_CONFIG_LIBDIR support which was

21
NEWS
View file

@ -1,3 +1,24 @@
pkg-config 0.18
===
- The inter-library dependencies check was too tight and caused
problems if one used the --no-undefined flag to libtool on Solaris
(since it there expands to -Wl,-z,defs which disallows undefined
symbols). Add a new name to .pc files: Libs.private which will not
be listed in the output of --libs unless --static is also given.
Private libraries are libraries which are needed in the case of
static linking or on platforms not supporting inter-library
dependencies. They are not supposed to be used for libraries which
are exposed through the library in question. An example of an
exposed library is GTK+ exposing Glib. A common example of a private
library is libm.
Generally, if include another library's headers in your own, it's a
public dependency and not a private one.
Thanks a lot to James Henstridge for both the bug and the following
discussion.
pkg-config 0.17.2
===
- Don't go into an infinite loop allocating more and more memory when

View file

@ -1,3 +1,3 @@
TESTS = check-cflags check-libs check-define-variable
EXTRA_DIST = $(TESTS) common simple.pc
TESTS = check-cflags check-libs check-define-variable check-libs-private
EXTRA_DIST = $(TESTS) common simple.pc

10
check/check-libs-private Executable file
View file

@ -0,0 +1,10 @@
#! /bin/sh
set -e
. ${srcdir}/common
ARGS="--static --libs simple"
RESULT="-lsimple -lm"
run_test

View file

@ -8,4 +8,5 @@ Description: Dummy pkgconfig test package for testing pkgconfig
Version: 1.0.0
Requires:
Libs: -lsimple
Libs.private: -lm
Cflags: -I${includedir}

View file

@ -27,9 +27,9 @@ PKG_CONFIG_FIND_PC_PATH
#
# Code taken from gtk+-2.0's configure.in.
#
# This causes pkg-config to only list direct dependencies on platforms
# which support inter-library dependencies.
#
# This causes pkg-config to not list private dependencies (a very
# common example is libm) on platforms which support inter-library
# dependencies.
AC_ARG_ENABLE(indirect-deps,
[AC_HELP_STRING([--enable-indirect-deps],

13
main.c
View file

@ -413,6 +413,11 @@ main (int argc, char **argv)
else
debug_spew ("Error printing disabled\n");
if (want_static_lib_list)
enable_private_libs();
else
disable_private_libs();
if (want_my_version)
{
printf ("%s\n", VERSION);
@ -446,6 +451,8 @@ main (int argc, char **argv)
g_string_append (str, " ");
}
poptFreeContext (opt_context);
g_strstrip (str->str);
{
@ -601,14 +608,14 @@ main (int argc, char **argv)
if (want_l_libs)
{
char *str = packages_get_l_libs (packages, want_static_lib_list);
char *str = packages_get_l_libs (packages);
printf ("%s ", str);
g_free (str);
need_newline = TRUE;
}
else if (want_L_libs)
{
char *str = packages_get_L_libs (packages, want_static_lib_list);
char *str = packages_get_L_libs (packages);
printf ("%s ", str);
g_free (str);
need_newline = TRUE;
@ -622,7 +629,7 @@ main (int argc, char **argv)
}
else if (want_libs)
{
char *str = packages_get_all_libs (packages, want_static_lib_list);
char *str = packages_get_all_libs (packages);
printf ("%s ", str);
g_free (str);
need_newline = TRUE;

149
parse.c
View file

@ -39,7 +39,6 @@ char *prefix_variable = "prefix";
int msvc_syntax = FALSE;
#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
@ -205,6 +204,7 @@ trim_and_sub (Package *pkg, const char *str, const char *path)
g_free (varname);
g_string_append (subst, varval);
g_free (varval);
}
else
{
@ -581,15 +581,8 @@ parse_conflicts (Package *pkg, const char *str, const char *path)
g_free (trimmed);
}
static void
parse_libs (Package *pkg, const char *str, const char *path)
static void _do_parse_libs (Package *pkg, int argc, char **argv)
{
/* Strip out -l and -L flags, put them in a separate list. */
char *trimmed;
char **argv = NULL;
int argc;
int result;
int i;
#ifdef G_OS_WIN32
char *L_flag = (msvc_syntax ? "/libpath:" : "-L");
@ -600,25 +593,6 @@ parse_libs (Package *pkg, const char *str, const char *path)
char *l_flag = "-l";
char *lib_suffix = "";
#endif
if (pkg->l_libs || pkg->L_libs || pkg->other_libs)
{
verbose_error ("Libs field occurs twice in '%s'\n", path);
exit (1);
}
trimmed = trim_and_sub (pkg, str, path);
result = poptParseArgvString (trimmed, &argc, &argv);
if (result < 0)
{
verbose_error ("Couldn't parse Libs field into an argument vector: %s\n",
poptStrerror (result));
exit (1);
}
i = 0;
while (i < argc)
@ -696,14 +670,96 @@ parse_libs (Package *pkg, const char *str, const char *path)
++i;
}
g_free (argv);
g_free (trimmed);
pkg->l_libs = g_slist_reverse (pkg->l_libs);
pkg->L_libs = g_slist_reverse (pkg->L_libs);
pkg->other_libs = g_slist_reverse (pkg->other_libs);
}
static void
parse_libs (Package *pkg, const char *str, const char *path)
{
/* Strip out -l and -L flags, put them in a separate list. */
char *trimmed;
char **argv = NULL;
int argc;
int result;
if (pkg->libs_num > 0)
{
verbose_error ("Libs field occurs twice in '%s'\n", path);
exit (1);
}
trimmed = trim_and_sub (pkg, str, path);
result = poptParseArgvString (trimmed, &argc, &argv);
if (result < 0)
{
verbose_error ("Couldn't parse Libs field into an argument vector: %s\n",
poptStrerror (result));
exit (1);
}
_do_parse_libs(pkg, argc, argv);
g_free (trimmed);
g_free (argv);
pkg->libs_num++;
}
static void
parse_libs_private (Package *pkg, const char *str, const char *path)
{
/*
List of private libraries. Private libraries are libraries which
are needed in the case of static linking or on platforms not
supporting inter-library dependencies. They are not supposed to
be used for libraries which are exposed through the library in
question. An example of an exposed library is GTK+ exposing Glib.
A common example of a private library is libm.
Generally, if include another library's headers in your own, it's
a public dependency and not a private one.
*/
char *trimmed;
char **argv = NULL;
int argc;
int result;
if (pkg->libs_private_num > 0)
{
verbose_error ("Libs.private field occurs twice in '%s'\n", path);
exit (1);
}
trimmed = trim_and_sub (pkg, str, path);
result = poptParseArgvString (trimmed, &argc, &argv);
if (result < 0)
{
verbose_error ("Couldn't parse Libs.private field into an argument vector: %s\n",
poptStrerror (result));
exit (1);
}
_do_parse_libs(pkg, argc, argv);
g_free (argv);
g_free (trimmed);
pkg->libs_private_num++;
}
static void
parse_cflags (Package *pkg, const char *str, const char *path)
{
@ -797,7 +853,7 @@ 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)
parse_line (Package *pkg, const char *untrimmed, const char *path, gboolean ignore_requires, gboolean ignore_private_libs)
{
char *str;
char *p;
@ -807,8 +863,11 @@ parse_line (Package *pkg, const char *untrimmed, const char *path, gboolean igno
str = trim_string (untrimmed);
if (*str == '\0')
return; /* empty line */
if (*str == '\0') /* empty line */
{
g_free(str);
return;
}
p = str;
@ -816,7 +875,7 @@ parse_line (Package *pkg, const char *untrimmed, const char *path, gboolean igno
while ((*p >= 'A' && *p <= 'Z') ||
(*p >= 'a' && *p <= 'z') ||
(*p >= '0' && *p <= '9') ||
*p == '_')
*p == '_' || *p == '.')
p++;
tag = g_strndup (str, p - str);
@ -842,8 +901,11 @@ parse_line (Package *pkg, const char *untrimmed, const char *path, gboolean igno
if (ignore_requires == FALSE)
parse_requires (pkg, p, path);
else
return;
goto cleanup;
}
else if ((strcmp (tag, "Libs.private") == 0) &&
ignore_private_libs == FALSE)
parse_libs_private (pkg, p, path);
else if (strcmp (tag, "Libs") == 0)
parse_libs (pkg, p, path);
else if (strcmp (tag, "Cflags") == 0 ||
@ -915,9 +977,7 @@ parse_line (Package *pkg, const char *untrimmed, const char *path, gboolean igno
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;
goto cleanup;
}
}
#endif
@ -938,13 +998,14 @@ parse_line (Package *pkg, const char *untrimmed, const char *path, gboolean igno
g_hash_table_insert (pkg->vars, varname, varval);
}
cleanup:
g_free (str);
g_free (tag);
}
Package*
parse_package_file (const char *path, gboolean ignore_requires)
parse_package_file (const char *path, gboolean ignore_requires, gboolean ignore_private_libs)
{
FILE *f;
Package *pkg;
@ -981,7 +1042,7 @@ parse_package_file (const char *path, gboolean ignore_requires)
{
one_line = TRUE;
parse_line (pkg, str->str, path, ignore_requires);
parse_line (pkg, str->str, path, ignore_requires, ignore_private_libs);
g_string_truncate (str, 0);
}
@ -989,7 +1050,7 @@ parse_package_file (const char *path, gboolean ignore_requires)
if (!one_line)
verbose_error ("Package file '%s' appears to be empty\n",
path);
g_string_free (str, TRUE);
fclose(f);
return pkg;
}

View file

@ -22,7 +22,8 @@
#include "pkg.h"
Package *parse_package_file (const char *path, gboolean ignore_requires);
Package *parse_package_file (const char *path, gboolean ignore_requires,
gboolean ignore_private_libs);
Package *get_compat_package (const char *name);

View file

@ -210,15 +210,23 @@ from automatically trying to override the value of the variable
Also this option is available only on Windows. It sets the name of the
variable that \fIpkg-config\fP automatically sets as described above.
.TP
.I "--static"
Output libraries suitable for static linking. That means including
any private libraries in the output. This relies on proper tagging in
the .pc files, else a too large number of libraries will ordinarily be
output.
.SH ENVIRONMENT VARIABLES
.TP
.I "PKG_CONFIG_PATH"
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.
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:\fIdatadir\fP/pkgconfig where \fIlibdir\fP is
the libdir where \fIpkg-config\fP and \fIdatadir\fP is the datadir
where \fIpkg-config\fP was installed.
.TP
.I "PKG_CONFIG_DEBUG_SPEW"
@ -318,6 +326,7 @@ URL: http://www.gtk.org
Requires: glib-2.0 = 1.3.1
Conflicts: foobar <= 4.5
Libs: -L${libdir} -lgobject-1.3
Libs.private: -lm
Cflags: -I${includedir}/glib-2.0 -I${libdir}/glib/include
.fi
@ -380,6 +389,12 @@ This line should give the link flags specific to your package.
Don't add any flags for required packages; \fIpkg-config\fP will
add those automatically.
.TP
.I "Libs.private:"
This line should list any private libraries in use. Private libraries
are libraries which are not exposed through your library, but are
needed in the case of static linking.
.TP
.I "Cflags:"
This line should list the compile flags specific to your package.
@ -396,6 +411,6 @@ various hackers in the GNOME team. It was inspired by Owen Taylor's
\fIgtk-config\fP program.
.SH BUGS
Hah!
\fIpkg-config\fP does not handle mixing of parameters with and without
= well. Stick with one.

83
pkg.c
View file

@ -55,6 +55,7 @@ static int scanned_dir_count = 0;
gboolean disable_uninstalled = FALSE;
gboolean ignore_requires = FALSE;
gboolean ignore_private_libs = TRUE;
void
add_search_dir (const char *path)
@ -145,7 +146,7 @@ scan_dir (const char *dirname)
}
dir = opendir (dirname_copy);
free (dirname_copy);
g_free (dirname_copy);
if (!dir)
{
debug_spew ("Cannot open directory '%s' in package search path: %s\n",
@ -196,6 +197,7 @@ scan_dir (const char *dirname)
dent->d_name);
}
}
closedir(dir);
}
static Package *
@ -320,7 +322,7 @@ internal_get_package (const char *name, gboolean warn, gboolean check_compat)
}
debug_spew ("Reading '%s' from file '%s'\n", name, location);
pkg = parse_package_file (location, ignore_requires);
pkg = parse_package_file (location, ignore_requires, ignore_private_libs);
if (pkg == NULL)
{
@ -998,10 +1000,8 @@ get_multi_merged_from_back (GSList *pkgs, GetListFunc func, gboolean in_path_ord
}
char *
package_get_l_libs (Package *pkg, gboolean recurse)
package_get_l_libs (Package *pkg)
{
if (!recurse)
return string_list_to_string (get_l_libs(pkg));
/* We don't want these in search path order, rather in dependency
* order, so static linking works.
*/
@ -1012,41 +1012,14 @@ package_get_l_libs (Package *pkg, gboolean recurse)
}
char *
packages_get_l_libs (GSList *pkgs, gboolean recurse)
packages_get_l_libs (GSList *pkgs)
{
if (!recurse) {
GSList *tmp;
GSList *list;
GSList *dups_list = NULL;
char *retval;
tmp = pkgs;
while (tmp != NULL)
{
dups_list = g_slist_concat (dups_list, g_slist_copy(get_l_libs(tmp->data)));
tmp = tmp->next;
}
list = string_list_strip_duplicates_from_back (dups_list);
g_slist_free (dups_list);
retval = string_list_to_string (list);
g_slist_free (list);
return retval;
}
return get_multi_merged_from_back (pkgs, get_l_libs, FALSE);
}
char *
package_get_L_libs (Package *pkg, gboolean recurse)
package_get_L_libs (Package *pkg)
{
if (!recurse)
return string_list_to_string (get_L_libs(pkg));
/* We want these in search path order so the -L flags don't override PKG_CONFIG_PATH */
if (pkg->L_libs_merged == NULL)
pkg->L_libs_merged = get_merged (pkg, get_L_libs, TRUE);
@ -1055,31 +1028,8 @@ package_get_L_libs (Package *pkg, gboolean recurse)
}
char *
packages_get_L_libs (GSList *pkgs, gboolean recurse)
packages_get_L_libs (GSList *pkgs)
{
if (!recurse) {
GSList *tmp;
GSList *list;
GSList *dups_list = NULL;
char *retval;
tmp = pkgs;
while (tmp != NULL)
{
dups_list = g_slist_concat (dups_list, g_slist_copy(get_L_libs(tmp->data)));
tmp = tmp->next;
}
list = string_list_strip_duplicates_from_back (dups_list);
g_slist_free (dups_list);
retval = string_list_to_string (list);
g_slist_free (list);
return retval;
}
return get_multi_merged (pkgs, get_L_libs, TRUE);
}
@ -1099,7 +1049,7 @@ packages_get_other_libs (GSList *pkgs)
}
char *
packages_get_all_libs (GSList *pkgs, gboolean recurse)
packages_get_all_libs (GSList *pkgs)
{
char *l_libs;
char *L_libs;
@ -1110,8 +1060,8 @@ packages_get_all_libs (GSList *pkgs, gboolean recurse)
str = g_string_new ("");
other_libs = packages_get_other_libs (pkgs);
L_libs = packages_get_L_libs (pkgs, recurse);
l_libs = packages_get_l_libs (pkgs, recurse);
L_libs = packages_get_L_libs (pkgs);
l_libs = packages_get_l_libs (pkgs);
if (other_libs)
g_string_append (str, other_libs);
@ -1503,3 +1453,14 @@ print_package_list (void)
g_hash_table_foreach (locations, packages_foreach, GINT_TO_POINTER (mlen + 1));
}
void
enable_private_libs(void)
{
ignore_private_libs = FALSE;
}
void
disable_private_libs(void)
{
ignore_private_libs = TRUE;
}

12
pkg.h
View file

@ -72,16 +72,18 @@ struct _Package
GSList *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 */
int libs_num; /* Number of times the "Libs" header has been seen */
int libs_private_num; /* Number of times the "Libs.private" header has been seen */
};
Package *get_package (const char *name);
char * package_get_l_libs (Package *pkg, gboolean recurse);
char * packages_get_l_libs (GSList *pkgs, gboolean recurse);
char * package_get_L_libs (Package *pkg, gboolean recurse);
char * packages_get_L_libs (GSList *pkgs, gboolean recurse);
char * package_get_l_libs (Package *pkg);
char * packages_get_l_libs (GSList *pkgs);
char * package_get_L_libs (Package *pkg);
char * packages_get_L_libs (GSList *pkgs);
char * package_get_other_libs (Package *pkg);
char * packages_get_other_libs (GSList *pkgs);
char * packages_get_all_libs (GSList *pkgs, gboolean recurse);
char * packages_get_all_libs (GSList *pkgs);
char * package_get_I_cflags (Package *pkg);
char * packages_get_I_cflags (GSList *pkgs);
char * package_get_other_cflags (Package *pkg);