Opened 2 years ago

Closed 2 years ago

Last modified 4 months ago

#57821 closed defect (invalid)

libiconv breaks compatibility with OS-provided

Reported by: mouse07410 (Mouse) Owned by: ryandesign (Ryan Schmidt)
Priority: Normal Milestone:
Component: ports Version:
Keywords: Cc: essandess (Steve Smith)
Port: libiconv

Description

libiconv port changes the names of the functions it provides from likes of iconv_open to likes of libiconv_open. This makes it impossible to use Macports components (such as gcc8) with 3rd-party stuff like Haskell GHC-8.4.3 compiler whose libraries were linked against {/usr/lib/libiconv.dylib}.

Here's how the problem manifests itself:

Linking dist/build/tests/tests ...
Undefined symbols for architecture x86_64:
  "_iconv", referenced from:
      _hs_iconv in libHSbase-4.11.1.0.a(iconv.o)
     (maybe you meant: _base_GHCziIOziEncodingziIconv_iconvEncoding16_closure, _base_GHCziIOziEncodingziIconv_iconvEncoding1_info , _base_GHCziIOziEncodingziIconv_iconvEncoding3_closure , 
. . . . . _
base_GHCziIOziEncodingziIconv_iconvEncoding6_info , _base_GHCziIOziEncodingziIconv_iconvEncoding2_info , _base_GHCziIOziEncodingziIconv_iconvEncoding11_closure , _base_GHCziIOziEncodingziIconv_iconvEncoding13_bytes , _hs_iconv , _base_GHCziIOziEncodingziIconv_iconvEncoding_info , _hs_iconv_close , _base_GHCziIOziEncodingziIconv_iconvEncoding12_closure , _base_GHCziIOziEncodingziIconv_iconvEncoding_closure , _base_GHCziIOziEncodingziIconv_iconvEncoding2_closure , _base_GHCziIOziEncodingziIconv_iconvEncoding14_info , _base_GHCziIOziEncodingziIconv_iconvEncoding12_info )
  "_iconv_open", referenced from:
      _hs_iconv_open in libHSbase-4.11.1.0.a(iconv.o)
     (maybe you meant: _hs_iconv_open)
  "_iconv_close", referenced from:
      _hs_iconv_close in libHSbase-4.11.1.0.a(iconv.o)
     (maybe you meant: _hs_iconv_close)
  "_locale_charset", referenced from:
      _localeEncoding in libHSbase-4.11.1.0.a(PrelIOUtils.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
`clang' failed in phase `Linker'. (Exit code: 1)
make: *** [build] Error 1

I wonder why it was decided to add prefix lib to the function names, and wish this was reverted.

Coincidentally, I'm stymied trying to understand why it does not try to link against what's in /usr/lib.

Change History (25)

comment:1 Changed 2 years ago by ryandesign (Ryan Schmidt)

Cc: ryandesign@… removed
Owner: set to ryandesign
Status: newassigned

comment:2 Changed 2 years ago by ryandesign (Ryan Schmidt)

Resolution: invalid
Status: assignedclosed

The libiconv port works as intended. Mangling of function names is normal. The developers of libiconv have engineered it to work this way specifically so that it does not conflict with an OS-provided iconv library, which, depending on the OS, may or may not be libiconv. See #43698 for a prior discussion of this situation.

I don't know why you're having whatever problem you're having, but it is not a bug in the libiconv port. If you need help resolving it, you could ask on the MacPorts mailing lists.

comment:3 Changed 2 years ago by mouse07410 (Mouse)

depending on the OS...

But this is a Macports version of libiconv - therefore the only OS it should target (e.g., via Macports patches) should be MacOS, right?

Also, the name of the library does collide - which makes it impossible to use packages that require, e.g., a modern (Macports-installed) OpenSSL that resides in /opt/local/lib and OS-provided libiconv that resides in /usr/lib. If I don't add /opt/local/lib - then all the older OS-provided libraries would be used, in which case what's the point of using Macports? And if I add /opt/local/lib before the default /usr/lib - then /opt/local/lib/libiconv.dylib gets used because it carries the same name as /usr/lib/libiconv.dylib.

If the developers were concerned about the conflict with an OS-provided iconv library - why on earth did they keep exactly the same name? To ensure the conflict would occur, by binary distributions linked with one library stumbling upon the other?

Comrade Stalin used to say about such cases "Ни Богу свечка, ни чёрту кочерга".

If you need help resolving it, you could ask on the MacPorts mailing lists

Could you please point me at the appropriate mailing list? Thanks!

Last edited 2 years ago by mouse07410 (Mouse) (previous) (diff)

comment:4 in reply to:  3 Changed 2 years ago by ryandesign (Ryan Schmidt)

Replying to mouse07410:

depending on the OS...

But this is a Macports version of libiconv - therefore the only OS it should target (e.g., via Macports patches) should be MacOS, right?

Yes, but that doesn't really matter. The developers of libiconv have decreed that a system copy of libiconv shall not mangle the function names, and any third-party copies of libiconv shall mangle the names. MacPorts is a third party, so its copy of libiconv does mangle the names.

Also, the name of the library does collide - which makes it impossible to use packages that require, e.g., a modern (Macports-installed) OpenSSL that resides in /opt/local/lib and OS-provided libiconv that resides in /usr/lib. If I don't add /opt/local/lib - then all the older OS-provided libraries would be used, in which case what's the point of using Macports? And if I add /opt/local/lib before the default /usr/lib - then /opt/local/lib/libiconv.dylib gets used because it carries the same name as /usr/lib/libiconv.dylib.

One solution, if you want to ensure that you use the system iconv and not MacPorts libiconv, but you still want to use other libraries like openssl from MacPorts, is to create a new directory anywhere, and inside that, create lib and include directories, and inside those, put symlinks to the system iconv files. Then add -I and -L flags to your build system pointing to those directories. Place those flags before the flags that point to the MacPorts directories.

If the developers were concerned about the conflict with an OS-provided iconv library - why on earth did they keep exactly the same name? To ensure the conflict would occur, by binary distributions linked with one library stumbling upon the other?

Comrade Stalin used to say about such cases "Ни Богу свечка, ни чёрту кочерга".

I cannot answer this; ask the developers. They probably are not reading this ticket and won't see your questions here.

If you need help resolving it, you could ask on the MacPorts mailing lists

Could you please point me at the appropriate mailing list? Thanks!

Our lists are here:

https://www.macports.org/contact.php#Lists

The macports-users list is probably appropriate for this question.

comment:5 Changed 2 years ago by mouse07410 (Mouse)

The developers of libiconv have decreed that a system copy of libiconv shall not mangle the function names, and any third-party copies of libiconv shall mangle the names. MacPorts is a third party, so its copy of libiconv does mangle the names

And I find their decision to be extremely bad for the problems it is causing, as described here and in the other ticket #43698.

One solution, if you want to ... use the system iconv and not MacPorts libiconv, but ... other libraries like openssl from MacPorts

Yes, thank you - this might work (and is a good advice). Except that I don't see how Macports-provided binaries could work together with, e.g., Haskell and Haskell-built binaries. For example, Haskell invokes either gcc or clang - and Macports versions require Macports iconv.

The macports-users list is probably appropriate for this question

Will try that, thanks.

Another possibility probably is making a fake port of iconv that simply points at the system iconv, and forcing Macports to use that one. And force-rebuild less than 300 ports on one machine, and less than 600 ports on another. ;-) What do I need to do to create such a fake port?

comment:6 in reply to:  5 Changed 2 years ago by ryandesign (Ryan Schmidt)

Replying to mouse07410:

One solution, if you want to ... use the system iconv and not MacPorts libiconv, but ... other libraries like openssl from MacPorts

Yes, thank you - this might work (and is a good advice). Except that I don't see how Macports-provided binaries could work together with, e.g., Haskell and Haskell-built binaries. For example, Haskell invokes either gcc or clang - and Macports versions require Macports iconv.

The library search paths specified with -L and the header search paths specified with -I are only relevant at build time. After a tool like gcc8 has been built with those flags, those flags are no longer relevant for it. gcc8 will happily use whichever iconv library it was built to use, because it's linked with it by its absolute path—no search paths are involved. Which iconv library your tools use should have no bearing on what iconv library you want your own code to use; you can determine that by using the right -L and -I flags at the time that you compile your code.

But I see above that the problem is occurring in a haskell static library libHSbase-4.11.1.0.a. That is indeed a bit of a special case. The use of static libraries is discouraged on macOS, perhaps partly because it can cause problems like this. If you were using a dynamic version of libHSbase (and if they provide one, maybe you can try that) there should be no problem, because as I said above the absolute path to the correct iconv library to use will be baked into the dynamic library. And it's no problem if you want to use a different iconv than that in your own code; it's the libiconv name mangling that makes that possible.

If you continue to use the static library, then because the static library was built with macOS iconv you'll have to build your program that uses that static library with macOS iconv as well by supplying -L and -I flags that put the macOS iconv library first, as I suggested above with the temporary directories and symlinks.

Another thought is that you probably wouldn't run into the problem if you were using the MacPorts haskell port, ghc. However, as you know, it's out of date, and if you need features of ghc 8, then you'll have to use a non-MacPorts copy (or help us update ours).

Another possibility probably is making a fake port of iconv that simply points at the system iconv, and forcing Macports to use that one. And force-rebuild less than 300 ports on one machine, and less than 600 ports on another. ;-) What do I need to do to create such a fake port?

I don't think there is any reason why you should need to do that, so I don't want to provide advice for doing that, and I don't want to then provide further support to solve the problems that doing that will create.

If you need further help compiling your own program using MacPorts libraries, do ask on the macports-users mailing list. But I think we should stop discussing it in this ticket, because our issue tracker is for bug reports—problem we can fix by committing a change to MacPorts. In this case, libiconv is working as designed, so there is nothing for us to change. If you disagree with the design, you have to talk to the developers of libiconv about it, but libiconv has worked this way for a long time, so it is probably unlikely that they will change the design at this point.

comment:7 Changed 2 years ago by mouse07410 (Mouse)

... Which iconv library your tools use should have no bearing on what iconv library you want your own code to use ...

The problem is that I'm using binaries of other tools, therefore the decision what iconv library to use has been made by somebody else.

because the static library was built with macOS iconv you'll have to build your program that uses that static library with macOS iconv as well

If the problem was with what to use for my build, then indeed it would be trivial to resolve with a bit of -L and -I play. Unfortunately, there's nothing I can do - because iconv chose to force collision on the library name level and incompatibility on the library functions name level.

you'll have to build your program that uses that static library with macOS iconv...

I think the main problem here is that the two libraries (MacOS and Macports) use the same lib name but different function names. The static vs. dynamic does not seem relevant - because of the function names mismatch the libHSbase cannot use libiconv interchangeably between MacOS and Macports, and if libHSbase were dynamic the situation would've been exactly the same.

I'll investigate the path you're suggesting.

Another thought is that you probably wouldn't run into the problem if you were using the MacPorts haskell port, ghc...

True. But as you noted, it's hopelessly out of date, and I don't even know how complete it is.

...if you need features of ghc 8, then you'll have to use a non-MacPorts copy (or help us update ours)...

I'm already using a non-Macports copy of GHC - which is what brought all this issue up in the first place. How can I help you guys update yours?

I don't think there is any reason why you should need to do [fake iconv port]...

To be honest, I'm not crazy about that option myself. So let's pretend I didn't suggest it. ;-)

Is it possible to create a libiconv variant that does not mangle function names? Would you consider that?

Last edited 2 years ago by mouse07410 (Mouse) (previous) (diff)

comment:8 in reply to:  7 Changed 2 years ago by ryandesign (Ryan Schmidt)

Replying to mouse07410:

... Which iconv library your tools use should have no bearing on what iconv library you want your own code to use ...

The problem is that I'm using binaries of other tools, therefore the decision what iconv library to use has been made by somebody else.

because the static library was built with macOS iconv you'll have to build your program that uses that static library with macOS iconv as well

If the problem was with what to use for my build, then indeed it would be trivial to resolve with a bit of -L and -I play. Unfortunately, there's nothing I can do - because iconv chose to force collision on the library name level and incompatibility on the library functions name level.

I understand that you're using binaries. The decision of what iconv library that binary will use has already been made, that is correct. With the exception of the unique case of haskell's base static library, I don't see why that choice would affect you in any way.

you'll have to build your program that uses that static library with macOS iconv...

I think the main problem here is that the two libraries (MacOS and Macports) use the same lib name but different function names. The static vs. dynamic does not seem relevant - because of the function names mismatch the libHSbase cannot use libiconv interchangeably between MacOS and Macports, and if libHSbase were dynamic the situation would've been exactly the same.

A dynamic library specifies by absolute path which libraries it uses, and so does a program.

Consider the system CUPS library. It links with the system iconv library:

$ otool -L /usr/lib/libcups.2.dylib
/usr/lib/libcups.2.dylib:
	/usr/lib/libcups.2.dylib (compatibility version 2.0.0, current version 2.12.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4)
	/System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos (compatibility version 5.0.0, current version 6.0.0)
	/System/Library/Frameworks/GSS.framework/Versions/A/GSS (compatibility version 1.0.0, current version 1.0.0)
	/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1454.90.0)
	/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration (compatibility version 1.0.0, current version 963.50.8)
	/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
	/System/Library/Frameworks/Security.framework/Versions/A/Security (compatibility version 1.0.0, current version 58286.70.7)
	/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
	/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)

Consider the MacPorts samba3 port's smbd program. It links with the system CUPS library and with the MacPorts iconv library:

$ otool -L /opt/local/sbin/smbd
/opt/local/sbin/smbd:
	/opt/local/lib/libintl.8.dylib (compatibility version 10.0.0, current version 10.5.0)
	/usr/lib/libcups.2.dylib (compatibility version 2.0.0, current version 2.12.0)
	/usr/lib/libpam.2.dylib (compatibility version 3.0.0, current version 3.0.0)
	/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 1.0.0)
	/opt/local/lib/libiconv.2.dylib (compatibility version 9.0.0, current version 9.0.0)
	/opt/local/lib/libpopt.0.dylib (compatibility version 1.0.0, current version 1.0.0)
	/opt/local/lib/samba3/libtalloc.dylib (compatibility version 0.0.0, current version 0.0.0)
	/opt/local/lib/samba3/libtevent.dylib (compatibility version 0.0.0, current version 0.0.0)
	/opt/local/lib/samba3/libtdb.dylib (compatibility version 0.0.0, current version 0.0.0)
	/opt/local/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4)

There is no problem. samba3 didn't need to know what iconv library the CUPS library uses. samba3 was free (at build time) to use either the system iconv library or the MacPorts iconv library, and it does not interfere with what CUPS used.

On the other hand, if smbd tried to link with a static library of CUPS, it would very much matter, because a static library is essentially like copying all of the library's code into your program. If that static library links with other dynamic libraries, you must supply the flags to do so when you use the static library, just as if you had used that other dynamic library directly in your own code. And because in your case the haskell static library was compiled for the system iconv, you must also use the system iconv.

I'm already using a non-Macports copy of GHC - which is what brought all this issue up in the first place. How can I help you guys update yours?

If interested, discuss it in #48899 or contact the maintainer.

Is it possible to create a libiconv variant that does not mangle function names? Would you consider that?

Yes, it is possible, but no, I will not add that to the port, because it will cause problems—much like the ones you're experiencing now, just in different circumstances—which I do not wish to spend time helping users resolve.

comment:9 Changed 2 years ago by mouse07410 (Mouse)

Thanks for explaining. I think I got it now.

I will not add that to the port, because it will cause problems—much like the ones you're experiencing now, just in different circumstances—which I do not wish to spend time helping users resolve

I'm not sure I understand how it could cause problems, especially when the majority would use the default that does mangle the function names. I wish you'd reconsider adding a port variant.

comment:10 Changed 2 years ago by mouse07410 (Mouse)

I've applied your recommendation, and, while more tests are needed, it looks like it works.

In summary, the workaround that you proposed and I tested is:

  • create a new directory and put the offending library in it;
  • list that directory first in the "extra-lib-dirs:" parameter for Haskell utilities Cabal and Stack.

Figuring the correct format for the above was a greater pain than everything else together.

For Stack (in ~/.stack/config.yaml) include this (I list all the directories I need - libiconv is in /opt/local/lib/liconv, new OpenSSL in /opt/local/lib, etc):

extra-lib-dirs: [ /opt/local/lib/liconv, /opt/local/lib, /usr/local/lib ]

For Cabal (in ~/.cabal/config) include this:

library-vanilla: False
executable-dynamic: True
extra-lib-dirs: /opt/local/lib/liconv
extra-lib-dirs: /opt/local/lib 
extra-lib-dirs: /usr/local/lib

Thank you for your help!

P.S. I still think that having a no-name-mangling variant of the libiconv port would be a good thing.

comment:11 Changed 2 years ago by mouse07410 (Mouse)

Update. The workaround failed, unfortunately. Some packages refused to build with it.

So I bit the bullet and compiled GHC from the source. It turned out to be trivial, if a little time-consuming (CPU time, not mine ;). That way GHC that I built uses Macports libiconv, and everything is smooth.

Based on my current experience with Macports and GHC, I'd say the ghc port needs to be simplified: drop dependency on LLVM - GHC people say it's not sufficiently debugged, drop attempts to manage Haskell packages via Macports - cabal and stack will remain better at that job anyway. It is trying to do too much, which IMHO is why its maintainers find it so hard to keep current.

comment:12 in reply to:  9 Changed 2 years ago by ryandesign (Ryan Schmidt)

Replying to mouse07410:

I will not add that to the port, because it will cause problems—much like the ones you're experiencing now, just in different circumstances—which I do not wish to spend time helping users resolve

I'm not sure I understand how it could cause problems, especially when the majority would use the default that does mangle the function names. I wish you'd reconsider adding a port variant.

If we offered a variant that did not mangle the function names, all of the other ports that the user had installed that linked with libiconv would be broken, because they expect mangled function names. The user would have to uninstall and rebuild all of those ports from source so that they use unmangled names. If the user didn't do that, they would receive undefined symbol errors, much as you did. MacPorts doesn't contain any feature that would make it easy for the user to identify the ports that need to be rebuilt, so it would be a manual process. I would not want to be involved in assisting the user with that task.

We have an automated build system that builds and distributes binaries of ports to users. Anything built by that system would use libiconv in its normal state—with mangled function names. Those binaries would be incompatible with a libiconv variant for using unmangled function names installed on a user system. The user would have to know this, and would have to instruct MacPorts not to use any binaries (i.e. to build from source instead). We could inform the user of that by using notes in the variant, but users often don't read notes, and there's no way to enforce that the user has disabled binaries if they use that hypothetical variant. For these reasons, we try to avoid adding variants that, when selected, cause other ports to build differently.

Sometimes being a maintainer of a port means knowing when not to offer users the opportunity to shoot themselves in the foot, because some users inevitably take that opportunity and then either leave MacPorts because they perceive it to be broken, or else they ask us for tech support. Some of my goals are to reduce the likelihood that a user will need tech support or leave us.

comment:13 in reply to:  11 Changed 2 years ago by ryandesign (Ryan Schmidt)

Replying to mouse07410:

Based on my current experience with Macports and GHC, I'd say the ghc port needs to be simplified: drop dependency on LLVM - GHC people say it's not sufficiently debugged,

Please communicate with the MacPorts maintainer of ghc about this, by email or in the ticket about the ghc update. They will not see your messages in this ticket.

drop attempts to manage Haskell packages via Macports - cabal and stack will remain better at that job anyway. It is trying to do too much, which IMHO is why its maintainers find it so hard to keep current.

If we did that, we would also have to remove all the ports that have dependencies on Haskell packages, and all the ports that depend on them, and so on.

comment:14 Changed 2 years ago by mouse07410 (Mouse)

If we offered a variant that did not mangle the function names, all of the other ports that the user had installed that linked with libiconv would be broken, because they expect mangled function names. The user would have to uninstall and rebuild all of those ports from source so that they use unmangled names...

I see your points. But is this really different from +quartz -x11 vs. +x11 -quartz issue?

Those binaries would be incompatible with a libiconv variant for using unmangled function names installed on a user system. The user would have to know this, and would have to instruct MacPorts not to use any binaries...

My assumption is that if a user chooses a variant over the default - he knows why he does it, and realizes the consequences (especially those listed in the port description ;).

For these reasons, we try to avoid adding variants that, when selected, cause other ports to build differently...

True, and agreed. But sometimes it is not possible to avoid such variants (see my example above). I'd agree that this is probably not such a case.

Sometimes being a maintainer of a port means knowing when not to offer users the opportunity to shoot themselves in the foot...

I take your point.

Essentially, the correct solution was to use a rebuilt GHC. A pity that Macports cannot provide a good GHC, but:

Please communicate with the MacPorts maintainer of ghc about this...

That's what I'm doing, and after this post will continue the discussion there: #48899

drop attempts to manage Haskell packages via Macports - cabal and stack will remain better at that job anyway. It is trying to do too much, which IMHO is why its maintainers find it so hard to keep current.

If we did that, we would also have to remove all the ports that have dependencies on Haskell packages, and all the ports that depend on them, and so on

And I'd call it a Good Riddance. Currently a huge number of 48 ports, of which about one third are semi-independent binaries (aka not something managed by cabal). In any case, users would be better off managing the majority of those directly via cabal and/or stack.

comment:15 Changed 2 years ago by mouse07410 (Mouse)

Here's the latest update, after a long discussion with the GHC developers.

  • Passing -L/dir/for/libiconv to GHC for some reason does not work as expected. Theoretically it should, in practice it doesn't.
  • Making libHSbase.a dynamic-only would remove the ability to distribute pre-packaged binaries, because then they would run only on systems where GHC is installed. Therefore, it's been decided by the GHC developers that it's not an acceptable option.
  • Building a Macports-aware GHC works, but prevents distributing binaries to systems that don't have Macports installed.

All of these problems would not exist if Macports could provide a variant of libiconv.dylib with no mangled names.

Based on the above, I have to ask @ryandesign again to reconsider. All the other venues I've explored so far, don't seem to cover the desired set of use cases.

comment:16 Changed 2 years ago by mouse07410 (Mouse)

Resolution: invalid
Status: closedreopened

Re-opening with the request to re-consider adding a variant to libiconv.dylib

comment:17 Changed 2 years ago by jmroot (Joshua Root)

The system libiconv and the version provided by the libiconv port are not 100% compatible even if the symbol renaming were turned off. If your lib was built against the system libiconv, you need to use it with the system libiconv. If -L/path/to -lfoo is not working, try simply /path/to/foo.dylib.

comment:18 Changed 2 years ago by mouse07410 (Mouse)

The system libiconv and the version provided by the libiconv port are not 100% compatible even if the symbol renaming were turned off.


I'm not sure I fully understand. If an app can be built against either library without modifying its source, then these two are compatible "enough"???


If your lib was built against the system libiconv, you need to use it with the system libiconv


All I can say is "I'm trying, without much success so far..." ;-) ;-(


If -L/path/to -lfoo is not working, try simply /path/to/foo.dylib.


An excellent advice. I don't understand why this would work, while the -L/some/thing doesn't, but apparently it seemed to work! Thank you, Joshua!

To help others, here's what worked:

$ cabal v2-configure --with-ghc /usr/local/bin/ghc --with-gcc /opt/local/bin/clang --with-ld /opt/local/bin/clang --ld-option "/usr/lib/libiconv.dylib" --ghc-option "/usr/lib/libiconv.dylib"
'cabal.project.local' file already exists. Now overwriting it.
Resolving dependencies...
Build profile: -w ghc-8.6.3 -O1
In order, the following would be built (use -v for more details):
 - StateVar-1.1.1.1 (lib) (requires build)
. . . . .
 - profunctors-5.3 (lib) (requires build)
 - saltine-0.1.1.0 (lib) (first run)
 - saltine-0.1.1.0 (test:tests) (first run)
$ cabal v2-test --with-ghc /usr/local/bin/ghc --with-gcc /opt/local/bin/clang --with-ld /opt/local/bin/clang --ld-option "/usr/lib/libiconv.dylib" --ghc-option "/usr/lib/libiconv.dylib"
Resolving dependencies...
Build profile: -w ghc-8.6.3 -O1
In order, the following will be built (use -v for more details):
 - StateVar-1.1.1.1 (lib) (requires build)
. . . . .
Linking /Users/uri/src/saltine/dist-newstyle/build/x86_64-osx/ghc-8.6.3/saltine-0.1.1.0/t/tests/build/tests/tests ...
Running 1 test suites...
Test suite tests: RUNNING...
...Internal.Box:
  Can decrypt ciphertext using...:
    ... public key/secret key: [OK, passed 20000 tests]
    ... combined key: [OK, passed 20000 tests]
. . . . .
  matches test vector for shared secret from bob's view: [OK, passed 1 tests]

         Properties   Total       
 Passed  52           52          
 Failed  0            0           
 Total   52           52          

Test suite tests: PASS

$ otool -L dist-newstyle/build/x86_64-osx/ghc-8.6.3/saltine-0.1.1.0/t/tests/build/tests/tests
dist-newstyle/build/x86_64-osx/ghc-8.6.3/saltine-0.1.1.0/t/tests/build/tests/tests:
	/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
	/opt/local/lib/libsodium.23.dylib (compatibility version 25.0.0, current version 25.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
$ 

Here's what didn't:

$ /usr/local/bin/ghc -V
The Glorious Glasgow Haskell Compilation System, version 8.6.3
$ cabal v2-configure --with-ghc /usr/local/bin/ghc --with-ld /opt/local/bin/clang --ld-option "/usr/lib/libiconv.dylib"
Resolving dependencies...
Build profile: -w ghc-8.6.3 -O1
In order, the following would be built (use -v for more details):
 - StateVar-1.1.1.1 (lib) (requires build)
. . . . .
$ cabal v2-test --with-ghc /usr/local/bin/ghc --with-ld /opt/local/bin/clang --ld-option "/usr/lib/libiconv.dylib"
Build profile: -w ghc-8.6.3 -O1
In order, the following will be built (use -v for more details):
 - StateVar-1.1.1.1 (lib) (requires build)
. . . . .
Completed    tf-random-0.5 (lib)
cabal: Failed to build distributive-0.6 (which is required by test:tests from
saltine-0.1.1.0). The failure occurred during the configure step. The
exception was:
dieVerbatim: user error (cabal: '/usr/local/bin/ghc' exited with an error:
Undefined symbols for architecture x86_64:
"_iconv", referenced from:
_hs_iconv in libHSbase-4.12.0.0.a(iconv.o)
(maybe you meant: _base_GHCziIOziEncodingziIconv_iconvEncoding1_info,
_base_GHCziIOziEncodingziIconv_iconvEncoding7_closure ,
_base_GHCziIOziEncodingziIconv_iconvEncoding15_closure ,
_base_GHCziIOziEncodingziIconv_iconvEncoding4_info ,
_base_GHCziIOziEncodingziIconv_iconvEncoding7_info ,
_base_GHCziIOziEncodingziIconv_iconvEncoding6_closure ,
_base_GHCziIOziEncodingziIconv_iconvEncoding6_info , _hs_iconv ,
_base_GHCziIOziEncodingziIconv_iconvEncoding5_closure ,
_base_GHCziIOziEncodingziIconv_iconvEncoding14_bytes ,
_base_GHCziIOziEncodingziIconv_iconvEncoding8_closure ,
_base_GHCziIOziEncodingziIconv_iconvEncoding8_info , _hs_iconv_open ,
_base_GHCziIOziEncodingziIconv_iconvEncoding9_closure , _hs_iconv_close ,
_base_GHCziIOziEncodingziIconv_iconvEncoding9_info ,
_base_GHCziIOziEncodingziIconv_iconvEncoding11_info ,
_base_GHCziIOziEncodingziIconv_iconvEncoding12_info ,
_base_GHCziIOziEncodingziIconv_iconvEncoding15_info ,
_base_GHCziIOziEncodingziIconv_iconvEncoding13_closure ,
_base_GHCziIOziEncodingziIconv_iconvEncoding4_closure ,
_base_GHCziIOziEncodingziIconv_iconvEncoding3_closure ,
_base_GHCziIOziEncodingziIconv_iconvEncoding1_closure ,
_base_GHCziIOziEncodingziIconv_iconvEncoding12_closure ,
_base_GHCziIOziEncodingziIconv_iconvEncoding10_bytes ,
_base_GHCziIOziEncodingziIconv_iconvEncoding2_info ,
_base_GHCziIOziEncodingziIconv_iconvEncoding13_info ,
_base_GHCziIOziEncodingziIconv_iconvEncoding11_closure ,
_base_GHCziIOziEncodingziIconv_iconvEncoding2_closure ,
_base_GHCziIOziEncodingziIconv_iconvEncoding_closure ,
_base_GHCziIOziEncodingziIconv_iconvEncoding_info )
"_iconv_open", referenced from:
_hs_iconv_open in libHSbase-4.12.0.0.a(iconv.o)
(maybe you meant: _hs_iconv_open)
"_iconv_close", referenced from:
_hs_iconv_close in libHSbase-4.12.0.0.a(iconv.o)
(maybe you meant: _hs_iconv_close)
"_locale_charset", referenced from:
_localeEncoding in libHSbase-4.12.0.0.a(PrelIOUtils.o)
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
`gcc' failed in phase `Linker'. (Exit code: 1)
)

Minimum required seems to be:

$ cabal v2-test --with-ghc /usr/local/bin/ghc --ghc-option "/usr/lib/libiconv.dylib"
. . . . .
Test suite tests: PASS
Test suite logged to:
/Users/mouse/src/saltine/dist-newstyle/build/x86_64-osx/ghc-8.6.3/saltine-0.1.1.0/t/tests/test/saltine-0.1.1.0-tests.log
1 of 1 test suites (1 of 1 test cases) passed.
Last edited 2 years ago by mouse07410 (Mouse) (previous) (diff)

comment:19 in reply to:  14 Changed 2 years ago by ryandesign (Ryan Schmidt)

Replying to mouse07410:

If we offered a variant that did not mangle the function names, all of the other ports that the user had installed that linked with libiconv would be broken, because they expect mangled function names. The user would have to uninstall and rebuild all of those ports from source so that they use unmangled names...

I see your points. But is this really different from +quartz -x11 vs. +x11 -quartz issue?

It's similar, but different because all of the ports that build themselves differently because of the x11/quartz distinction are supposed to have x11 and quartz variants so that the user can indicate which one they want. If we were to implement your suggested no-name-mangling variant of the libiconv port, we would have to add such a variant to every port that uses libiconv. I don't want to do that. There's also no mechanism in MacPorts to ensure that the variants of all ports match. Nothing would prevent a user from installing libiconv with that variant and then installing [a port that uses libiconv] without that variant, and that would make things break, and I don't want to provide technical support for that.

Those binaries would be incompatible with a libiconv variant for using unmangled function names installed on a user system. The user would have to know this, and would have to instruct MacPorts not to use any binaries...

My assumption is that if a user chooses a variant over the default - he knows why he does it, and realizes the consequences (especially those listed in the port description ;).

You give users too much credit. If there is a way for a user to mess up their MacPorts installation, some user will find it, and will then write to us asking why it's broken. We need to reduce the number of ways for the user to cause problems, not add new ones.

If we did that, we would also have to remove all the ports that have dependencies on Haskell packages, and all the ports that depend on them, and so on

And I'd call it a Good Riddance. Currently a huge number of 48 ports, of which about one third are semi-independent binaries (aka not something managed by cabal). In any case, users would be better off managing the majority of those directly via cabal and/or stack.

I personally use shellcheck, and have previously used pandoc. Both are in MacPorts and require Haskell. I don't care what language a software package I want to use is written in; I just want to install and use it. I don't want to have to know what cabal and/or stack are or how to use them. That's why we put things in MacPorts: so that a user only has to learn one way of installing the software they need.

comment:20 in reply to:  16 Changed 2 years ago by ryandesign (Ryan Schmidt)

Resolution: invalid
Status: reopenedclosed

Replying to mouse07410:

Here's the latest update, after a long discussion with the GHC developers.

  • Passing -L/dir/for/libiconv to GHC for some reason does not work as expected. Theoretically it should, in practice it doesn't.
  • Making libHSbase.a dynamic-only would remove the ability to distribute pre-packaged binaries, because then they would run only on systems where GHC is installed. Therefore, it's been decided by the GHC developers that it's not an acceptable option.
  • Building a Macports-aware GHC works, but prevents distributing binaries to systems that don't have Macports installed.

Neither offering a dynamic version of the HSbase library, nor using a MacPorts ghc, would prevent you from distributing binaries built with it. You can relocate any needed dynamic libraries into your application bundle, either manually by running install_name_tool as needed or by automating it using a tool such as dylibbundler (which can be installed with MacPorts).

Replying to mouse07410:

Re-opening with the request to re-consider adding a variant to libiconv.dylib

I'm not going to do that; I've explained why. Now please, let us stop talking about this issue. I don't want to spend any more time on it.

comment:21 Changed 4 months ago by essandess (Steve Smith)

I'm updating port ghc and this annoying libiconv issue bites me every time.

The simple solution is to run

sudo port deactivate libiconv

before running sudo port test ghc.

My preferred solution would be to prevent linking to /usr/lib/libiconv.dylib in the first place. I don't see why this happens—LIBRARY_PATH is already set to /opt/local/lib in all MacPorts stages.

Does anyone know how to tell MacPorts to build ghc without using the system iconv library?

comment:22 Changed 4 months ago by mouse07410 (Mouse)

Are there any users of GHC port? Why would one choose it instead of a very powerful and very convenient ghcup?

My experience taught me not to waste time on this.

comment:23 in reply to:  21 ; Changed 4 months ago by ryandesign (Ryan Schmidt)

Cc: essandess added

Replying to essandess:

I'm updating port ghc and this annoying libiconv issue bites me every time.

The simple solution is to run

sudo port deactivate libiconv

before running sudo port test ghc.

My preferred solution would be to prevent linking to /usr/lib/libiconv.dylib in the first place. I don't see why this happens—LIBRARY_PATH is already set to /opt/local/lib in all MacPorts stages.

Does anyone know how to tell MacPorts to build ghc without using the system iconv library?

Steve, please file a new ticket and attach logs showing what's happening so we can help you diagnose it.

This ticket was about a problem mouse07410 experienced when trying to use a copy of ghc that had been compiled outside of MacPorts without MacPorts libiconv being present. This caused that ghc's static library to be compiled against the system's libiconv. Trying to link a program with that static library would fail if also trying to use MacPorts libiconv. The solution was to rebuild ghc from source while MacPorts libiconv was present. I would think that would already be the case when you build the MacPorts ghc port, so I don't think you're experiencing the same problem. This ticket asked us to change MacPorts libiconv to deviate from the intentions of its developers, and our response was that we would not do that. The resolution for your issue may be different.

Replying to mouse07410:

Are there any users of GHC port? Why

As I explained before, ghc is an implementation of the haskell programming language, and we would like to offer haskell and all other programming languages in MacPorts, so that software that happens to be written in those programming languages can also be offered in MacPorts. It would not be convenient for MacPorts to have a policy that a program cannot be included in MacPorts only because that program happened to have been written in haskell.

comment:24 in reply to:  23 Changed 4 months ago by ryandesign (Ryan Schmidt)

Replying to ryandesign:

Steve, please file a new ticket and attach logs showing what's happening so we can help you diagnose it.

I think I now see what you're probably seeing and have filed #61222 for it.

comment:25 Changed 4 months ago by essandess (Steve Smith)

Last edited 4 months ago by essandess (Steve Smith) (previous) (diff)
Note: See TracTickets for help on using tickets.