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

Windows Library naming conventions #8153

Closed
jmoguillansky-gpsw opened this issue Jan 4, 2021 · 74 comments
Closed

Windows Library naming conventions #8153

jmoguillansky-gpsw opened this issue Jan 4, 2021 · 74 comments

Comments

@jmoguillansky-gpsw
Copy link
Contributor

Describe the bug
Meson build system currently labels Windows static libraries by default with .a extension in order to distinguish between static and import libs. I understand that Meson supports overriding this behavior with "name_suffix" param.

Shouldn't Meson follow Windows conventions by default?
How does CMake deal with this issue?
Another approach is to use different library names, e.g. lib_xyz.lib and lib_xyz_static.lib or to put the build artifacts in different folders such as static and shared.

Expected behavior
Meson should follow windows convention and name static libs with .lib extension by default.

@Neumann-A
Copy link
Contributor

Just for reference: vcpkg is renaming all static libs to follow the native naming on windows because otherwise CMake and Autotools +pkg-config are completely broken. Since it breaks pkg-config it also breaks meson itself.

@SpaceIm
Copy link

SpaceIm commented Nov 26, 2022

related to #7378

@h-vetinari
Copy link
Contributor

h-vetinari commented Nov 28, 2022

I think the explanation for the conscious choice why things are the way they are is pretty good, but while it solves the collision of import-vs-static libs, it introduces a new collision for artefacts with a mingw ABI vs. MSVC ABI, which is what people are running into, now that the CMake 3.25 has been released, which considers .a on MSVC due to meson's naming choice (complicated by the outrageous Strawberry perl stuff, and the fact that it's installed by default in GHA images).

But I was wondering why it has to be libfoo.a? I get that it's aesthetically appealing to have similarly named artefacts on all platforms, but do the benefits here really outweigh the costs?

How about .lib.a (or .b, or ...)? That way, CMake could provide a saner choice (not considering mingw-built libfoo.a artefacts in MSVC builds, but still consider libfoo.lib.a, i.e. when the artefact has come from meson), and meson could still disambiguate import libs from static libs.

CC @eli-schwartz, I saw you commented on reddit about this. There have been more comments about this on the CMake PR. I don't have a horse in this race, except that - all things considered - I'd prefer more projects to add support for meson (and the breakage caused by this isn't helping that goal particularly AFAICS).

@h-vetinari
Copy link
Contributor

Relevant: CMake has reverted the change to look for libfoo.a on windows under MSVC now.

@jpakkane
Copy link
Member

Does anyone have a proposal for a naming convention that would fix this issue without causing breakage in other cases. IIRC Rust has a different naming scheme for their libs but I don't remember the details (and I looked at that ages ago, maybe it has changed since).

@h-vetinari
Copy link
Contributor

Does anyone have a proposal for a naming convention that would fix this issue without causing breakage in other cases.

See above:

How about .lib.a (or .b, or ...)?

AFAICT, it should be enough choose a different file extension other than vanilla .a on windows.

@eli-schwartz
Copy link
Member

Part of the reason for originally choosing libfoo.a is because GNU and MSVC can mix under some circumstances (of course not including the Strawberry Perl badness) and as mentioned in the FAQ, mingw can only find libraries via -lfoo if they follow one of two particular naming schemes.

I suppose it's not beyond reason for them to add a third (and maybe even popularize convention between meson, gcc, and cmake to fix this problem once and for all).

@h-vetinari
Copy link
Contributor

mingw can only find libraries via -lfoo if they follow one of two particular naming schemes.

Is building on mingw with meson a common usecase (much less mixing in artefacts produced by MSVC)? It seems to me that mingw tends to stay in its own distribution bubble much much more than a cross-platform build tool like meson ever could, so reusing meson-built artefacts in mingw seems to me to be the least widespread1 usecase to sacrifice here...

OTOH, with the speed at which things diffuse in mingw-land (at least from some limited experience), I wouldn't expect a third way to find libraries (even if released today) to be broadly usable before 3-5 years, and presumably this situation should not stay in limbo that long...

Footnotes

  1. citation needed

@eli-schwartz
Copy link
Member

Is building on mingw with meson a common usecase

Yes, because that includes both cygwin and MSYS2 runtime layers. :)

(much less mixing in artefacts produced by MSVC)?

That's a better question. The answer to that is "I dunno".

It's definitely done at least sometimes. @nirbheek can speak about gstreamer usage, for example.

If I had to take a completely wild guess, I'd guess that people who do development with a mingw compiler are significantly more likely to mix the two than people who do development with a MSVC compiler, though!

...

Due to the first part, it's absolutely, unquestionably correct to continue using mingw naming when running the mingw compiler. :D Fortunately, that part is easy to if/else.

Due to the second part, it might be plausible to use .lib.a or whatever if the compiler is MSVC -- we already have a handy self.get_using_msvc() for that (we need to determine whether to use .dll.a or .lib for shared library import libs).

If we did do that:

  • cmake can look for those MSVC-ABI libraries specifically.
  • Meson would probably continue to look for both libfoo.a and libfoo.lib.a as the meson compiler environment isn't leaky and prone to auto-misdetecting Strawberry Perl, so if you're looking for libraries with both ABIs together, you intended to do it.
  • People using non-Meson build systems AND who want to use libraries from both camps, would likely have some fiddling to do, tough luck

@mathstuf
Copy link
Contributor

(FD: CMake developer)

FWIW, I don't find the "but it makes -lfoo work" argument convincing at all. I'd much prefer seeing full paths instead of decay into -L and -l flags for link lines (and searching for libraries at configure time gives you full paths already, so why break them apart in the first place?). Having to debug when decomposition puts some unintended library in front what I actually wanted isn't fun.

@eli-schwartz
Copy link
Member

That's unfortunately totally broken, because full paths hardcode one or the other of static vs. shared libraries.

I do understand that shipping static and shared isn't a use case supported by cmake, so cmake's approach is internally consistent, but... it doesn't work generically, it's a practical problem for Unix users, and it's technically wrong for Windows as well even if in practice windows users often only bother building whichever linkage model will be used by the next step in the application they are currently building without a system library framework.

(But that doesn't mean Windows users never want both!)

Decomposition can't ever find the wrong thing if you do manual searching instead of letting the compiler interpret -l, because it's well within your power to search only in the -L location and ignore unintended libraries in other locations.

That doesn't mean we can't do better! *-config.cmake is inherently unfixable, but pkg-config could be fixed to learn new tricks, such as using a libraries field with split support for specifying the name and static-path: ... + shared-path: ... of the libraries.

... We could even call it "CPS" or something. :p But that is overly verbose, has way too much focus on things people don't need, doesn't nicely handle common pkg-config use cases, like dataonly, and making yet another tool instead of version 2.0 of an existing tool implies making a third ecosystem.

(Freedesktop pkg-config is effectively dead. Everyone tends to use pkgconf instead, these days. The pkgconf developer is interested in incrementally improving .pc files and probably moving to something that has proper quoting, like json. But it's probably a good idea to have the new universal package configuration recording and parsing tool be backwards compatible with the existing state of the art.)

@eli-schwartz
Copy link
Member

(Note also that you still want to be able to emit the flags as -lfoo via an option, because some people want that. e.g. I seem to recall bug reports about libtool breaking horribly otherwise. Yes, I mentioned libtool. I'm deeply sorry to do that to you. ☹️)

@Neumann-A
Copy link
Contributor

hardcode one or the other of static vs. shared libraries.

your approach is already broken so ..... (in exactly the same way on windows)

pkg-config has the cmd line switch --msvc-syntax but meson seems to have ignored that one.

shipping static and shared isn't a use case supported by cmake

that statement is wrong. I see a lot of upstream building both. The difference is that it requires explicit targets to do so instead of implying it.

*-config.cmake is inherently unfixable

You don't mean *-config.cmake. That should be the user generated part and not the CMake generated part.

libtool breaking

libtool already breaks if you try to mix static and shared libs in the lookup unless you explicitly pass lt_cv_deplibs_check_method=pass_all

@eli-schwartz
Copy link
Member

eli-schwartz commented Nov 29, 2022

You don't mean *-config.cmake. That should be the user generated part and not the CMake generated part.

No, I mean the ecosystem which that's an entry point to. The user generated part is broken, and the cmake generated part is also broken.

libtool already breaks if you try to mix static and shared libs in the lookup

No. I mean libtool was breaking when using all shared libs all the time everywhere, if the shared lib is specified via a path instead of -lfoo.

(Why, I could not tell you.)

@mathstuf
Copy link
Contributor

because full paths hardcode one or the other of static vs. shared libraries.

Any specific link should? One already needs to change the link line when switching, so why is this not suitable?

I do understand that shipping static and shared isn't a use case supported by cmake

It's not something supported through a "config" change (i.e., release vs. debug), but projects do indeed do this.

Decomposition can't ever find the wrong thing if you do manual searching instead of letting the compiler interpret -l, because it's well within your power to search only in the -L location and ignore unintended libraries in other locations.

Decomposition can fail with:

  • /lib/libA.so
  • /lib/libB.so
  • /lib2/libB.so

where -L/lib -L/lib2 -lA -lB won't find /lib2/libB.so. I'm talking about the linker here. All we have is the command line to communicate with the linker (last I checked), so how is doing the search manually going to fix that?

*-config.cmake is inherently unfixable, but pkg-config could be fixed to learn new tricks, such as using a libraries field with split support for specifying the name and static-path: ... + shared-path: ... of the libraries.

Yeah, CMake's config files use syntax that is not trivial for anything else to understand. I don't think it's the long-term solution for interop myself either (though I'd be surprised if CMake didn't convert whatever it reads into that format for a long overlap period). As for pkg-config, I think there are things that will be hard-pressed to be specified there, namely combination and reduction rules for flags (e.g., deduping -I flags or knowing that rpath directories are joined with :). I think it could be done for a static list, but my longer-term idea is to support user-defined usage requirements (e.g., "add X to PYTHONPATH to use me", "I have a path for plugins of application Y, please use path Z", or "collect all values of property P and put them into a JSON list"). I don't think a key/value setup is suitable there and some richer structure is required in general.

What I do not want to see is continuation of the "flag soup" that we have today. Not all compilers share flag spellings or even support the same features. There are requirements that depend on usage (e.g., "link to libpython if you are an executable or a plugin not being loaded by something necessarily already aware of Python, otherwise tell the linker to ignore undefined symbols" is not something I think one can express in a .pc without doing bespoke key generation) and trying to spell all of those out is destined for failure IMO.

@nirbheek
Copy link
Member

nirbheek commented Nov 30, 2022

pkg-config has the cmd line switch --msvc-syntax but meson seems to have ignored that one.

We didn't ignore it. We don't use it because it has (had?) a bug where it would blindly put the .lib suffix on incorrect parts of the Libs: line and because doesn't give us anything special anyway. We'd need to manually parse the list of args to get rid of things like -lm or linker args that pkg-config can't translate to MSVC syntax for us.

Decomposition can fail with:

/lib/libA.so
/lib/libB.so
/lib2/libB.so

where -L/lib -L/lib2 -lA -lB won't find /lib2/libB.so. I'm talking about the linker here. All we have is the command line to communicate with the linker (last I checked), so how is doing the search manually going to fix that?

This is actually exactly the case that Meson handles better than most other build systems. If you wanted to pull libA and libB from two different prefixes and they have pkgconfig files, then you'd get:

$ export PKG_CONFIG_PATH=/bar/lib:/foo/lib
$ pkg-config --libs A
-L/foo/lib -lA
$ pkg-config --libs B
-L/bar/lib -lB

If you don't do decomposition, you get a linker line like:

$ cc -o foo -L/foo/lib -lA -L/bar/lib -lB

Which will actually put -Lfoo/lib first and pick up /foo/lib/libB.so. Meson does manual searching for libs while parsing the pkgconfig output so the linker line it generates will be:

$ cc -o foo /foo/lib/libA.so /bar/lib/libB.so

And if you call dependency() with static: true then it will search for static libs instead of shared libs.

Like you say, we only have the command-line to communicate with the linker, so it is up to us to provide APIs for the user to communicate to us (the build system) what they want to do, so we can make sure that the linker does the right thing.

Now, why is it a benefit to have libraries that can be found with -L -l pairs? Because the rest of the world doesn't do all this work. Autotools, Rust, and even make-based custom build systems (like openssl, ffmpeg, etc) expect -L -l pairs to work.

For example, if a Rust crate wants to link to your library using a pkgconfig file (which is something gstreamer, gtk, glib, etc use for Rust bindings), then the build system will need to parse the pkgconfig output and pass it to rustc correctly: https://github.com/rust-lang/pkg-config-rs/blob/master/src/lib.rs#L88-L111

because GNU and MSVC can mix under some circumstances

GNU / MSVC is actually a false split. The actual split is:

  • C++ / C ABI
  • What CRT is being used?

If you want to link libA with libB, if the two are C libraries, all you need to check is what CRT they are using. If both are using MSVCRT or UCRT then you're fine. Else, you can still link them but you need to be careful about memory management: https://learn.microsoft.com/en-us/cpp/c-runtime-library/potential-errors-passing-crt-objects-across-dll-boundaries

If you want to link libA with libB, if the two are C++, they must be built with the same C++ std and ABI, which means they must be built with the same major compiler version. IIRC MSVC breaks C++ ABI across compiler versions, and each C++ std has a different ABI. Also both must be linked to the same CRT.

So, the actual fix that cmake (and meson!) should employ is to check whether the static library contains only C objects, and in that case just link them together if they use the same CRT. And if it contains C++ objects, also check whether the C++ ABI is compatible.

@Neumann-A
Copy link
Contributor

We didn't ignore it. We don't use it because it has (had?) a bug where it would blindly put the .lib suffix on incorrect parts of the Libs: line and because doesn't give us anything special anyway.

This comment was not about meson but outside meson. E.g. generating link lines from pc files for e.g. msbuild.

can't translate to MSVC syntax for us.

that shouldn't happen and means the pc file is incorrect.

@eli-schwartz
Copy link
Member

@mathstuf @bradking,

(I cannot comment on the cmake MR because I cannot seem to find my gitlab.kitware.com password, and I'm not sure how I originally created that account but my current email address isn't getting recovery emails but also seems to say it's already in use. Sorry for discussing this in the wrong place.)

I wonder if maybe the correct long-term solution for CMake is to check for libfoo.a but only for prefix paths that were manually added by the user, not ones that were autodetected from $PATH? It seems like the problem essentially boils down to:

  • users who manually specify that the development environment consists of such and such carefully crafted locations, presumably verified that those libraries are the right ABI
    • assumption historically works for Meson
  • things break when combined with adding automatically detected locations to the development environment
  • it may be possible to analyze found libraries and check whether they are compatible, but it's probably quite a bit of work

I don't know if CMake is set up to make this split between explicit vs. implicit prefixes, but if it could be done then CMake would once again be able to detect Meson-built static libraries, but also autotools ones and, I believe, the ones cmake itself creates when told to use the mingw GCC compiler (and the UCRT as a default CRT).

What do you think?

@bradking
Copy link

bradking commented Dec 2, 2022

things break when combined with adding automatically detected locations to the development environment

I was thinking along those lines too, and have opened CMake Issue 24216 to discuss dropping the PATH-derived search prefixes.

@amyspark
Copy link
Contributor

This also affects using Meson-built libraries from Rust, which hardcodes the MSVC ABI to expect .lib: https://github.com/rust-lang/rust/blob/2ceed0b6cb9e9866225d7cfcfcbb4a62db047163/compiler/rustc_target/src/spec/windows_msvc_base.rs#L15

@xclaesse
Copy link
Member

I was not aware of this thread, and there is indeed something to do in Rust as well... rust-lang/rust#114013.

FWIW, I find Rust's foo.dll.lib name for import lib makes sense. But I don't really understand implications of doing such change in Meson.

@eli-schwartz
Copy link
Member

So rustc produces import libraries that are unusable by mingw GCC which is otherwise capable of linking together mingw+ucrt libraries and MSVC libraries?

It is not clear to me why this is an advantage...

@xclaesse
Copy link
Member

I haven't followed the whole thread here, what's the TL;DR? When doing -lfoo what are the filenames GCC looks for? What are the names MSVC looks for? is there any intersection?

In the likely case there is no intersection, I think ultimately the decision needs to come from the user. Only they know how that lib will be used, so we probably need a global naming_convention: <gcc, msvc, auto> option? That way user can build something with GCC but tell Meson to produce foo.lib instead of libfoo.dll.a because they know it's going to be used by MSVC.

Sorry if I miss the point here, I'm new to this topic, trying to understand.

@eli-schwartz
Copy link
Member

Part of the reason for originally choosing libfoo.a is because GNU and MSVC can mix under some circumstances (of course not including the Strawberry Perl badness) and as mentioned in the FAQ, mingw can only find libraries via -lfoo if they follow one of two particular naming schemes.

The FAQ: https://mesonbuild.com/FAQ.html#why-does-building-my-project-with-msvc-output-static-libraries-called-libfooa

Also try searching mesonbuild/build.py for "libfoo".

@xclaesse
Copy link
Member

The FAQ: https://mesonbuild.com/FAQ.html#why-does-building-my-project-with-msvc-output-static-libraries-called-libfooa

Oh, point 6 there is the part I missed, thanks.

So rustc produces import libraries that are unusable by mingw GCC which is otherwise capable of linking together mingw+ucrt libraries and MSVC libraries?

You mean that with GCC -lfoo won't find foo.dll.lib? It has to be named foo.lib?

@amyspark
Copy link
Contributor

So rustc produces import libraries that are unusable by mingw GCC which is otherwise capable of linking together mingw+ucrt libraries and MSVC libraries?

I'm talking specifically about Microsoft's MSVC, haven't gotten round to testing GCC here.

MSVC cannot find Meson generated libraries. Not because they're wrong in format; rustc tells LINK.EXE that they have the .lib extension (as per the TargetOptions, and per MSVC's own standard), but Meson does that rename to avoid the name clash. This is not detected in any way by rustc, and cannot be handled by Meson except by going over every single dependency and setting the name_suffix appropriately.

@amyspark
Copy link
Contributor

@xclaesse @eli-schwartz Once more, my remarks so far only cover the MSVC compiler -- I've not tried to build gst-plugins-rs with MSYS2, so I cannot comment or offer any insights yet.

@eli-schwartz
Copy link
Member

eli-schwartz commented Aug 18, 2023

MSVC cannot find Meson generated libraries.

MSVC cannot find libraries, it doesn't implement the concept of searching.

rustc tells LINK.EXE that they have the .lib extension (as per the TargetOptions, and per MSVC's own standard),

rustc can tell LINK.EXE whatever rustc wishes to tell it -- and rustc will have to tell it that they have a *.a or *.dll.a extension, if rustc wishes to support interoperability between mingw libraries built against the UCRT and cl.exe libraries, something that is commonly done in ecosystems such as gstreamer that need to build against a variety of open source libraries some of which only have an autotools build system.

MSVC doesn't have a standard, period, so that shouldn't be a problem.

@ChrisDenton
Copy link

ChrisDenton commented Aug 18, 2023

MSVC cannot find Meson generated libraries.

You can use the verbatim link modifier for externs if you're just wanting to link libraries from rust that don't follow the target's conventions. E.g.:

#[link(name = "mylib.a", modifiers = "+verbatim")
extern "C" {
    fn bar();
}

@tristan957
Copy link
Contributor

first world meson problem. You basically never need both at the same time in the same project.

This is completely incorrect. I build static libraries alongside shared libraries all the time in my projects because I link my libraries statically into their test executables. I am not alone in this practice either.

@eli-schwartz
Copy link
Member

Unless something has changed recently,

Correct, it hasn't changed recently.

an MSVC or LLVM produced import library will not be usable by mingw gcc. So there should be a distinction to prevent accidentally using the wrong lib, imho.

Wrong, because it is usable...

I mean it's the reason that windows-rs produces separate import libraries for different toolchains even if they're the same target platform.

Perhaps gcc has improved recently and is more interoperable now. But that certainly didn't used to be the case.

I don't think it makes sense to imagine that "what windows-rs does" can be generalized to all cases. You keep saying that mingw GCC didn't "used to" be able to do things that people have been doing for a very long time (probably longer than rust has existed) but it's not clear to me what that's based on -- I suspect concern that it can't be made foolproof, so better to forbid anyone from doing it no matter how much they beg to be allowed and insist they know what they are doing?

What's gotten better is that modern Windows has the UCRT, and modern mingw can target the UCRT, which means better standards conformance and less need to take care in writing your source code to specifically cope with fragilities that were for a long time part of what people doing this sort of mixing considered to be a standard and accepted requirement of doing so safely.

Note that this mixing was always opt in, not opt out... you had to actually install both toolchains and add search paths of one into the other.

There are already static-only fields (Requires.private), so one (technically) needs to know ahead of time anyways. I don't see why Libs.shared and Libs.static couldn't exist. Not to mention that there are libraries like hdf5 which need different compile flags on Windows for shared vs. static (there's one set of headers and to get the declspec right, H5_BUILT_AS_DYNAMIC_LIB and H5_BUILT_AS_STATIC_LIB need to be correct).

My understanding was that it's considered widely accepted practice on Windows to have one define, not two, and a number of projects from the Unix world specifically arranged for that to be the define for linking statically for exactly this reason. (There's some interesting insight in libass/libass@c5ee66d, which points out that for simplicity some projects which only care about functions, totally ignore dllimport and eat an object pointer cost in order to ensure that linking works no matter what.)

But either way I suspect it's very much a non-issue, you can just do both. Stick -DH5_BUILT_AS_DYNAMIC_LIB in the shared flags and -UH5_BUILT_AS_DYNAMIC_LIB -DH5_BUILT_AS_STATIC_LIB in the static flags. People using the maintained version of pkgconf have Cflags.private support and the -U flag correctly overrides the previous flag. Command lines are a bit longer.

Sure, more options can be added to make that prettier. But it's no hard blocker.

@Neumann-A
Copy link
Contributor

This is completely incorrect. I build static libraries alongside shared libraries all the time in my projects because I link my libraries statically into their test executables. I am not alone in this practice either.

For what reason are you doing this? In the worst case you are not testing the same generated code you are deploying....
What you probably want instead is to link the obj files of the shared build instead of the static library. Also if you are trying to argue for a practice you are applying in meson to argue for a default meson supplies the argument automatically becomes invalid due to it being a circular argumentation.

@mathstuf
Copy link
Contributor

But either way I suspect it's very much a non-issue, you can just do both. Stick -DH5_BUILT_AS_DYNAMIC_LIB in the shared flags and -UH5_BUILT_AS_DYNAMIC_LIB -DH5_BUILT_AS_STATIC_LIB in the static flags. People using the maintained version of pkgconf have Cflags.private support and the -U flag correctly overrides the previous flag. Command lines are a bit longer.

Do we have a specification on how flags should be put together? Because if the order here is flipped, things don't work.

Just to note, this is my general unhappiness with .pc files and any "here's a pile of flags"-style dependency management: they act without context and may contradict each other and it's (usually) up to the linker to detect problems by which point a lot of useful context for a decent error message has been lost.

@xclaesse
Copy link
Member

I'm not the one who's going to defend pkg-config, it has no formal spec, it's implementation is terrible and most projects get it wrong. But there we are, it is so widely used across OSS that we can't ignore it, and we can barely even improve it... Until at least all major distro switch to pkgconf, looking at you debian...

Regardless, back to original topic, I think requirement for a naming convention are:

  • No clash between static and import lib name.
  • Both static and shared libs should be found by gcc in the form -lfoo
  • Be as close as possible to platform's default as long as the 2 conditions above are respected.

Current status:

  • I think meson has a pretty good naming given those conditions.
  • Cmake is willing to support that has well, judging from the MR they had to revert. AFAIK they should be able to reinstate that MR if they exclude system PATH?
  • Rustc is currently broken, not sure how they are willing to improve that. IMHO a simple fix for them could just to expose a command line argument to define the import lib name, so the build system can make/override the decision.

Did I miss something?

@tristan957
Copy link
Contributor

This is completely incorrect. I build static libraries alongside shared libraries all the time in my projects because I link my libraries statically into their test executables. I am not alone in this practice either.

For what reason are you doing this? In the worst case you are not testing the same generated code you are deploying....
What you probably want instead is to link the obj files of the shared build instead of the static library. Also if you are trying to argue for a practice you are applying in meson to argue for a default meson supplies the argument automatically becomes invalid due to it being a circular argumentation.

Arguing with you has proven to be a waste of time on multiple forums.

@Neumann-A
Copy link
Contributor

I think meson has a pretty good naming given those conditions.

Nope I think meson could do better. I mean somebody already suggested different folders so why not have different output folders on windows like shared/static on build time and decide what to actually install on install time. The static test linkage tristan957 mentions seems more to be a build time thing instead.

But there we are, it is so widely used across OSS

Strictly speaking pkg-config on windows is not really a thing unless you use MinGW and than the naming issue doesn't really exist. It works yes but since there is no defined directory layout pc files always struggle with relocateablity if not explicitly fixing the prefix. MSVC also has to differentiate between debug/release CRT which pkg-config simply cannot do. (How does meson even want to fix that dilemma btw?). This also has a unsolved naming conflict which hasn't been broadly discussed yet. So there is not only the static/shared name conflict but also the release/debug name conflict.

I mean vcpkg solution is quite straight forward here. Only allow one library type and one configuration type per project/prefix.

Arguing with you has proven to be a waste of time on multiple forums.

Yeah it gets is increasingly difficult to argue with me if you don't have any good arguments.

@eli-schwartz
Copy link
Member

The static test linkage tristan957 mentions seems more to be a build time thing instead.

It is one of many uses. It's also standard in many places to, well, ship both so that people can make their own decision which to use. Obviously, this is Unix exclusive behavior, because building libraries in advance once and distributing them to many people is a Unix exclusive urge... but that's convention and the desire to be useful to downstream users, not a hard requirement...

It works yes but since there is no defined directory layout pc files always struggle with relocateablity if not explicitly fixing the prefix.

What? No. This is totally false, although also totally typical of people who hate pkg-config so much that they'd rather be unable to use it effectively than give up the opportunity to complain about it every chance they get.

I mean vcpkg solution is quite straight forward here. Only allow one library type and one configuration type per project/prefix.

Okay. So do that. Run meson once per type, and install it with different relocatable prefixes. MSVC can then differentiate all it wants between debug/release and static/shared and any combination thereof.

It's certainly a style choice of some sort. But there's nothing stopping you from making it.

However, installing different prefixes for each type of library does mean that you'll need to build all code generators, data, binaries, etc twice and install them twice or you simply won't have them available for use inside of totally different prefixes, which seems particularly unfortunate for something as easily solved as naming static/shared libraries with names that allow the build system to distinguish between the two when using find_library(foo).

@xclaesse
Copy link
Member

xclaesse commented Aug 21, 2023

For example, GStreamer project ships prebuilt development kit that contains both libgstreamer-1.0.a and libgstreamer-1.0.dll.a in lib/ subdir. Their pkg-config files are relocatable by using prefix=${pcfiledir}/../.. and has Libs: -L${libdir} -lgstreamer-1.0. That means that an app developer can use pkg-config to use either shared or static libs as they wish.

But they provide different MSI that install into different locations for MSVC/Mingw and 32/64bits: https://gstreamer.freedesktop.org/download.

An app developer would build their Meson project with PKG_CONFIG_PATH=C:\gstreamer\1.0\msvc_x86_64\lib\pkgconfig meson setup builddir, and have dependency('gstreamer-1.0', static: true_or_false_as_you_wish) in their meson.build. Note how you are sure to not mix CRT because you point pkg-config to a msvc specific folder.

I'm not saying that's a hugely important use-case, clearly not how most project distribute for Windows, but it's a use-case that exists and we can/should support.

@Neumann-A
Copy link
Contributor

distributing them to many people is a Unix exclusive urge.

I think this was more driven by technological limitations of the past which nowadays seems to generates more issues than it solves by having "seemingly" outdated stuff if you don't build yourself anyway.

What? No. This is totally false

So how many packages generate pc files that actually install using pcfiledir instead of prefix=<some_abs_path> (or manually passing --define-variable)? I mean there is a reason why vcpkg has vcpkg_fixup_pkgconfig() to make pc files relocatable and remove any absolute paths in it. Also I don't hate on pc files. They kind of work, just the mixing of static/shared shouldn't have been done.

you'll need to build all code generators

vcpkg has host-triplets and code generators are only build for the host and not for the target (if it at all can be deactivated). This means packages with code generators have a host dependency on themselves to build the actual code generators. (vcpkg forces meson to use None.txt as a native file). But IMHO projects should only focus on the target architecture for better modularity, but that is a totally different discussion.

solved as naming static/shared libraries with names that allow the build system to distinguish between the two when using find_library(foo).

again you neglect debug/release configuration which is the only one CMake needs to be able to distinguish on MSVC. Since a lot of projects don't add debug suffixes to debug builds it is basically impossible to do that without using different prefixes. Furthermore CMake uses cache variables so you can to explicit set it if necessary.

For example, GStreamer project ships

gstreamer uses meson.... again a cyclic argument. The MSVC gstreamer build in vcpkg actually renames the static meson output to reflect MSVC default behavior.
I also can tell that the pc file for the MSVC distribution is broken for static builds due to mesons naming conventions.

That means that an app developer can use pkg-config to use either shared or static libs as they wish.

pkg-config needs the --static keyword to link statically but that generates issues/runs into limitations if you want to have mixed linkage of other dependent libraries.

@xclaesse
Copy link
Member

xclaesse commented Aug 21, 2023

@Neumann-A I think there is a reason why mixing static/shared in a build makes sense, but not mixing debug/release or different ABIs. It is because you can make both shared and static libraries out of the same .o objects without recompiling. Arguably it's rarely the case for Windows (but not impossible), but it works on all other platforms, which makes it a not so niche use-case. If you make different ABIs, or debug/release builds, you have to recompile everything twice anyway, so better install into different prefix.

The MSVC gstreamer build in vcpkg actually renames the static meson output to reflect MSVC default behavior.

Why are they doing that? AFAIK that's because CMake's fine_library() won't find libgstreamer.a otherwise? But I saw that CMake seems to be willing to support Meson's naming, so it could just be a temporary workaround until CMake supports that naming. Once that's done we are all good?

Also, isn't it already working for CMake projects that relies on pkg-config file generated by Meson anyway?

@Neumann-A
Copy link
Contributor

Why are they doing that?

As I said the pc file for gstreamer is broken for static linkage for MSVC without renaming (cli: --msvc-syntax). CMake lookup is just another thing which breaks.

@xclaesse
Copy link
Member

I don't think they are broken, I think they rely on the fact that Meson will resolve -lfoo using Meson's convention instead of using --msvc-syntax. Meson resolves -lfoo from pkg-config the same way it resolves find_library, CMake could do the same. As pointing in #8153 (comment), --msvc-syntax is not reliable anyway.

I know that this sounds like Meson imposing its convention on CMake, but it really feels like Meson does have a better proposal with strong rational. Is there really a downside in adopting that convention if CMake is willing to do it?

@eli-schwartz
Copy link
Member

So how many packages generate pc files that actually install using pcfiledir instead of prefix=<some_abs_path> (or manually passing --define-variable)?

I haven't done a study on the topic. I do know for example that this is one of the reasons meson recommends using the builtin .pc file generator, since it can get this correct automatically.

vcpkg has host-triplets and code generators are only build for the host and not for the target (if it at all can be deactivated). This means packages with code generators have a host dependency on themselves to build the actual code generators. (vcpkg forces meson to use None.txt as a native file). But IMHO projects should only focus on the target architecture for better modularity, but that is a totally different discussion.

Sounds like quite a bit of work which is then ignored half the time by projects that don't support it. But it also misses the issue of built artifacts that aren't C/C++ libraries. e.g. common in toolkits.

again you neglect debug/release configuration which is the only one CMake needs to be able to distinguish on MSVC.

No, I didn't ignore it, I said that instead of 4 prefixes one for each combination I think it makes sense to have two prefixes for debug/release configuration and then

which seems particularly unfortunate for something as easily solved as naming static/shared libraries with names that allow the build system to distinguish between the two when using find_library(foo).

would allow having each of those two prefixes "easily solve" the static/shared split by providing both in one prefix.

gstreamer uses meson.... again a cyclic argument. The MSVC gstreamer build in vcpkg actually renames the static meson output to reflect MSVC default behavior.

This is not a cyclic argument???

The argument is that people who use meson or autotools find the meson/autotools behavior useful and rely on it. How can you dismiss that by arguing that "they only find it useful because they use meson/autotools".

And I'm sure gstreamer has been doing this since before they migrated to meson.

@xclaesse
Copy link
Member

So how many packages generate pc files that actually install using pcfiledir instead of prefix=<some_abs_path> (or manually passing --define-variable)?

FYI, every Meson project can do that simply by using -Dpkgconfig.relocatable=true: https://mesonbuild.com/Builtin-options.html#pkgconfig-module. GStreamer however still has old code that fixup pc files in the same way vcpkg does.

amyspark added a commit to amyspark/pkg-config-rs that referenced this issue Aug 21, 2023
Although there's a clear MSVC convention of calling import libraries
"xxxx.lib", when a build system creates both static and shared
libraries, a race condition will be caused [1].

To this end, the Meson build system decided to also apply the GNU
convention for the MSVC ABI [2], which is not considered in
pkg-config-rs.

[1]: https://aomedia-review.googlesource.com/c/aom/+/173603
[2]: mesonbuild/meson#8153
@Neumann-A
Copy link
Contributor

convention instead of using --msvc-syntax

WTF?! pc files also need to work as intended outside of meson. meson is not a closed of ecosystem ..... also we are not speaking about meson & cmake alone there is also qmake/qbs/scons/autotools/b2/bazel/makefiles/perl scripts etc. and the pc file needs to be correct for any build system to come in the future....

But it also misses the issue of built artifacts that aren't C/C++ libraries. e.g. common in toolkits.

Everything is build somehow. You either build from source or install/extract binaries directly into the directories as you want. If it is something which needs to run on the host it is a host dependency. Everything can be provided somehow.

The argument is that people who use meson or autotools find the meson/autotools behavior useful and rely on it. How can you dismiss that by arguing that "they only find it useful because they use meson/autotools".

I can be dismissed by the fact that simply because I use x doesn't indicate that x useful or that x even makes sense. If you argue for x due to people using x that is a cyclic argument. Or other way said: You cannot tell why people use x. It might be because there is no similar alternative or they simply dislike y or z even though z is the objectively better or correct solution/answer.

And I'm sure gstreamer has been doing this since before they migrated to meson.

Nope, the MSI installer just shipped MinGW builds (I checked 1.45 and 1.6.4). (considering their dependencies this is no wonder.) So they will probably be fine with any naming reflecting MinGW naming and won't notice the difference to native MSVC naming.

But let me apply displayed meson contributor logic here: The existence of this issue proofs that mesons naming convention is flawed on MSVC because otherwise the issue and the discussion around it would simply not exist.

@eli-schwartz
Copy link
Member

Nope, the MSI installer just shipped MinGW builds (I checked 1.45 and 1.6.4). (considering their dependencies this is no wonder.) So they will probably be fine with any naming reflecting MinGW naming and won't notice the difference to native MSVC naming.

But isn't what we're doing right now, already the thing that they are fine with? And which they wanted to do, and are doing, and are relying on?

But let me apply displayed meson contributor logic here: The existence of this issue proofs that mesons naming convention is flawed on MSVC because otherwise the issue and the discussion around it would simply not exist.

No, it proves that meson's naming convention has reasons for as well as reasons against.

The idea of a concept that has both pros and cons isn't novel to computer science or to C++ libraries or even to meson. I have never argued against the idea of a concept that has both pros and cons (though I might feel the cons are misguided, or that there are better solutions).

Your standard stock in trade, however, is to argue against the idea of a concept that has both pros and cons. You do this, for example, by protesting that any suggestion of a pro is "circular logic".

And when Tristan says "arguing with you has proven to be a waste of time on multiple forums" this is exactly what he's talking about -- the fact that any conversation with you, has a tendency to turn into "meson is not only wrong, but stupid with it, meson should apologize for its insolence and change and drop support for existing OSS workflows that rely on this functionality".

Which is apparently the only acceptable outcome, because it "works for vcpkg because we build everything five times after patching the sources to search for prefix-installed versions of any build machine tools" due to "modularity".

Needless to say, the idea that build systems should only work pleasantly inside vcpkg is not an attractive idea to me. The fact that meson has real, correct cross compilation support by mixing build and host machines together into a unified single-project configuration in cases where internal, uninstalled intermediate code generators are used, is actually something that quite a few people are very grateful to meson for -- we're not about to revert to cmake levels of hackery because vcpkg thinks it's weird.

And it's really not a compelling argument against people wanting to build their project once for release and once for debug and shipping a general purpose release SDK that meets a variety of needs and doesn't involve building large data assets multiple times or shipping multiple copies of them for spurious reasons.

@xclaesse
Copy link
Member

@Neumann-A The problem is pretty simple: The VS default of using foo.lib for both static and shared libraries does not work because it cause a file collision. Turn it the way you want, one of them MUST have a different name. Given the options we have, I think renaming the static library to libfoo.a is what makes the most sense. What else do you propose? Meson is not to blame for the flaw of the default VS convention...

Yes that requires some cooperation between build systems. CMake is willing to support Meson's proposal, but seems temporally unable to do that because they admit themself they abuse of PATH (https://gitlab.kitware.com/cmake/cmake/-/issues/24216).

Most other build system are pretty terrible with MSVC+pkg-config to begin with. Not sure which one actually has something that works?

@Neumann-A
Copy link
Contributor

@xclaesse: No the problem is meson trying to support a scenario which isn't common to the platform instead of deferring the solution of said problem to the building problem. I fully understand the file/target name problem on windows you don't need to reiterate on it.

What else do you propose?

Don't assume that both libraries are build by default at the same time on windows. Only allow building one and then use the platform default name. If somebody wants to opt-in to meson multi library type solution feel free to add an option for that. There is no reason why single library type builds should pay a naming fee or why projects should manually set the name.

Meson is not to blame for the flaw of the default VS convention...

Ah the blame game. Lets fill in some facts:

Meson made the decision to build both types of libraries as such meson could be blamed for the following:

  • a file name conflict on Windows with MSVC
  • it had to break file name conventions to solve the above problem
  • its own generated pc files don't work correctly with pkg-config and MSVC due to the static lib name

the VS naming existed before meson so meson should have adjusted to it accordingly. Also they are not flawed they are just what they are humanly defined conventions.

Most other build system are pretty terrible with MSVC+pkg-config to begin with

They could at least work if the pc file is correct? But no chance if the pc file is already incorrect. However, I again see here the behavior to not own the responsibility for a design decision and just blame somebody else.

@eli-schwartz:

But isn't what we're doing right now, already the thing that they are fine with? And which they wanted to do, and are doing, and are relying on?

Why are we only talking about gstreamer? gstreamer was given as an argument for x behavior in meson for MSVC. However, gstreamer was not directly build with MSVC before? MinGW != MSVC. gstreamer probably simply doesn't know better so it will use the behavior meson dictates and as such the behavior of the current gstreamer MSI Installer cannot be used as an argument to support (or go against) mesons naming.

No, it proves that meson's naming convention has reasons for as well as reasons against.

Yes you can make a list and I would probably argue that the cons are bigger than the pros on Windows, however if you land in the territory of contradictory behavior you should know that something is broken. So where is the contradiction in meson? Ok lets read point 5 in https://mesonbuild.com/FAQ.html#why-does-building-my-project-with-msvc-output-static-libraries-called-libfooa.
Since -lfoo works out of the box, pkgconfig files will work correctly for projects built with both MSVC, GCC, and Clang on Windows. This sentence is simply not true for static libraries with the current naming convention using MSVC. Point 6 is ok but the linker will emit a warning and point 3 is nice for consistent naming but not really an argument (could lead to unintended mixing if people are not careful).

Which is apparently the only acceptable outcome, because it "works for vcpkg because we build everything five times after patching the sources to search for prefix-installed versions of any build machine tools" due to "modularity"....... The fact that meson has real, correct cross compilation support by mixing build and host machines together into a unified single-project configuration in cases where internal, uninstalled intermediate code generators are used, is actually something that quite a few people are very grateful to meson for

I use vcpkg as an example to demonstrate which problem was observed and how it was solved. vcpkg only builds the amount required. OT: How many times does meson build the host part if you target N architectures and want a clean working dir for every architecture? Mixing host(native)/target(cross) builds in one build description is a convenience but simply doesn't scale correctly if you cannot simply reuse the host build. /OT

Needless to say, the idea that build systems should only work pleasantly inside vcpkg is not an attractive idea to me.

That is not the target. The target is to make the build system work correctly with windows and deliver correct pc files for consumption. If the build system delivers that then vcpkg will seamless work with it as will probably conan or any other package manager. However, meson does not fulfill this requirement of at least correct pc files for static builds using MSVC. It also doesn't play nice with CMake by default due to the naming decision. (It will work with the automake compile wrapper but not everybody using autotools is also using automake...)

we're not about to revert to cmake levels of hackery

It not hackery. I think CMake made a concise decision to not directly integrate it into the build but defer the solution to the user. The same applies to building both static/shared libraries at the same time. It is simply up to the user to implement if they want/need it. As such CMake doesn't need to solve problems which are unrelated of creating a pure build description for a project. As a side note I personally like Qt6 take on solving cross builds in cmake.

So TL;DR
libraries names need to:

  • fit into the rest of the world (which the current naming doesn't as shown by the cmake and platform naming conventions)
  • agree with what the pc file/pkgconf will say (libfoo.a isn't -lfoo on windows but foo.lib)

@xclaesse
Copy link
Member

Note that the discussion has been focused on Meson's usage of libfoo.a static library name, but if I understand correctly @nirbheek here #8153 (comment), you can also build libfoo.a with mingw and UCRT which makes them compatible with MSVC, right? So the problem is not new and not limited to Meson, or did I miss something?

@nirbheek
Copy link
Member

@xclaesse correct, and gstreamer actually already does this. Our "MSVC" builds are actually building meson projects with MSVC and Autotools projects with MinGW and linking them together. It works fine because everything is using UCRT.

We also have Autotools (MinGW) projects picking up and linking to Meson (MSVC) built binaries via pkg-config, and it all works because of Meson's default Windows library naming conventions. For the same reason, we are able to port Autotools projects to Meson and everything continues to work as-is.

MSVC and MinGW artifacts are fully compatible. The only difference is that you won't get PDB info from the MinGW artifacts.

The same is also done by gvsbuild, IIRC, and MSYS2 has a UCRT64 variant specifically to allow this.

@nirbheek
Copy link
Member

it introduces a new collision for artefacts with a mingw ABI vs. MSVC ABI

There is no difference between the MSVC and MinGW C ABIs, so there is no collision either.

The only reason there's a difference between naming of MSVC DLLs and MinGW DLLs is because the libfoo.dll naming scheme is ONLY used by MinGW (Autotools). The purpose was to allow Meson to be a drop-in replacement for Autotools in projects that were shipping both during the transition period. The same naming was not used for MSVC because Windows DLLs do not start with lib, so that's pretty much a convention.

The only thing to be careful about is that there are different CRTs, and if you mix them, you need to be careful about passing CRT objects across DLL boundaries:

  • MSVCRT (obsolete, used by ancient MinGW and MSVC compilers)
  • UCRT -Db_vscrt=md (default, used by current MinGW and MSVC compilers)
  • UCRTD -Db_vscrt=mdd (UCRT debug)

There is no naming convention to differentiate these. Some projects will append d at the end of the name for artifacts that use the debug CRT so that you can ship both debug and release in the same directory, but that just makes these libraries harder to pick up automatically.

So, in practice, it's acceptable to mix MinGW and MSVC artifacts, and GStreamer and GTK (and projects using GStreamer/GTK) and other projects have been doing this for over a decade, before Meson even existed.

The convention is to put debug vs release in separate directories. This is already what Visual Studio and Cargo do. When shipping aggregates of artifacts, you should just use separate trees (prefixes).

And of course if you're using C++ all this goes out the window, because there is no C++ ABI stability. Any of these can change the ABI:

  • Different C++ std
  • Different compilers
  • Different compiler versions
  • Debug vs release
  • Exceptions disabled vs not
  • and more

Library naming cannot do anything here. C++ static libraries are only usable as intermediate formats inside the builddir, and should not be redistributed.

@nirbheek
Copy link
Member

libraries names need to:

  • fit into the rest of the world (which the current naming doesn't as shown by the cmake and platform naming conventions)

  • agree with what the pc file/pkgconf will say (libfoo.a isn't -lfoo on windows but foo.lib)

pkg-config's --msvc-syntax mode is just a "simple and stupid" mode added in 2001 to allow people to pass the output of pkg-config directly to cl and link in nmake scripts. I have no idea why you think it should be a basis for a convention today. This is what the commit message says:

New Win32 feature to make pkg-config useful for users of MSVC:
with the flag --msvc-syntax, munge -L and -l flags appropriately
for the MSVC command-line compiler. (-I flags are the same.)

And this is what the man page says:

This option is available only on Windows. It causes pkg-config
to output -l and -L flags in the form recognized by the Microsoft
Visual C++ command-line compiler, cl. Specifically, instead of
-Lx:/some/path it prints /libpath:x/some/path, and instead
of -lfoo it prints foo.lib. Note that the --libs output
consists of flags for the linker, and should be placed on the cl
command line after a /link switch. 

So the purpose is to avoid outputting flags that the MSVC compiler doesn't understand. It's not meant to be "a flag that you should use to find libraries built with MSVC on Windows". You (and other projects like pkg-config-rs) are misusing it.

You should be using the -L and -l pairs received from each pc file to do a manual search and passing the full path to the library to the compiler. When you aggregate /LIBPATH and foo.lib from multiple pc files on a single link line, you can end up picking the library from the wrong library path.

No one should be passing --msvc-syntax today, 22 years later when we have modern build systems and not raw makefiles.

Don't assume that both libraries are build by default at the same time on windows. Only allow building one and then use the platform default name

Does anyone even know why MSVC uses the same name for import libraries and static libraries? I don't think there's a good reason for it at all.

Do you know how MSVC solves this naming collision for UCRT? If you want to link to the UCRT dynamically (/MD), you link to ucrt.lib (import library). If you want to link to UCRT statically (/MT), you link to libucrt.lib (static library). Same for the C++ runtime library and other CRT libs: https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=msvc-170

Amazing! So even Microsoft knows that this naming collision is problematic, and their solution breaks your so-called "convention". I guess we should petition Microsoft to "fit into the rest of the world" 😉

I am baffled that your "solution" for the file collision is to pretend it doesn't exist. After reading your comments on this issue, I am inclined to agree with @tristan957 that you're too closed-minded to see other people's problems.

The core problem here is that there is no "rest of the world" or "convention" around publishing and discovering aggregates of libraries / include directories on Windows. Visual Studio doesn't even provide a way to "install" a package somewhere outside the builddir. Best you can do is to export/import a nupkg, but how do you ship aggregate frameworks that are a combination of libraries from separate FOSS projects? This is something needed by everyone: Qt, GTK, OpenCV, FFmpeg, GStreamer, etc.

Conventions around such things are always created by open-source communities, and MinGW was the first community to attempt to make a convention around this on Windows. They, obviously, based their system around what is done in the UNIX world, to make a prefix and put everything in it:

  • DLLs go into bin/ next to executables
  • Static libraries and import libraries go into lib/
  • Headers go into include/
  • How to compile or link to a package is discovered via pc files in share/pkgconfig/. Same with cmake package files.

This is the same convention that Meson inherits, and hence we need to solve the filename collision.

People who do not need to work in this fashion (proprietary projects) can ignore the filename collision, but that doesn't change the fact that other people care about it.

@xclaesse
Copy link
Member

I think this should close the debate here. It seems that all Meson devs agree that current naming is the best compromise available and that will not be changed. This is also what Autotools does when built with UCRT which is compatible with MSVC, so this is not an issue specific to Meson.

Other build systems should adapt to find libraries built with libfoo.a name. Prior PR shows CMake is willing to do it but they are blocked by CMake specific issue that they can work on. Time would probably be better spent helping them with that issue.

I opened a Meson PR to document the UCRT story as an extra argument for our naming choice: #12163.

Closing this issue as I think everything has been said already. Thanks everyone for your input!

@tristan957
Copy link
Contributor

Don't assume that both libraries are build by default at the same time on windows.

I would be interested in seeing more discussion around this point if other people would find that agreeable because it seems like a good compromise for both positions being argued in this ticket.

@xclaesse
Copy link
Member

xclaesse commented Aug 27, 2023

@tristan957 even if you don't build both at the same time, you could still install both in the same location. That's what MSYS2 does AFAIK:

image

With #11981 Meson will be able to build both at the same time (configure once but compile twice automatically).

@xclaesse
Copy link
Member

When compiling with MSVC you can set PKG_CONFIG_PATH=C:\msys64\ucrt64\lib\pkgconfig to use those libraries.

amyspark added a commit to amyspark/pkg-config-rs that referenced this issue Jan 16, 2024
Although there's a clear MSVC convention of calling import libraries
"xxxx.lib", when a build system creates both static and shared
libraries, a race condition will be caused [1].

To this end, the Meson build system decided to also apply the GNU
convention for the MSVC ABI [2], which is not considered in
pkg-config-rs.

[1]: https://aomedia-review.googlesource.com/c/aom/+/173603
[2]: mesonbuild/meson#8153
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests