mirror of
https://gitlab.freedesktop.org/pkg-config/pkg-config.git
synced 2026-05-17 15:38:09 +02:00
Add Cflags.private field
Those Cflags will be added if linking statically against a library; this is necessary if the public headers need to be mutated depending on linkage mode. Eg on Microsoft Windows varaibles whose definition resides in a shared library need to be declared with a special attribute; if linked to statically this attribute must not be used. With Cflags.private their headers can eg check if 'LIBRARYNAME_STATIC' is not defined to know that the special attribute is needed; without it everyone linking against the library will need to manually research what the expected macro is and set it depending on linkage mode. This field is also supported by pkgconf since version 0.9.3 and already used by (some) affected libraries targeting Microsoft Windows. Note that _do_parse_cflags always adds the flags to pkg->cflags and there is no pkg->cflags_private; instead the call to parse_cflags_private is conditional. This matches the existing implementation of Libs.private. Closes: https://gitlab.freedesktop.org/pkg-config/pkg-config/-/issues/38
This commit is contained in:
parent
481ef5b743
commit
bb8f1b7b91
10 changed files with 131 additions and 12 deletions
|
|
@ -2,6 +2,7 @@ TESTS_ENVIRONMENT = PKG_CONFIG='$(TESTS_PKG_CONFIG)' $(TESTS_SHELL)
|
|||
|
||||
TESTS = \
|
||||
check-cflags \
|
||||
check-cflags-private \
|
||||
check-libs \
|
||||
check-mixed-flags \
|
||||
check-non-l-flags \
|
||||
|
|
@ -40,6 +41,7 @@ EXTRA_DIST = \
|
|||
requires-test.pc \
|
||||
public-dep.pc \
|
||||
private-dep.pc \
|
||||
private-cflags.pc \
|
||||
includedir.pc \
|
||||
missing-requires-private.pc \
|
||||
missing-requires.pc \
|
||||
|
|
|
|||
11
check/check-cflags-private
Executable file
11
check/check-cflags-private
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#! /bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
. ${srcdir}/common
|
||||
|
||||
RESULT="-I/dummy/include"
|
||||
run_test --cflags private-cflags
|
||||
|
||||
RESULT="-DDUMMY_STATIC=1 $RESULT"
|
||||
run_test --static --cflags private-cflags
|
||||
7
check/private-cflags.pc
Normal file
7
check/private-cflags.pc
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Name: Requires test package
|
||||
Description: Dummy pkgconfig test package for testing Cflags/Cflags.private
|
||||
Version: 1.0.0
|
||||
Libs: -L/dummy/lib -ldummy
|
||||
Cflags: -I/dummy/include
|
||||
Cflags.private: -DDUMMY_STATIC=1
|
||||
|
||||
10
main.c
10
main.c
|
|
@ -615,9 +615,15 @@ main (int argc, char **argv)
|
|||
debug_spew ("Error printing disabled\n");
|
||||
|
||||
if (want_static_lib_list)
|
||||
enable_private_libs();
|
||||
{
|
||||
enable_private_libs();
|
||||
enable_cflags_private();
|
||||
}
|
||||
else
|
||||
disable_private_libs();
|
||||
{
|
||||
disable_private_libs();
|
||||
disable_cflags_private();
|
||||
}
|
||||
|
||||
/* honor Requires.private if any Cflags are requested or any static
|
||||
* libs are requested */
|
||||
|
|
|
|||
64
parse.c
64
parse.c
|
|
@ -896,6 +896,57 @@ parse_cflags (Package *pkg, const char *str, const char *path)
|
|||
g_free (trimmed);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_cflags_private (Package *pkg, const char *str, const char *path)
|
||||
{
|
||||
/*
|
||||
List of private Cflags. Private Cflags are flags which
|
||||
are needed in the case of static linking. This can be required for
|
||||
example on platforms which require special attributes to be set
|
||||
for variables or functions which are defined in a shared library,
|
||||
as is the case for Microsoft Windows. Affected libraries will need
|
||||
to have ifdefs in their public headers to change the attributes
|
||||
depending on whether they are being linked to staticly or dynamicly.
|
||||
*/
|
||||
|
||||
char *trimmed;
|
||||
char **argv = NULL;
|
||||
int argc = 0;
|
||||
GError *error = NULL;
|
||||
|
||||
if (pkg->cflags_private_num)
|
||||
{
|
||||
verbose_error ("Cflags.private field occurs twice in '%s'\n", path);
|
||||
if (parse_strict)
|
||||
exit (1);
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
trimmed = trim_and_sub (pkg, str, path);
|
||||
|
||||
if (trimmed && *trimmed &&
|
||||
!g_shell_parse_argv (trimmed, &argc, &argv, &error))
|
||||
{
|
||||
verbose_error ("Couldn't parse Cflags.private field into an argument vector: %s\n",
|
||||
error ? error->message : "unknown");
|
||||
if (parse_strict)
|
||||
exit (1);
|
||||
else
|
||||
{
|
||||
g_free (trimmed);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_do_parse_cflags(pkg, argc, argv);
|
||||
|
||||
g_strfreev (argv);
|
||||
g_free (trimmed);
|
||||
pkg->cflags_private_num++;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
parse_url (Package *pkg, const char *str, const char *path)
|
||||
{
|
||||
|
|
@ -914,7 +965,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, gboolean ignore_private_libs,
|
||||
gboolean ignore_requires_private)
|
||||
gboolean ignore_requires_private, gboolean ignore_cflags_private)
|
||||
{
|
||||
char *str;
|
||||
char *p;
|
||||
|
|
@ -979,6 +1030,12 @@ parse_line (Package *pkg, const char *untrimmed, const char *path,
|
|||
else if (strcmp (tag, "Cflags") == 0 ||
|
||||
strcmp (tag, "CFlags") == 0)
|
||||
parse_cflags (pkg, p, path);
|
||||
else if (strcmp (tag, "Cflags.private") == 0 ||
|
||||
strcmp (tag, "CFlags.private") == 0)
|
||||
{
|
||||
if (!ignore_cflags_private)
|
||||
parse_cflags_private (pkg, p, path);
|
||||
}
|
||||
else if (strcmp (tag, "Conflicts") == 0)
|
||||
parse_conflicts (pkg, p, path);
|
||||
else if (strcmp (tag, "URL") == 0)
|
||||
|
|
@ -1096,7 +1153,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_cflags_private)
|
||||
{
|
||||
FILE *f;
|
||||
Package *pkg;
|
||||
|
|
@ -1141,7 +1199,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_cflags_private);
|
||||
|
||||
g_string_truncate (str, 0);
|
||||
}
|
||||
|
|
|
|||
3
parse.h
3
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_cflags_private);
|
||||
|
||||
GList *parse_module_list (Package *pkg, const char *str, const char *path);
|
||||
|
||||
|
|
|
|||
|
|
@ -137,6 +137,13 @@ Libs: -L${libdir} -lfoo</pre>
|
|||
libraries support <tt>pkg-config</tt>, they should be added to
|
||||
<tt>Requires</tt> or <tt>Requires.private</tt>.</li>
|
||||
|
||||
<li><b>Cflags.private</b>: The compiler flags specific to the static version
|
||||
of your package. This may be required if your public headers need to change
|
||||
according to linkage mode, as is for example the case on Microsoft Windows
|
||||
if a library exposes a variable.
|
||||
Don't add any flags for required packages supporting <tt>pkg-config</tt>;
|
||||
<tt>pkg-config</tt> will add those automatically.</li>
|
||||
|
||||
<li><b>Libs</b>: The link flags specific to this package and any required
|
||||
libraries that don't support <tt>pkg-config</tt>. The same rule as
|
||||
<tt>Cflags</tt> applies here.</li>
|
||||
|
|
@ -186,8 +193,9 @@ includedir=${prefix}/include
|
|||
Cflags: -I${includedir}/foo</pre>
|
||||
|
||||
<p>The most important <tt>pkg-config</tt> metadata fields are
|
||||
<tt>Requires</tt>, <tt>Requires.private</tt>, <tt>Cflags</tt>, <tt>Libs</tt>
|
||||
and <tt>Libs.private</tt>. They will define the metadata used by external
|
||||
<tt>Requires</tt>, <tt>Requires.private</tt>, <tt>Cflags</tt>, <tt>Cflags.private</tt>
|
||||
<tt>Libs</tt> and <tt>Libs.private</tt>.
|
||||
They will define the metadata used by external
|
||||
projects to compile and link with the library.</p>
|
||||
|
||||
<p><tt>Requires</tt> and <tt>Requires.private</tt> define other modules
|
||||
|
|
@ -214,9 +222,9 @@ Cflags: -I${includedir}/foo</pre>
|
|||
additional direct dependency.</p>
|
||||
|
||||
<p>Finally, the <tt>Cflags</tt> contains the compiler flags for using the
|
||||
library. Unlike the <tt>Libs</tt> field, there is not a private variant of
|
||||
<tt>Cflags</tt>. This is because the data types and macro definitions are
|
||||
needed regardless of the linking scenario.</p>
|
||||
library. <tt>Cflags.private</tt> contain compiler flags specific to only the
|
||||
static version of the library; they will be used in addition to the regular
|
||||
<tt>Cflags</tt> if <tt>--static</tt> is set.</p>
|
||||
|
||||
<h2><a name="using">Using pkg-config files</a></h2>
|
||||
|
||||
|
|
|
|||
|
|
@ -629,6 +629,14 @@ installed.
|
|||
This line should list the compile flags specific to your package.
|
||||
Don't add any flags for required packages; \fIpkg-config\fP will
|
||||
add those automatically.
|
||||
.TP
|
||||
.I "Cflags.private:"
|
||||
This line should list the compile flags specific to the static version
|
||||
of your package. This may be required if your public headers need to change
|
||||
according to linkage mode, as is for example the case on Microsoft Windows
|
||||
if a library exposes a variable.
|
||||
Don't add any flags for required packages; \fIpkg-config\fP will
|
||||
add those automatically.
|
||||
.\"
|
||||
.SH AUTHOR
|
||||
|
||||
|
|
|
|||
17
pkg.c
17
pkg.c
|
|
@ -50,6 +50,7 @@ gboolean disable_uninstalled = FALSE;
|
|||
gboolean ignore_requires = FALSE;
|
||||
gboolean ignore_requires_private = TRUE;
|
||||
gboolean ignore_private_libs = TRUE;
|
||||
gboolean ignore_cflags_private = TRUE;
|
||||
|
||||
void
|
||||
add_search_dir (const char *path)
|
||||
|
|
@ -300,7 +301,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_cflags_private);
|
||||
g_free (key);
|
||||
|
||||
if (pkg != NULL && strstr (location, "uninstalled.pc"))
|
||||
|
|
@ -1181,6 +1183,7 @@ print_package_list (void)
|
|||
|
||||
ignore_requires = TRUE;
|
||||
ignore_requires_private = TRUE;
|
||||
ignore_cflags_private = TRUE;
|
||||
|
||||
/* Add the packages to a pointer array and sort by pkg->key first, to give
|
||||
* deterministic output. While doing that, work out the maximum key length
|
||||
|
|
@ -1246,3 +1249,15 @@ disable_requires_private(void)
|
|||
{
|
||||
ignore_requires_private = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
enable_cflags_private(void)
|
||||
{
|
||||
ignore_cflags_private = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
disable_cflags_private(void)
|
||||
{
|
||||
ignore_cflags_private = TRUE;
|
||||
}
|
||||
|
|
|
|||
3
pkg.h
3
pkg.h
|
|
@ -84,6 +84,7 @@ struct Package_
|
|||
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 */
|
||||
int cflags_private_num; /* Number of times the "Cflags.private" header has been seen */
|
||||
char *orig_prefix; /* original prefix value before redefinition */
|
||||
};
|
||||
|
||||
|
|
@ -122,6 +123,8 @@ void enable_requires(void);
|
|||
void disable_requires(void);
|
||||
void enable_requires_private(void);
|
||||
void disable_requires_private(void);
|
||||
void enable_cflags_private(void);
|
||||
void disable_cflags_private(void);
|
||||
|
||||
/* If TRUE, do not automatically prefer uninstalled versions */
|
||||
extern gboolean disable_uninstalled;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue