madler / zlib

A massively spiffy yet delicately unobtrusive compression library.
http://zlib.net/
Other
5.65k stars 2.44k forks source link

Problem installing libzip and minizip together. #977

Closed audetto closed 4 months ago

audetto commented 4 months ago

Hi,

I realised there is an issue if both libzip and minizip are installed in the same system.

Once they are installed pkg-config -cflags reports

-I/usr/include for libzip -I/usr/include/minizip for minizip

Then, when I try to include zip.h (which is present in both locations), this comes from minizip (if I add its -I) or from libzip. I think the fact that minizip's location is not a default location, means that when it is used it takes priority.

All good.

Except if they are both installed in a non default location: e.g. if I compile it myself or, the real problem: on FreeBSD.

For some reason, in FreeBSD they go to /usr/local/include, so if both -I are added, then it becomes ambiguous. Problem is that -I/usr/local/include might be necessary for other libs.

What is the correct way to install and include minizip so that it does not clash with libzip?

madler commented 4 months ago

I'm not getting it. Where do the two zip.h's end up on FreeBSD?

audetto commented 4 months ago

This is not FreeBSD specific, but in FreeBSD it is easier to trigger.

  1. I maintain an emulator which uses minizip: https://github.com/audetto/AppleWin
  2. I am not trying to use libzip and minizip at the same time
  3. I only want to use minizip
  4. But users (beyond my control) might have installed the libzip dev package

Comparing Ubuntu and FreeBSD helps in understanding

FreeBSD:

/usr/local/include/zip.h /usr/local/include/minizip/zip.h

and pkg-config -cflags says -I/usr/local/include -I/usr/local/include/minizip

Ubuntu, similar, but in a more standard location /usr/include/zip.h /usr/include/minizip/zip.h

and pkg-config -cflags says -I/usr/include -I/usr/include/minizip

So, now, in both cases there is an apparent ambiguity, if I do #include <zip.h>, but this seems to be resolved in Ubuntu by the fact that /usr/include is special and searched last, so when I do in my makefile -I/usr/include/minizip, this takes priority and minizip is found.

Some of this is pure speculation.

In FreeBSD, because the location is non standard: /usr/local/include, the special treatment of -I/usr/local/include is lost and we are back in the ambiguous case where the order of -I matters.

  1. why FreeBSD uses local? no idea, but I don't think it is forbidden
  2. why is -I/usr/local/include added? again, maybe it is needed by other libs, I can't remove it
  3. it is effectively forbidden to install libzip dev files anywhere other than /usr/include

But, it seems very easy to avoid all of this. If minizip pkg-config did not add /minizip then I would have to include it as #include <minizip/zip.h> and no ambiguity would exist.

I can tweak my build system (overriding minizip -I), but it looks to me a very inelegant solution and I wanted to understand if I have missed anything.

kiyolee commented 4 months ago

FreeBSD has been using /usr/local for third parties (freebsd ports) software for decades. It is some well established standard there and works for majority of packages available through freebsd ports. I think the problem is more with libzip that it does not put headers in a separate directory like minizip. However, that is also very common for many software not doing so. But unforturnately it just happens that two relatively popular software packages (minizip and libzip) both have a file named zip.h. I think pkg-config is doing the right thing for both packages and indeed on FreeBSD a lot of packages for which pkg-config would simply return /usr/local/include. Seeing a long list of repeating /usr/local/include when building freebsd ports packages is pretty common. The problem is not particularly different on Linux distros either. Most Linux distros just put everything in /usr/include and the conflict of zip.h between libzip and minizip does exist in the same way for build systems which rely on pkg-config. I think it is understandably why FreeBSD and many Linux distros would just use default installation location for libzip. Otherwise, many software packages may need the same treatment even when there is nothing being in conflict. My preferred solution would be either libzip or minizip renames their zip.h to something else.

madler commented 4 months ago

I guess I'm still missing something. Why don't you simply #include <minizip/zip.h> for minizip, and/or #include <zip.h> for libzip? (You could, in fact, use them both at the same time if you were so inclined.) As needed, you would only use one -I, e.g. -I/usr/include or -l/usr/local/include, which will cover both includes.

It seems to me that the installations are all de-conflicting the two zip.h's just fine. The ambiguity is being introduced by you, with two -I's, when you only need one.

audetto commented 4 months ago

The ambiguity is introduced by pkg-config, or better the way it configured here:

https://github.com/madler/zlib/blob/0f51fb4933fc9ce18199cb2554dacea8033e7fd3/contrib/minizip/minizip.pc.in#L4

user@pc$ pkg-config minizip -cflags
-I/usr/include/minizip 

I think it is a good standard not to hardcode any path, but to rely on pkg-config where it exists.

Here, we are saying that although pkg-config exists and is configured for minizip, it can't be used as-is. And since distros might install minizip without zip, I can't ask where zip is.

So, the (inelegant) solution is to append /.. to the path returned by pkg-config.

madler commented 4 months ago

Ah, ok. Thanks. I didn't know that that was coming from the minizip contribution. I will delete /minizip from that configuration file. This will undoubtedly mess up users of minizip and pkg-config, but even so the right thing to do is #include <minizip/zip.h> and #include <minizip/unzip.h>.