Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated pkg-config file contain linker flags for uninstalled static libraries #3934

Closed
ebassi opened this issue Jul 24, 2018 · 13 comments
Closed

Comments

@ebassi
Copy link
Contributor

ebassi commented Jul 24, 2018

If a library target A depend on an uninstalled static library target B, pkgconfig.generate() will add -lB to the Libs.private key of the pkg-config file.

Meson version: 0.47.1

Example, taken from Geoclue:

  • public-api/meson.build:
libgeoclue_public_api_lib = static_library('geoclue-public-api',
  libgeoclue_public_api_gen_sources,
  dependencies: base_deps,
)

libgeoclue_public_api = declare_dependency(link_with: libgeoclue_public_api_lib,
  sources: gclue_enum_types_h,
  include_directories: include_directories('.'),
  dependencies: base_deps,
)
  • libgeoclue/meson.build:
libgeoclue_lib = library('geoclue-2',
  libgeoclue_sources,
  include_directories: config_inc,
  dependencies: base_deps + [
    libgeoclue_public_api,
  ],
  soversion: '0',
  version: '0.0.0',
  install: true,
)

pkgconf = import('pkgconfig')
pkgconf.generate(libgeoclue_lib,
  name: 'Geoclue Client Library',
  description: 'A convenience library to interact with Geoclue service',
  version: gclue_version,
  filebase: 'libgeoclue-' + gclue_api_version,
  subdirs: [ header_dir ],
)
  • generated libgeoclue-2.0.pc file:
prefix=/home/ebassi/gnome/install
libdir=${prefix}/lib
includedir=${prefix}/include

Name: Geoclue Client Library
Description: A convenience library to interact with Geoclue service
Version: 2.4.10
Requires.private: glib-2.0 >=  2.34.0, gio-2.0 >=  2.34.0, gio-unix-2.0 >=  2.34.0
Libs: -L${libdir} -lgeoclue-2
Libs.private: -L${libdir} -lgeoclue-public-api
Cflags: /home/ebassi/gnome/install/include/libgeoclue-2.0

The -lgeoclue-public-api is wrong, and will cause any user of libgeoclue-2.0 to break.

@xclaesse
Copy link
Member

Don't you need libgeoclue-public-api.a when doing a static link witth libgeoclue-2.a? In geoclue master I see it uses link_whole and -lgeoclue-public-api is not in the generated pc file. I think that's correct, isn't it?

@xclaesse
Copy link
Member

The -lgeoclue-public-api is wrong, and will cause any user of libgeoclue-2.0 to break.

Only when using it for static link. When using the shared library Libs.private is not used, AFAIK.

@ebassi
Copy link
Contributor Author

ebassi commented Jul 24, 2018

It shouldn't really matter: libgeoclue-public-api.a is not installed, so it should be folded into the installed libgeoclue-2.0.so shared library.

There are a lot of projects that use internal static libraries to build an installed shared library; the internal dependency object should be enough — you shouldn't need to use link_whole.

The reason why link_whole is not enough, incidentally, is that libgeoclue-public-api depends on generated files; using an internal dependency object allows us to correctly express the dependencies transitively.

@xclaesse
Copy link
Member

If you're not going to provide static libraries, then use shared_library() instead of library(). As far as I know the generated pc file is correct for static links, and you must install libgeoclue-public-api.a.

@xclaesse
Copy link
Member

Note that meson's pc generator special case shared_library() to not pull its dependencies, exactly for the case you're describing. But since geoclue uses library() it means it wants to provide the static library.

@ebassi
Copy link
Contributor Author

ebassi commented Jul 24, 2018

That's a bit of a trap, though…

@xclaesse
Copy link
Member

Note that at least on Ubuntu the libgeoclue-dev package does provide libgeoclue.a, so I think using link_whole and library() as in geoclue master is the right thing to do.

@ebassi
Copy link
Contributor Author

ebassi commented Jul 24, 2018

Using link_whole breaks the build in two ways:

  • the generated enumeration files are not built before libgeoclue is compiled
  • if I add a link_whole and a dependency on the sources, I still get a broken build because the exported symbols are not found

@ebassi
Copy link
Contributor Author

ebassi commented Jul 24, 2018

Reference to actual working code: https://gitlab.freedesktop.org/geoclue/geoclue/merge_requests/8

@nirbheek
Copy link
Member

I think this related to #3937. link_with: on non-installed static libraries should work as expected, and should not require a link_whole: because that bloats the shared library.

nirbheek added a commit that referenced this issue Jul 25, 2018
This commit contains the following fixes:

1. When a shared library A does `link_with:` to static library B, the
   parts of B used by A will be added to A, and so we don't need to
   return B in A.get_dependencies() for targets that link to A. This
   already is the behaviour when a shared library A does `link_whole:`
   on B.

2. In situation (1), when generating a pkg-config file for A, we must
   also not add B to Libs.private for A. This already is the behaviour
   when a shared library A does `link_whole:` on B.

3. When a static library A does `link_whole:` to static library B, we
   must add the objects in B to A.

4. When a static library A does `link_with:` to static library B, and
   B is not installed (which makes it an internal static library), we
   must add the objects in B to A, otherwise nothing can use A.

5. In situation (4), when generating a pkg-config file for A, we must
   also not add B to Libs.private for A.

All these situations are tested by the unit test added in this commit.

Closes #3934
Closes #3937
@nirbheek nirbheek added this to the 0.48.0 milestone Aug 7, 2018
nirbheek added a commit that referenced this issue Aug 7, 2018
This commit contains the following fixes:

1. When a shared library A does `link_with:` to static library B, the
   parts of B used by A will be added to A, and so we don't need to
   return B in A.get_dependencies() for targets that link to A. This
   already is the behaviour when a shared library A does `link_whole:`
   on B.

2. In situation (1), when generating a pkg-config file for A, we must
   also not add B to Libs.private for A. This already is the behaviour
   when a shared library A does `link_whole:` on B.

3. When a static library A does `link_whole:` to static library B, we
   must add the objects in B to A.

4. When a static library A does `link_with:` to static library B, and
   B is not installed (which makes it an internal static library), we
   must add the objects in B to A, otherwise nothing can use A.

5. In situation (4), when generating a pkg-config file for A, we must
   also not add B to Libs.private for A.

All these situations are tested by the unit test added in this commit.

Closes #3934
Closes #3937
nirbheek added a commit that referenced this issue Aug 14, 2018
This commit contains the following fixes:

1. When a shared library A does `link_with:` to static library B, the
   parts of B used by A will be added to A, and so we don't need to
   return B in A.get_dependencies() for targets that link to A. This
   already is the behaviour when a shared library A does `link_whole:`
   on B.

2. In situation (1), when generating a pkg-config file for A, we must
   also not add B to Libs.private for A. This already is the behaviour
   when a shared library A does `link_whole:` on B.

3. When a static library A does `link_whole:` to static library B, we
   must add the objects in B to A.

4. When a static library A does `link_with:` to static library B, and
   B is not installed (which makes it an internal static library), we
   must add the objects in B to A, otherwise nothing can use A.

5. In situation (4), when generating a pkg-config file for A, we must
   also not add B to Libs.private for A.

All these situations are tested by the unit test added in this commit.

Closes #3934
Closes #3937
nirbheek added a commit that referenced this issue Aug 19, 2018
This commit contains the following fixes:

1. When a shared library A does `link_with:` to static library B, the
   parts of B used by A will be added to A, and so we don't need to
   return B in A.get_dependencies() for targets that link to A. This
   already is the behaviour when a shared library A does `link_whole:`
   on B.

2. In situation (1), when generating a pkg-config file for A, we must
   also not add B to Libs.private for A. This already is the behaviour
   when a shared library A does `link_whole:` on B.

3. When a static library A does `link_whole:` to static library B, we
   must add the objects in B to A.

4. When a static library A does `link_with:` to static library B, and
   B is not installed (which makes it an internal static library), we
   must add the objects in B to A, otherwise nothing can use A.

5. In situation (4), when generating a pkg-config file for A, we must
   also not add B to Libs.private for A.

All these situations are tested by the unit test added in this commit.

Closes #3934
Closes #3937
@fanc999
Copy link
Contributor

fanc999 commented Aug 29, 2018

Hi,

Is this the same issue that I am hit by here? When I try to build GLib for instance with Visual Studio+Ninja, my glib-2.0.pc contains the following for Libs.private:

Libs.private: -L${libdir} -lcharset -lgnulib -lpcre -lws2_32 -lwinmm

Note the part where it says -lcharset and -lgnulib, which are static .lib's that are internal to the glib-2.0-0.dll that I am trying to build

Likewise for the generated gio-2.0.pc:
Libs.private: -lintl -L${libdir} -lgiowin32 -lzlib1 -lintl -lshlwapi -ldnsapi -liphlpapi -lws2_32

Note the part where it says -lgiowin32, which is a static .lib that is internal to the gio-2.0-0.dll that I am trying to build.

These static .lib's get in the way when I try to build items using Meson that depends on these pkg-config files, as these static .lib's would not be found since they won't be installed, so as a workaround I need to remove them from these pkg-config files before I try to build any other projects using Meson that depends on them.

With blessings, and cheers, and thank you!

@nirbheek
Copy link
Member

@fanc999 yes, it's the same issue. Can you try the patch in #3939?

nirbheek added a commit that referenced this issue Sep 14, 2018
This commit contains the following fixes:

1. When a shared library A does `link_with:` to static library B, the
   parts of B used by A will be added to A, and so we don't need to
   return B in A.get_dependencies() for targets that link to A. This
   already is the behaviour when a shared library A does `link_whole:`
   on B.

2. In situation (1), when generating a pkg-config file for A, we must
   also not add B to Libs.private for A. This already is the behaviour
   when a shared library A does `link_whole:` on B.

3. When a static library A does `link_whole:` to static library B, we
   must add the objects in B to A.

4. When a static library A does `link_with:` to static library B, and
   B is not installed (which makes it an internal static library), we
   must add the objects in B to A, otherwise nothing can use A.

5. In situation (4), when generating a pkg-config file for A, we must
   also not add B to Libs.private for A.

All these situations are tested by the unit test added in this commit.

Closes #3934
Closes #3937
nirbheek added a commit that referenced this issue Sep 14, 2018
This commit contains the following fixes:

1. When a shared library A does `link_with:` to static library B, the
   parts of B used by A will be added to A, and so we don't need to
   return B in A.get_dependencies() for targets that link to A. This
   already is the behaviour when a shared library A does `link_whole:`
   on B.

2. In situation (1), when generating a pkg-config file for A, we must
   also not add B to Libs.private for A. This already is the behaviour
   when a shared library A does `link_whole:` on B.

3. When a static library A does `link_whole:` to static library B, we
   must add the objects in B to A.

4. When a static library A does `link_with:` to static library B, and
   B is not installed (which makes it an internal static library), we
   must add the objects in B to A, otherwise nothing can use A.

5. In situation (4), when generating a pkg-config file for A, we must
   also not add B to Libs.private for A.

All these situations are tested by the unit test added in this commit.

Closes #3934
Closes #3937
nirbheek added a commit that referenced this issue Sep 14, 2018
This commit contains the following fixes:

1. When a shared library A does `link_with:` to static library B, the
   parts of B used by A will be added to A, and so we don't need to
   return B in A.get_dependencies() for targets that link to A. This
   already is the behaviour when a shared library A does `link_whole:`
   on B.

2. In situation (1), when generating a pkg-config file for A, we must
   also not add B to Libs.private for A. This already is the behaviour
   when a shared library A does `link_whole:` on B.

3. When a static library A does `link_whole:` to static library B, we
   must add the objects in B to A.

4. When a static library A does `link_with:` to static library B, and
   B is not installed (which makes it an internal static library), we
   must add the objects in B to A, otherwise nothing can use A.

5. In situation (4), when generating a pkg-config file for A, we must
   also not add B to Libs.private for A.

All these situations are tested by the unit test added in this commit.

Closes #3934
Closes #3937
@nirbheek nirbheek modified the milestones: 0.48.0, 0.49.0 Sep 20, 2018
buildroot-auto-update pushed a commit to buildroot/buildroot that referenced this issue Aug 15, 2019
Switch back to autotools to fix static build with rygel (and so reverts
partially commit 66a3fbb
"package/gupnp: bump to version 1.0.4").

Indeed gupnp uses meson's subproject feature for guul which is just
plainly broken on static build with meson, see:
mesonbuild/meson#3934
mesonbuild/meson#3937
mesonbuild/meson#3939

This will fix a build failure with rygel

Fixes:
 - http://autobuild.buildroot.org/results/ebbf96a1be5547e416feb1e96e55986890d0a1de

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
eli-schwartz added a commit to eli-schwartz/pacman that referenced this issue Sep 19, 2019
libcommon isn't even installed, so that means libalpm.a (if installed)
is fatally broken as it misses objects. The problem is that meson
doesn't handle this case correctly:

mesonbuild/meson#3934
mesonbuild/meson#3937
mesonbuild/meson#3939

Work around this by manually extracting libcommon's .o files into the
list of objects used to create libalpm.
@xclaesse
Copy link
Member

xclaesse commented Oct 1, 2019

Should be fixed by #5936

@xclaesse xclaesse closed this as completed Oct 1, 2019
eworm-de pushed a commit to eworm-de/pacman that referenced this issue Oct 7, 2019
libcommon isn't even installed, so that means libalpm.a (if installed)
is fatally broken as it misses objects. The problem is that meson
doesn't handle this case correctly:

mesonbuild/meson#3934
mesonbuild/meson#3937
mesonbuild/meson#3939

Work around this by manually extracting libcommon's .o files into the
list of objects used to create libalpm.

Signed-off-by: Eli Schwartz <eschwartz@archlinux.org>
Signed-off-by: Allan McRae <allan@archlinux.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants