diff --git a/check/Makefile.am b/check/Makefile.am index 68c6d84..618a90a 100644 --- a/check/Makefile.am +++ b/check/Makefile.am @@ -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 \ diff --git a/check/check-cflags-private b/check/check-cflags-private new file mode 100755 index 0000000..544f1d3 --- /dev/null +++ b/check/check-cflags-private @@ -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 diff --git a/check/private-cflags.pc b/check/private-cflags.pc new file mode 100644 index 0000000..0cfbdfd --- /dev/null +++ b/check/private-cflags.pc @@ -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 + diff --git a/main.c b/main.c index cfebdba..7bc560e 100644 --- a/main.c +++ b/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 */ diff --git a/parse.c b/parse.c index f4a1baa..39a63cd 100644 --- a/parse.c +++ b/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); } diff --git a/parse.h b/parse.h index db1bf86..6135a4e 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_cflags_private); GList *parse_module_list (Package *pkg, const char *str, const char *path); diff --git a/pkg-config-guide.html b/pkg-config-guide.html index c666fe5..79335ff 100644 --- a/pkg-config-guide.html +++ b/pkg-config-guide.html @@ -137,6 +137,13 @@ Libs: -L${libdir} -lfoo libraries support pkg-config, they should be added to Requires or Requires.private. +
  • Cflags.private: 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 pkg-config; + pkg-config will add those automatically.
  • +
  • Libs: The link flags specific to this package and any required libraries that don't support pkg-config. The same rule as Cflags applies here.
  • @@ -186,8 +193,9 @@ 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 + Requires, Requires.private, Cflags, Cflags.private + 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 @@ -214,9 +222,9 @@ Cflags: -I${includedir}/foo additional direct dependency.

    Finally, the Cflags contains the compiler flags for using the - library. Unlike the Libs field, there is not a private variant of - Cflags. This is because the data types and macro definitions are - needed regardless of the linking scenario.

    + library. Cflags.private contain compiler flags specific to only the + static version of the library; they will be used in addition to the regular + Cflags if --static is set.

    Using pkg-config files

    diff --git a/pkg-config.1 b/pkg-config.1 index a147fc8..8272d15 100644 --- a/pkg-config.1 +++ b/pkg-config.1 @@ -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 diff --git a/pkg.c b/pkg.c index 4c1523a..202c944 100644 --- a/pkg.c +++ b/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; +} diff --git a/pkg.h b/pkg.h index c6732bd..09dd255 100644 --- a/pkg.h +++ b/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;