Bug 275969 - converters/libiconv: Unable to build without including /usr/local/include/iconv.h
Summary: converters/libiconv: Unable to build without including /usr/local/include/ico...
Status: Open
Alias: None
Product: Ports & Packages
Classification: Unclassified
Component: Individual Port(s) (show other bugs)
Version: Latest
Hardware: Any Any
: --- Affects Some People
Assignee: freebsd-desktop (Team)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-12-27 17:06 UTC by Rodrigo
Modified: 2023-12-29 08:32 UTC (History)
2 users (show)

See Also:
bugzilla: maintainer-feedback? (bofh)


Attachments
Build log (95.89 KB, application/gzip)
2023-12-27 22:35 UTC, Rodrigo
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Rodrigo 2023-12-27 17:06:52 UTC
Hi,

I'm trying to add FreeBSD as another OS in the continuous integration of the Dillo browser that depends on iconv, FLTK and other libraries in ports.

While the configure script runs, the libc is interrogated first in case it already provides a working iconv library, which it does, so it is configured as the iconv provider.

The problem I'm having is that FLTK from ports requires -I/usr/local/include, as that is the place where the headers are included in FreeBSD.

However, that causes the iconv.h file to also be picked from /usr/local/include, which is not compatible with the one in /usr/include, provided by the libc.

This problem causes a linkage error, as /usr/local/include/iconv.h prefixes the iconv_* functions as libiconv_*.

I tried to work around this issue, without having to switch to libiconv from ports, but I'm afraid there is no combination of -I flags that can override the search order. Adding -I/usr/include doesn't work, as it is already in the system search paths, I have more details here:

https://github.com/dillo-browser/dillo/issues/41

I saw the same problem with other ports and the workaround seems to always end up adding libiconv as a dependency. I would like to find another solution before doing so, so I can keep the dependency with the libc only (even if libiconv is installed).

I suspect one way would be to install libconv into /usr/local/include/iconv/..., so other packages have to include it manually by using the proper -I. Another solution that I saw in Arch Linux is to place the headers into libiconv.h instead of iconv.h:

https://gitlab.archlinux.org/archlinux/packaging/packages/libiconv/-/blob/9776068fe291e0653f5267aebdf31d5976a12593/PKGBUILD#L42

Do you have any other solution?

Best,
Rodrigo.
Comment 1 Muhammad Moinur Rahman freebsd_committer freebsd_triage 2023-12-27 17:19:54 UTC
Hi,

Do you have a buildlog somewhere?

So far I can say that changing the iconv header loacation will be a big change as there are currently 750 ports using this. I will look into hacking Mk/Uses/iconv.mk.

The way iconv.mk is designed it should not call the header from LOCALBASE/PREFIX if iconv.h already exists in the base.
Comment 2 Muhammad Moinur Rahman freebsd_committer freebsd_triage 2023-12-27 18:16:35 UTC
I think you have mixed up two different ports. One is converters/iconv and other is converters/libiconv which are different in terms of functionalities. While one is the library the other is the utilities for conversion. I am reassigning it to appropriate ones.
Comment 3 Gleb Popov freebsd_committer freebsd_triage 2023-12-27 18:32:21 UTC
The gotcha here is that you need to also pass -DLIBICONV_PLUG when including iconv from localbase.
Comment 4 Rodrigo 2023-12-27 22:35:16 UTC
Created attachment 247303 [details]
Build log
Comment 5 Rodrigo 2023-12-27 22:58:59 UTC
> Do you have a buildlog somewhere?

I attached the build log.

> I think you have mixed up two different ports. One is converters/iconv and other is converters/libiconv which are different in terms of functionalities.

Sorry, I didn't realize they were split :-)

> The gotcha here is that you need to also pass -DLIBICONV_PLUG when including iconv from localbase.

I tested that and it links properly.

However, the problem remains: I'm including /usr/local/include/iconv.h and linking with -lc which also provides an iconv implementation. With the LIBICONV_PLUG the libiconv functions don't get the "lib" prefix.

I'm guessing libiconv and libc try to provide compatible headers, but it seems a bit fragile to depend on that. So I was looking for a way to avoid including the /usr/local/include/iconv.h file and just include the one provided by the libc.

And in case there is none, I can instead link with -liconv, which at least would make more sense than depending on the headers to remain compatible among both implementations.

Best,
Rodrigo.
Comment 6 Gleb Popov freebsd_committer freebsd_triage 2023-12-28 06:15:15 UTC
> However, the problem remains: I'm including /usr/local/include/iconv.h and linking with -lc which also provides an iconv implementation. With the LIBICONV_PLUG the libiconv functions don't get the "lib" prefix.

> I'm guessing libiconv and libc try to provide compatible headers, but it seems a bit fragile to depend on that.

What's the problem with this approach? This is exactly what Ports framework do. By passing -DLIBICONV_PLUG you make it indifferent for the software you're compiling whether 3rd party libiconv is installed or not.
Comment 7 John Hein 2023-12-28 22:39:45 UTC
Doesn't dillo already build via the www/dillo2 port?  And so you could just use that for your CI.  FWIW, the www/dillo2 port does include /usr/local/include/iconv.h (and does build with -DDLIBICONV_PLUG).  And it does not link with /usr/local/lib/libiconv.so.

Maybe you are trying to avoid depending on the FreeBSD ports infrastructure for you continuous integration setup.  I guess that's a reasonable goal for the upstream CI.

That said, if you want to coerce the build to include /usr/include/iconv.h instead of /usr/local/include/iconv.h (for #include <iconv.h>), you can use '-isystem /usr/include' or '-isystem /usr/include -isystem /usr/local/include'.

That may work for using /usr/include/iconv.h (vs /usr/local/include/iconv.h).  But it may not work if you wanted header files from /usr/local/include/openssl (vs /usr/include/openssl).

Any time you have two choices for a library on any platform, you are going to run into potential conflicts that may be hard to resolve unless the build system for a project is set up specifically to support such an option (there are ways to do this).  Usually on FreeBSD in these situations for building most upstream projects, it is most manageable to prefer the libs / include files in LOCALBASE if there is a choice that exists in both the base system (/usr/include & /lib & /usr/lib) and also in LOCALBASE.
Comment 8 Rodrigo 2023-12-29 00:06:17 UTC
Hi,

> > I'm guessing libiconv and libc try to provide compatible headers, but it 
> > seems a bit fragile to depend on that.

> What's the problem with this approach? This is exactly what Ports framework do. 
> By passing -DLIBICONV_PLUG you make it indifferent for the software you're 
> compiling whether 3rd party libiconv is installed or not.

The problem is that I don't have a choice to include /usr/include/iconv.h
instead of /usr/local/include/iconv.h while using FLTK.

Using the plug flag relies on the promise that the libiconv header is
compatible with the libc implementation, which may be fine, but I cannot
choose otherwise.

> Doesn't dillo already build via the www/dillo2 port?  And so you could just
> use that for your CI.  FWIW, the www/dillo2 port does include 
> /usr/local/include/iconv.h (and does build with -DDLIBICONV_PLUG).
> And it does not link with /usr/local/lib/libiconv.so.
>
> Maybe you are trying to avoid depending on the FreeBSD ports infrastructure for 
> you continuous integration setup.  I guess that's a reasonable goal for the 
> upstream CI.
 
Yes, it should build reasonably fine from source directly, which is what we test
in the CI.

> That said, if you want to coerce the build to include /usr/include/iconv.h
> instead of /usr/local/include/iconv.h (for #include <iconv.h>), you can use
> '-isystem /usr/include' or '-isystem /usr/include -isystem /usr/local/include'.
>
> That may work for using /usr/include/iconv.h (vs /usr/local/include/iconv.h).
> But it may not work if you wanted header files from /usr/local/include/openssl
> (vs /usr/include/openssl).
>
> Any time you have two choices for a library on any platform, you are going to
> run into potential conflicts that may be hard to resolve unless the build
> system for a project is set up specifically to support such an option (there
> are ways to do this).

That is why I was suggesting to maybe install libiconv in a prefixed path like
/usr/local/include/libiconv/, so only one iconv.h header is present in either
/usr/include or /usr/local/include.

By default it will just include /usr/include/iconv.h and link with the libc
(which is what I would expect). But if I wanted to use libiconv, I could just
use:

  CPPFLAGS="-I/usr/local/include/libiconv" LDFLAGS="-I/usr/local/lib/libiconv" 

With no risk of accidentally including libiconv headers when adding
/usr/local/include for other ports.

I understand that this may require a lot of rebuilds for depending packages,
and that using the -DLIBICONV_PLUG flag may be a good compromise.

My comment was to manifest that this situation is happening, and I think it
should be changed eventually.

In Dillo I can either link with libiconv if I detect it before checking libc,
or use the plug flag.

> Usually on FreeBSD in these situations for building most upstream projects,
> it is most manageable to prefer the libs / include files in LOCALBASE if there
> is a choice that exists in both the base system (/usr/include & /lib & /usr/lib)
> and also in LOCALBASE.

That's what I had in mind too.
Comment 9 John Hein 2023-12-29 03:04:04 UTC
(In reply to Rodrigo from comment #8)
> The problem is that I don't have a choice to include /usr/include/iconv.h
> instead of /usr/local/include/iconv.h while using FLTK.

Of course you have a choice.  But the way the dillo build is constructed, it's just harder.  The only source files that include <iconv.h> are src/decode.c and src/form.cc.  Those are the only files that need to prefer searching for system include files in /usr/include before /usr/local/include.  And neither of those files need fltk header files.

So you CAN build a project with /usr/include/iconv.h and /usr/local/include/FL/*.h.  It's just more difficult the way dillo's build is set up.  Some projects support different -I options for different source files.  Dillo [right now] is just not one of those such projects.


> That is why I was suggesting to maybe install libiconv in a prefixed path like
> /usr/local/include/libiconv/, so only one iconv.h header is present in either
> /usr/include or /usr/local/include.

That's not an unreasonable setup (other projects do that: e.g., /usr/local/include/openssl, /usr/local/include/apache24, /usr/local/include/nss to name just a few).  But it's probably a heavier lift to get all the FreeBSD ports that are currently able to build with the current libiconv pkg to look in /usr/local/include/libiconv instead of /usr/local/include.  Maybe with a strategic change in Mk/Uses/iconv.mk, it might be not be too bad.

It also might not be too hard to modify the dillo build to support using a different set of -I options to the build of src/form.cc and src/decode.c.  I'm not sure which would be more easily get accepted (dillo build change or freebsd change to converters/libiconv).  But first step is to come up with a patch and get it reviewed.


Yet another option...

Here's another option.  Create a sym link in the build area that point to the desired iconv.h.  Then the existing -I (or -isystem) flags that point to paths within the dillo build area would be sufficient.  That might be the easiest path.


> > Usually on FreeBSD in these situations for building most upstream projects,
> > it is most manageable to prefer the libs / include files in LOCALBASE if there
> > is a choice that exists in both the base system (/usr/include & /lib & /usr/lib)
> > and also in LOCALBASE.
>
> That's what I had in mind too.

Then just use the the the headers / libs from the libiconv pkg for the iconv needs instead of libc & /usr/include/iconv.h.  You are already dependent on one package (fltk).  What's one more?
Comment 10 Gleb Popov freebsd_committer freebsd_triage 2023-12-29 08:32:40 UTC
(In reply to Rodrigo from comment #8)
> The problem is that I don't have a choice to include /usr/include/iconv.h
instead of /usr/local/include/iconv.h while using FLTK.

You just don't need to. When passed -DLIBICONV_PLUG the localbase iconv.h behaves exactly as base iconv.h. If it is not - then it is a bug that should be fixed.