pmqs / Compress-Raw-Zlib

Perl5 interface to zlib compression library
3 stars 10 forks source link

With static build, `Zlib.a/zutil.o` exports a `z_errmsg` symbol producing name clash when static linking with `libz.a` #32

Open vadimkantorov opened 3 days ago

vadimkantorov commented 3 days ago

I'm building a custom fully static perl install with various static modules (including Compress::Raw::Zlib and some others). Some of these modules require linking with libz.a. And I'm also linking with Zlib.a (the static library produced by Compress::Raw::Zlib). This led to a multiple definitions of z_errmsg symbol (from Zlib.a/zutil.o):

/usr/lib/gcc/x86_64-alpine-linux-musl/10.3.1/../../../../x86_64-alpine-linux-musl/bin/ld: /lib/libz.a(zutil.o):(.data.rel.ro.local+0x0): multiple definition of 'z_errmsg'; /__w/busybiber/busybiber/packfs/lib/perl5/5.40.0/x86_64-linux/auto/Compress/Raw/Zlib/Zlib.a(zutil.o):(.data.rel.ro.local+0x0): first defined here

As a workaround, I renamed this symbol in Zlib.a and then linking went all fine. But I think this name clash should be fixed in upstream (maybe via prefixing this and other zlib-symbols or making them private).

Also wondering, if I can instruct somehow Compress::Raw::Zlib to not build a private zlib copy and instead rely on later static linking with libz.a. Is there anywhere an example of such configure and perl build command? My current commands:

mkdir perlsourcestatic && curl -L https://www.cpan.org/src/5.0/perl-5.40.0.tar.gz | tar -xzf - --strip-components=1 --directory=perlsourcestatic
cd perlsourcestatic && sh +x ./Configure -sde -Dman1dir=none -Dman3dir=none -Dprefix="$PWD/perlprefix" -Aldflags="-lm -ldl" -Accflags="-lm -ldl" -Dusedevel -Dlibs="-lpthread -ldl -lm -lutil -lc" -Dstatic_ext="mro Devel/Peek File/DosGlob File/Glob Sys/Syslog Sys/Hostname PerlIO/via PerlIO/mmap PerlIO/encoding B attributes Unicode/Normalize Unicode/Collate threads threads/shared IPC/SysV re Digest/MD5 Digest/SHA SDBM_File Math/BigInt/FastCalc Data/Dumper I18N/Langinfo Time/HiRes Time/Piece IO Socket Hash/Util/FieldHash Hash/Util Filter/Util/Call POSIX Encode/Unicode Encode Encode/JP Encode/KR Encode/EBCDIC Encode/CN Encode/Symbol Encode/Byte Encode/TW Compress/Raw/Zlib Compress/Raw/Bzip2 MIME/Base64 Cwd Storable List/Util Fcntl Opcode" && cd -

make -C perlsourcestatic

make -C perlsourcestatic install

nm ./perlsourcestatic/perlprefix/lib/5.40.0/x86_64-linux/auto/Compress/Raw/Zlib/Zlib.a # shows that `z_errmsg` is exported

Original issue and repro/artifacts:

pmqs commented 3 days ago

If you set the environment variable BUILD_ZLIB to 0 it will disable building of a private zlib library.

vadimkantorov commented 3 days ago

If you set the environment variable BUILD_ZLIB to 0 it will disable building of a private zlib library.

Trying this now. Thanks!

But I think that the name clashes should also not happen for the default mode which builds a built-in copy of zlib: maybe via symbol prefixing or via modification of symbol visibility... (with version 5.36.0 of perl there were more symbol name clashes with some crc32 symbols, but in 5.40.0 only name clash with z_errmsg remained) - I consider this part more of a bug

pmqs commented 3 days ago

But I think that the name clashes should also not happen for the default mode which build a built-in copy of zlib: maybe via symbol prefixing or via modification of symbol visibility... (with version 5.36.0 of perl there were more name clashes with some crc32 symbols, but in 5.40.0 only name clash with z_errmsg remained)

The upstream zlib source has logic in place to allow all the external symbols to have a prefix added to them. That is supposed to avoid name clashes like this. For some reason z_errmsg isn't included in that logic. I'll see about reporting this upstream.