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

libxmp fails to build with gcc link-time optimization (LTO) enabled #385

Closed
rathann opened this issue Jun 22, 2021 · 41 comments · Fixed by #391
Closed

libxmp fails to build with gcc link-time optimization (LTO) enabled #385

rathann opened this issue Jun 22, 2021 · 41 comments · Fixed by #391

Comments

@rathann
Copy link

rathann commented Jun 22, 2021

When building on Fedora (33 and later) libxmp 4.4.1 and 4.5.0 fail to link if LTO was enabled (CFLAGS+=-flto=auto -ffat-lto-objects):

...
gcc -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,--no-undefined -shared -Wl,-soname,libxmp.so.4 -Wl,--version-script,libxmp.map -o lib/libxmp.so.4.5.0 src/virtual.lo src/format.lo src/period.lo src/player.lo src/read_event.lo src/dataio.lo src/misc.lo src/mkstemp.lo src/md5.lo src/lfo.lo src/scan.lo src/control.lo src/med_extras.lo src/filter.lo src/effects.lo src/mixer.lo src/mix_all.lo src/load_helpers.lo src/load.lo src/hio.lo src/hmn_extras.lo src/extras.lo src/smix.lo src/memio.lo src/tempfile.lo src/mix_paula.lo src/win32.lo src/loaders/common.lo src/loaders/iff.lo src/loaders/itsex.lo src/loaders/asif.lo src/loaders/voltable.lo src/loaders/sample.lo src/loaders/xm_load.lo src/loaders/mod_load.lo src/loaders/s3m_load.lo src/loaders/stm_load.lo src/loaders/669_load.lo src/loaders/far_load.lo src/loaders/mtm_load.lo src/loaders/ptm_load.lo src/loaders/okt_load.lo src/loaders/ult_load.lo src/loaders/mdl_load.lo src/loaders/it_load.lo src/loaders/stx_load.lo src/loaders/pt3_load.lo src/loaders/sfx_load.lo src/loaders/flt_load.lo src/loaders/st_load.lo src/loaders/emod_load.lo src/loaders/imf_load.lo src/loaders/digi_load.lo src/loaders/fnk_load.lo src/loaders/ice_load.lo src/loaders/liq_load.lo src/loaders/ims_load.lo src/loaders/masi_load.lo src/loaders/amf_load.lo src/loaders/psm_load.lo src/loaders/stim_load.lo src/loaders/mmd_common.lo src/loaders/mmd1_load.lo src/loaders/mmd3_load.lo src/loaders/rtm_load.lo src/loaders/dt_load.lo src/loaders/no_load.lo src/loaders/arch_load.lo src/loaders/sym_load.lo src/loaders/med2_load.lo src/loaders/med3_load.lo src/loaders/med4_load.lo src/loaders/dbm_load.lo src/loaders/umx_load.lo src/loaders/gdm_load.lo src/loaders/pw_load.lo src/loaders/gal5_load.lo src/loaders/gal4_load.lo src/loaders/mfp_load.lo src/loaders/asylum_load.lo src/loaders/hmn_load.lo src/loaders/mgt_load.lo src/loaders/chip_load.lo src/loaders/abk_load.lo src/loaders/coco_load.lo src/loaders/prowizard/prowiz.lo src/loaders/prowizard/ptktable.lo src/loaders/prowizard/tuning.lo src/loaders/prowizard/ac1d.lo src/loaders/prowizard/di.lo src/loaders/prowizard/eureka.lo src/loaders/prowizard/fc-m.lo src/loaders/prowizard/fuchs.lo src/loaders/prowizard/fuzzac.lo src/loaders/prowizard/gmc.lo src/loaders/prowizard/heatseek.lo src/loaders/prowizard/ksm.lo src/loaders/prowizard/mp.lo src/loaders/prowizard/np1.lo src/loaders/prowizard/np2.lo src/loaders/prowizard/np3.lo src/loaders/prowizard/p61a.lo src/loaders/prowizard/pm10c.lo src/loaders/prowizard/pm18a.lo src/loaders/prowizard/pha.lo src/loaders/prowizard/prun1.lo src/loaders/prowizard/prun2.lo src/loaders/prowizard/tdd.lo src/loaders/prowizard/unic.lo src/loaders/prowizard/unic2.lo src/loaders/prowizard/wn.lo src/loaders/prowizard/zen.lo src/loaders/prowizard/tp1.lo src/loaders/prowizard/tp3.lo src/loaders/prowizard/p40.lo src/loaders/prowizard/xann.lo src/loaders/prowizard/theplayer.lo src/loaders/prowizard/pp10.lo src/loaders/prowizard/pp21.lo src/loaders/prowizard/starpack.lo src/loaders/prowizard/titanics.lo src/loaders/prowizard/skyt.lo src/loaders/prowizard/novotrade.lo src/loaders/prowizard/hrt.lo src/loaders/prowizard/noiserun.lo src/depackers/depacker.lo src/depackers/ppdepack.lo src/depackers/unsqsh.lo src/depackers/mmcmp.lo src/depackers/readrle.lo src/depackers/readlzw.lo src/depackers/unarc.lo src/depackers/arcfs.lo src/depackers/xfd.lo src/depackers/inflate.lo src/depackers/muse.lo src/depackers/unlzx.lo src/depackers/s404_dec.lo src/depackers/unzip.lo src/depackers/gunzip.lo src/depackers/uncompress.lo src/depackers/unxz.lo src/depackers/bunzip2.lo src/depackers/unlha.lo src/depackers/xz_dec_lzma2.lo src/depackers/xz_dec_stream.lo src/depackers/oxm.lo src/depackers/vorbis.lo src/depackers/crc32.lo src/depackers/xfd_link.lo src/depackers/xfnmatch.lo -lm
/tmp/ccm9dItI.s: Assembler messages:
/tmp/ccm9dItI.s: Error: invalid attempt to declare external version name as default in symbol `xmp_set_player@@XMP_4.4'
lto-wrapper: fatal error: gcc returned 1 exit status
compilation terminated.
/usr/bin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status
make: *** [Makefile:111: lib/libxmp.so.4.5.0] Error 1

This is with gcc-10.3.1.

@sezero
Copy link
Collaborator

sezero commented Jun 22, 2021

Googling points to some hints at alsa-project/alsa-lib#6
@cmatsuoka: What's the best solution for this?

  • Do we need to detect -ftlo and add -flto-partition=none to CFLAGS?
  • Do we need externally_visible attribute for versioned symbols?

@sezero
Copy link
Collaborator

sezero commented Jun 22, 2021

Tried lto on my old fedora-27 setup with binutils-2.29-13.fc27.x86_64,
by configuring with CFLAGS="-O2 -Wall -flto" LDFLAGS="-flto" set on
the command line. (Yes, I know f27 is old, I just don't have a newer
fedora setup to test at the moment.)

  • With fedora-provided gcc-7.3.1-6.fc27.x86_64: no issues,

  • With gcc-9.2.1 (20190915) or gcc-8.2.1 (20180920) built from FSF,
    there are no errors/warnings, but xmp_set_player is not exported.

I tried adding -flto-partition=none to CFLAGS and changed export
of version symbols to __attribute__((visibility("default"),externally_visible))
did not help.

@rathann
Copy link
Author

rathann commented Jun 22, 2021

I also found this Fedora developers mailing list post, which suggests __attribute__((externally_visible)) should be used with LTO and indeed, patching include/xmp.h with:

diff -up libxmp-4.5.0/include/xmp.h.lto libxmp-4.5.0/include/xmp.h
--- libxmp-4.5.0/include/xmp.h.lto	2021-06-10 02:24:24.000000000 +0200
+++ libxmp-4.5.0/include/xmp.h	2021-06-22 21:34:03.394649770 +0200
@@ -22,7 +22,7 @@ extern "C" {
 #elif defined(__OS2__) && defined(__WATCOMC__) && defined(__SW_BD)
 #  define LIBXMP_EXPORT __declspec(dllexport)
 #elif (defined(__GNUC__) || defined(__clang__) || defined(__HP_cc)) && defined(XMP_SYM_VISIBILITY)
-# define LIBXMP_EXPORT __attribute__((visibility ("default")))
+# define LIBXMP_EXPORT __attribute__((externally_visible))
 #elif defined(__SUNPRO_C) && defined(XMP_LDSCOPE_GLOBAL)
 # define LIBXMP_EXPORT __global
 #elif defined(EMSCRIPTEN)

fixes the issue for me on Fedora 34 (gcc-10.3.1).

@rathann
Copy link
Author

rathann commented Jun 22, 2021

Hm, but the test suite fails to link:

gcc -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,--no-undefined -o test/libxmp-test test/test.o src/md5.o -lm -Llib -lxmp
/usr/bin/ld: /usr/bin/ld: DWARF error: invalid abstract instance DIE ref
/tmp/ccW4RC5g.ltrans0.ltrans.o: in function `main':
<artificial>:(.text.startup+0x29): undefined reference to `xmp_create_context'
/usr/bin/ld: <artificial>:(.text.startup+0x40): undefined reference to `xmp_load_module'
/usr/bin/ld: <artificial>:(.text.startup+0x57): undefined reference to `xmp_get_frame_info'
/usr/bin/ld: <artificial>:(.text.startup+0x84): undefined reference to `xmp_release_module'
/usr/bin/ld: <artificial>:(.text.startup+0x8c): undefined reference to `xmp_free_context'
/usr/bin/ld: <artificial>:(.text.startup+0xc3): undefined reference to `xmp_start_player'
/usr/bin/ld: <artificial>:(.text.startup+0xd5): undefined reference to `xmp_set_player'
/usr/bin/ld: <artificial>:(.text.startup+0xe7): undefined reference to `xmp_set_player'
/usr/bin/ld: <artificial>:(.text.startup+0x17d): undefined reference to `xmp_play_frame'
/usr/bin/ld: <artificial>:(.text.startup+0x188): undefined reference to `xmp_get_frame_info'
/usr/bin/ld: <artificial>:(.text.startup+0x2e2): undefined reference to `xmp_release_module'
/usr/bin/ld: <artificial>:(.text.startup+0x2ea): undefined reference to `xmp_free_context'
collect2: error: ld returned 1 exit status
make: *** [test/Makefile:23: test/libxmp-test] Error 1

@sezero
Copy link
Collaborator

sezero commented Jun 22, 2021

The problem with externally_visible isn't supported by all, e.g. clang.
Does the attached patch work for you? test1_patch.txt

(It doesn't fix the export issue I'm having on fc27 with fsf gcc8/9 though,
which looks like the linkage issue you are having.)

@rathann
Copy link
Author

rathann commented Jun 22, 2021

@sezero Unfortunately, with your patch it's failing as in the original report:

/tmp/ccqfHkhS.s: Error: invalid attempt to declare external version name as default in symbol `xmp_set_player@@XMP_4.4'

@rathann
Copy link
Author

rathann commented Jun 22, 2021

After compiling with -save-temps, I can see that the symbols get __attribute__((visibility("default"))) only with your patch.

@sezero
Copy link
Collaborator

sezero commented Jun 22, 2021

Does configure report that externally_visible is supported?
Mine does, and control.i has

__attribute__((visibility("default"),externally_visible)) extern int xmp_set_player_v40__(xmp_context, int, int);
__attribute__((visibility("default"),externally_visible)) extern int xmp_set_player_v41__(xmp_context, int, int)
   __attribute__((alias("xmp_set_player_v40__")));
__attribute__((visibility("default"),externally_visible)) extern int xmp_set_player_v43__(xmp_context, int, int)
   __attribute__((alias("xmp_set_player_v40__")));
__attribute__((visibility("default"),externally_visible)) extern int xmp_set_player_v44__(xmp_context, int, int)
   __attribute__((alias("xmp_set_player_v40__")));

(Note that my patch applies externally_visible only to versioned syms in control.c)

Updated the patch btw (there was a minor -Werror issue)

@rathann
Copy link
Author

rathann commented Jun 22, 2021

Scratch that. I haven't run autoreconf -fiv after applying your patch, so I was still using the old configure. The patch fixes both the first and the second issue for me. Thanks!

@sezero
Copy link
Collaborator

sezero commented Jun 22, 2021

That's great!

To confirm: With the patch applied:

  • no errors
  • no linkage issues at all (easiest way to test is configuring xmp
    against the build.)

Yes?

@rathann
Copy link
Author

rathann commented Jun 22, 2021

Correct. There are no backwards-incompatible ABI changes, so I simply updated the existing libxmp on my system and xmp still works fine.

sezero added a commit that referenced this issue Jun 22, 2021
this seems to help with lto-enabled builds, see issue reported by fedora
people at: #385.

also tweak the visibility attribute checks in configure.
@sezero sezero added the waiting label Jun 22, 2021
@sezero
Copy link
Collaborator

sezero commented Jun 22, 2021

OK, pushed the patch as a091de5

Keeping this open so that @AliceLR, @cmatsuoka and others can test and
report their results: setting status to waiting.

@rathann: if you can try building xmp-cli (from git), that'd be great.

@cmatsuoka
Copy link
Collaborator

I wonder if declaring versioned symbols using the gcc 10 symver attribute instead of asm could also work. Something like:

-LIBXMP_EXPORT extern int xmp_set_player_v40__(xmp_context, int, int);
+LIBXMP_EXPORT extern int xmp_set_player_v40__(xmp_context, int, int)
+                        __attribute__((__symver__("xmp_set_player@XMP_4.0")));
 LIBXMP_EXPORT extern int xmp_set_player_v41__(xmp_context, int, int)
-                       __attribute__((alias("xmp_set_player_v40__")));
+                       __attribute__((alias("xmp_set_player_v40__"), __symver__("xmp_set_player@XMP_4.1")));
 LIBXMP_EXPORT extern int xmp_set_player_v43__(xmp_context, int, int)
-                       __attribute__((alias("xmp_set_player_v40__")));
+                       __attribute__((alias("xmp_set_player_v40__"), __symver__("xmp_set_player@XMP_4.3")));
 LIBXMP_EXPORT extern int xmp_set_player_v44__(xmp_context, int, int)
-                       __attribute__((alias("xmp_set_player_v40__")));
+                       __attribute__((alias("xmp_set_player_v40__"), __symver__("xmp_set_player@@XMP_4.4")));

and removing the asm lines.

@sezero
Copy link
Collaborator

sezero commented Jun 22, 2021

I don't have a gcc10 build to test that.

(Even with my patch applied, the export/link issues I experienced (see #385 (comment)) hasn't actually gone, I'm guessing this is somehow a gcc issue.)

@cmatsuoka
Copy link
Collaborator

From what I understood LTO doesn't play well with asm-based versioned symbols, but attribute __symver__ should work. The problem is that __symver__ is AFAIK only available in gcc 10, so some different solution would be needed if using LTO with gcc < 10. See https://gcc.gnu.org/legacy-ml/gcc-patches/2019-11/msg01334.html

@rathann
Copy link
Author

rathann commented Jun 22, 2021

@sezero I've just tested building xmp from git, it builds against patched libxmp and works just fine, too.

@sezero
Copy link
Collaborator

sezero commented Jun 22, 2021

@sezero I've just tested building xmp from git, it builds against patched libxmp and works just fine, too.

Great, thank you for testing and feedback!

@cmatsuoka
Copy link
Collaborator

@rathann I'm just curious, does cmatsuoka@3d488c0 work too, keeping ABI compatibility with previous versions?

@sezero
Copy link
Collaborator

sezero commented Jun 22, 2021

The problem is that __symver__ is AFAIK only available in gcc 10,

We need a configury check for it: If it is found, we define HAVE_SYMVER_ATTRIBUTE
or something and prefer it over the externally_visible attribute

so some different solution would be needed if using LTO with gcc < 10.

The externally_visible solution is working for Fedora. (But I guess you are saying
that we need test results from a wider audience.)

@cmatsuoka
Copy link
Collaborator

The externally_visible solution is working for Fedora. (But I guess you are saying
that we need test results from a wider audience.)

But is Fedora using LTO by default with gcc < 10 as well? If so, we'll need to check how other projects are handling it.

@sezero
Copy link
Collaborator

sezero commented Jun 22, 2021

The externally_visible solution is working for Fedora. (But I guess you are saying
that we need test results from a wider audience.)

But is Fedora using LTO by default with gcc < 10 as well? If so, we'll need to check how other projects are handling it.

Possibly. @rathann?

As for compiler support: Does clang support this new attribute?

@rathann
Copy link
Author

rathann commented Jun 22, 2021

Fedora enabled LTO by default in release 33, which shipped with gcc-10.2.1 (and was updated to 10.3.1 subsequently), so the answer is no, it's used with gcc-10 or later only by default.

I'll test @cmatsuoka 's patch later.

@AliceLR
Copy link
Contributor

AliceLR commented Jun 23, 2021

I've confirmed that both patches fix the issue in my Fedora 34 VM (gcc 11.1.1). I don't know enough about this particular problem to have any other useful feedback.

@sezero
Copy link
Collaborator

sezero commented Jun 24, 2021

@cmatsuoka, @rathann, @AliceLR: Is the patch below correct and works?
(It's Claudio's symver attribute patch but just conditionalized.)

@AliceLR
Copy link
Contributor

AliceLR commented Jun 24, 2021

This patch uses xmp_get_player for the LIBXMP_ATTRIB_SYMVER attributes where it should use xmp_set_player... when I fix that, libxmp builds and links correctly in my VM.

@sezero
Copy link
Collaborator

sezero commented Jun 24, 2021

This patch uses xmp_get_player for the LIBXMP_ATTRIB_SYMVER attributes where it should use xmp_set_player... when I fix that, libxmp builds and links correctly in my VM.

Eww, copy/paste srew-up, sorry. Fixed one (hopefully) below:

@sezero
Copy link
Collaborator

sezero commented Jun 24, 2021

This patch uses xmp_get_player for the LIBXMP_ATTRIB_SYMVER attributes where it should use xmp_set_player... when I fix that, libxmp builds and links correctly in my VM.

Eww, copy/paste srew-up, sorry. Fixed one (hopefully) below:

More eww.. Fixed one attached and inlined below: symver_patch.txt

diff --git a/src/common.h b/src/common.h
index 9b88f43..7998988 100644
--- a/src/common.h
+++ b/src/common.h
@@ -29,6 +29,11 @@
 #else
 #define LIBXMP_EXPORT_VERSIONED __attribute__((visibility("default")))
 #endif
+#if defined(__GNUC__) && (__GNUC__ >= 10)
+#define LIBXMP_ATTRIB_SYMVER(_sym) __attribute__((__symver__(_sym)))
+#else
+#define LIBXMP_ATTRIB_SYMVER(_sym)
+#endif /* gcc >= 10 */
 #endif
 #endif
 
diff --git a/src/control.c b/src/control.c
index 9644374..ff581aa 100644
--- a/src/control.c
+++ b/src/control.c
@@ -310,18 +310,20 @@ int xmp_channel_vol(xmp_context opaque, int chn, int vol)
 }
 
 #ifdef USE_VERSIONED_SYMBOLS
-LIBXMP_EXPORT_VERSIONED extern int xmp_set_player_v40__(xmp_context, int, int);
+LIBXMP_EXPORT_VERSIONED extern int xmp_set_player_v40__(xmp_context, int, int) LIBXMP_ATTRIB_SYMVER("xmp_set_player@XMP_4.0");
 LIBXMP_EXPORT_VERSIONED extern int xmp_set_player_v41__(xmp_context, int, int)
-			__attribute__((alias("xmp_set_player_v40__")));
+			__attribute__((alias("xmp_set_player_v40__"))) LIBXMP_ATTRIB_SYMVER("xmp_set_player@XMP_4.1");
 LIBXMP_EXPORT_VERSIONED extern int xmp_set_player_v43__(xmp_context, int, int)
-			__attribute__((alias("xmp_set_player_v40__")));
+			__attribute__((alias("xmp_set_player_v40__"))) LIBXMP_ATTRIB_SYMVER("xmp_set_player@XMP_4.3");
 LIBXMP_EXPORT_VERSIONED extern int xmp_set_player_v44__(xmp_context, int, int)
-			__attribute__((alias("xmp_set_player_v40__")));
+			__attribute__((alias("xmp_set_player_v40__"))) LIBXMP_ATTRIB_SYMVER("xmp_set_player@@XMP_4.4");
 
+#if !defined(__GNUC__) || (__GNUC__ < 10)
 asm(".symver xmp_set_player_v40__, xmp_set_player@XMP_4.0");
 asm(".symver xmp_set_player_v41__, xmp_set_player@XMP_4.1");
 asm(".symver xmp_set_player_v43__, xmp_set_player@XMP_4.3");
 asm(".symver xmp_set_player_v44__, xmp_set_player@@XMP_4.4");
+#endif
 
 #define xmp_set_player__ xmp_set_player_v40__
 #else
@@ -428,21 +430,23 @@ int xmp_set_player__(xmp_context opaque, int parm, int val)
 }
 
 #ifdef USE_VERSIONED_SYMBOLS
-LIBXMP_EXPORT_VERSIONED extern int xmp_get_player_v40__(xmp_context, int);
+LIBXMP_EXPORT_VERSIONED extern int xmp_get_player_v40__(xmp_context, int) LIBXMP_ATTRIB_SYMVER("xmp_get_player@XMP_4.0");
 LIBXMP_EXPORT_VERSIONED extern int xmp_get_player_v41__(xmp_context, int)
-		__attribute__((alias("xmp_get_player_v40__")));
+		__attribute__((alias("xmp_get_player_v40__"))) LIBXMP_ATTRIB_SYMVER("xmp_get_player@XMP_4.1");
 LIBXMP_EXPORT_VERSIONED extern int xmp_get_player_v42__(xmp_context, int)
-		__attribute__((alias("xmp_get_player_v40__")));
+		__attribute__((alias("xmp_get_player_v40__"))) LIBXMP_ATTRIB_SYMVER("xmp_get_player@XMP_4.2");
 LIBXMP_EXPORT_VERSIONED extern int xmp_get_player_v43__(xmp_context, int)
-		__attribute__((alias("xmp_get_player_v40__")));
+		__attribute__((alias("xmp_get_player_v40__"))) LIBXMP_ATTRIB_SYMVER("xmp_get_player@XMP_4.3");
 LIBXMP_EXPORT_VERSIONED extern int xmp_get_player_v44__(xmp_context, int)
-		__attribute__((alias("xmp_get_player_v40__")));
+		__attribute__((alias("xmp_get_player_v40__"))) LIBXMP_ATTRIB_SYMVER("xmp_get_player@@XMP_4.4");
 
+#if !defined(__GNUC__) || (__GNUC__ < 10)
 asm(".symver xmp_get_player_v40__, xmp_get_player@XMP_4.0");
 asm(".symver xmp_get_player_v41__, xmp_get_player@XMP_4.1");
 asm(".symver xmp_get_player_v42__, xmp_get_player@XMP_4.2");
 asm(".symver xmp_get_player_v43__, xmp_get_player@XMP_4.3");
 asm(".symver xmp_get_player_v44__, xmp_get_player@@XMP_4.4");
+#endif
 
 #define xmp_get_player__ xmp_get_player_v40__
 #else

@cmatsuoka
Copy link
Collaborator

Perhaps we could write a macro that can be used to declare versioned symbols and switch between asm or attribute in the macro definition. I'll try it and propose a change if it looks good enough.

@cmatsuoka
Copy link
Collaborator

Perhaps we could write a macro that can be used to declare versioned symbols and switch between asm or attribute in the macro definition. I'll try it and propose a change if it looks good enough.

It didn't, @sezero's solution is more verbose but less ugly/magic. The only thing I'd change is to test for availablliity of attribute __symver__ in configure.ac instead of checking the compiler version.

@sezero
Copy link
Collaborator

sezero commented Jun 24, 2021

I don't have a setup with gcc10+ so I don't have a configure.ac solution.
Do you have one?

@cmatsuoka
Copy link
Collaborator

I don't have a setup with gcc10+ so I don't have a configure.ac solution.
Do you have one?

This should do the trick: cmatsuoka@cc4e53d

(From a quick glance at the current configure.ac I also think that compilation with the Sun Studio compiler will fail to set symbol visibility correctly, but we can see that later.)

@sezero
Copy link
Collaborator

sezero commented Jun 24, 2021

I don't have a setup with gcc10+ so I don't have a configure.ac solution.
Do you have one?

This should do the trick: cmatsuoka@cc4e53d

The attribute is new, so -Werror=attributes should be supported if the
attribute itself is supported: So I guess it should be good. It fails properly
with my old gcc versions:

configure:4670: checking whether compiler understands attribute __symver__
configure:4693: gcc -c -g -O2 -Wall -fvisibility=hidden -DXMP_SYM_VISIBILITY -DHAVE_EXTERNAL_VISIBILITY -Werror=attributes  conftest.c >&5
conftest.c:19: error: '__symver__' attribute directive ignored
configure:4700: $? = 1
configure: failed program was:
| /* confdefs.h.  */
| #define PACKAGE_NAME ""
| #define PACKAGE_TARNAME ""
| #define PACKAGE_VERSION ""
| #define PACKAGE_STRING ""
| #define PACKAGE_BUGREPORT ""
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
| #define HAVE_STDLIB_H 1
| #define HAVE_STRING_H 1
| #define HAVE_MEMORY_H 1
| #define HAVE_STRINGS_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_UNISTD_H 1
| /* end confdefs.h.  */
| 
| void foo(void) __attribute__((__symver__("foo@bar")));
configure:4716: result: no

(From a quick glance at the current configure.ac I also think that compilation with the Sun Studio compiler will fail to set symbol visibility correctly, but we can see that later.)

Have we actually ever tested that compiler along with its visibility support?

@sezero
Copy link
Collaborator

sezero commented Jun 24, 2021

OK, here is a patch incorporating the autotools solution of @cmatsuoka,
attached here and also inlined below: symver_patch2.txt. Works? OK to apply?

diff --git a/configure.ac b/configure.ac
index 909cc96..6c4639e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -139,12 +139,18 @@ dnl https://github.com/libxmp/libxmp/issues/385
    if test $ac_cv_c_flag_w_all = yes; then
       CFLAGS="${CFLAGS} -Werror"
    fi
-   XMP_TRY_COMPILE(whether compiler understands externally_visible attribute,
+   XMP_TRY_COMPILE(whether compiler understands attribute externally_visible,
     ac_cv_c_attribute_visibility_external,[],[
 __attribute__((visibility("default"),externally_visible)) int foo(void);
 int foo(void) { return 0; }],
     [CFLAGS="${old_CFLAGS} -DHAVE_EXTERNAL_VISIBILITY"],
     [CFLAGS="${old_CFLAGS}"])
+
+   XMP_TRY_COMPILE(whether compiler understands attribute __symver__,
+    ac_cv_c_attribute_symver,[-Werror=attributes],[
+void foo(void) __attribute__((__symver__("foo@bar")));],
+    [CFLAGS="${CFLAGS} -DHAVE_ATTRIBUTE_SYMVER"],
+    [CFLAGS="${CFLAGS}"])
 fi
 
 dnl for clang
diff --git a/lite/configure.ac b/lite/configure.ac
index e094b42..501b66b 100644
--- a/lite/configure.ac
+++ b/lite/configure.ac
@@ -138,12 +138,18 @@ dnl https://github.com/libxmp/libxmp/issues/385
    if test $ac_cv_c_flag_w_all = yes; then
       CFLAGS="${CFLAGS} -Werror"
    fi
-   XMP_TRY_COMPILE(whether compiler understands externally_visible attribute,
+   XMP_TRY_COMPILE(whether compiler understands attribute externally_visible,
     ac_cv_c_attribute_visibility_external,[],[
 __attribute__((visibility("default"),externally_visible)) int foo(void);
 int foo(void) { return 0; }],
     [CFLAGS="${old_CFLAGS} -DHAVE_EXTERNAL_VISIBILITY"],
     [CFLAGS="${old_CFLAGS}"])
+
+   XMP_TRY_COMPILE(whether compiler understands attribute __symver__,
+    ac_cv_c_attribute_symver,[-Werror=attributes],[
+void foo(void) __attribute__((__symver__("foo@bar")));],
+    [CFLAGS="${CFLAGS} -DHAVE_ATTRIBUTE_SYMVER"],
+    [CFLAGS="${CFLAGS}"])
 fi
 
 dnl for clang
diff --git a/src/common.h b/src/common.h
index 9b88f43..a18bf0d 100644
--- a/src/common.h
+++ b/src/common.h
@@ -29,6 +29,11 @@
 #else
 #define LIBXMP_EXPORT_VERSIONED __attribute__((visibility("default")))
 #endif
+#ifdef HAVE_ATTRIBUTE_SYMVER
+#define LIBXMP_ATTRIB_SYMVER(_sym) __attribute__((__symver__(_sym)))
+#else
+#define LIBXMP_ATTRIB_SYMVER(_sym)
+#endif
 #endif
 #endif
 
diff --git a/src/control.c b/src/control.c
index 9644374..7cb913e 100644
--- a/src/control.c
+++ b/src/control.c
@@ -310,18 +310,20 @@ int xmp_channel_vol(xmp_context opaque, int chn, int vol)
 }
 
 #ifdef USE_VERSIONED_SYMBOLS
-LIBXMP_EXPORT_VERSIONED extern int xmp_set_player_v40__(xmp_context, int, int);
+LIBXMP_EXPORT_VERSIONED extern int xmp_set_player_v40__(xmp_context, int, int) LIBXMP_ATTRIB_SYMVER("xmp_set_player@XMP_4.0");
 LIBXMP_EXPORT_VERSIONED extern int xmp_set_player_v41__(xmp_context, int, int)
-			__attribute__((alias("xmp_set_player_v40__")));
+			__attribute__((alias("xmp_set_player_v40__"))) LIBXMP_ATTRIB_SYMVER("xmp_set_player@XMP_4.1");
 LIBXMP_EXPORT_VERSIONED extern int xmp_set_player_v43__(xmp_context, int, int)
-			__attribute__((alias("xmp_set_player_v40__")));
+			__attribute__((alias("xmp_set_player_v40__"))) LIBXMP_ATTRIB_SYMVER("xmp_set_player@XMP_4.3");
 LIBXMP_EXPORT_VERSIONED extern int xmp_set_player_v44__(xmp_context, int, int)
-			__attribute__((alias("xmp_set_player_v40__")));
+			__attribute__((alias("xmp_set_player_v40__"))) LIBXMP_ATTRIB_SYMVER("xmp_set_player@@XMP_4.4");
 
+#ifndef HAVE_ATTRIBUTE_SYMVER
 asm(".symver xmp_set_player_v40__, xmp_set_player@XMP_4.0");
 asm(".symver xmp_set_player_v41__, xmp_set_player@XMP_4.1");
 asm(".symver xmp_set_player_v43__, xmp_set_player@XMP_4.3");
 asm(".symver xmp_set_player_v44__, xmp_set_player@@XMP_4.4");
+#endif
 
 #define xmp_set_player__ xmp_set_player_v40__
 #else
@@ -428,21 +430,23 @@ int xmp_set_player__(xmp_context opaque, int parm, int val)
 }
 
 #ifdef USE_VERSIONED_SYMBOLS
-LIBXMP_EXPORT_VERSIONED extern int xmp_get_player_v40__(xmp_context, int);
+LIBXMP_EXPORT_VERSIONED extern int xmp_get_player_v40__(xmp_context, int) LIBXMP_ATTRIB_SYMVER("xmp_get_player@XMP_4.0");
 LIBXMP_EXPORT_VERSIONED extern int xmp_get_player_v41__(xmp_context, int)
-		__attribute__((alias("xmp_get_player_v40__")));
+		__attribute__((alias("xmp_get_player_v40__"))) LIBXMP_ATTRIB_SYMVER("xmp_get_player@XMP_4.1");
 LIBXMP_EXPORT_VERSIONED extern int xmp_get_player_v42__(xmp_context, int)
-		__attribute__((alias("xmp_get_player_v40__")));
+		__attribute__((alias("xmp_get_player_v40__"))) LIBXMP_ATTRIB_SYMVER("xmp_get_player@XMP_4.2");
 LIBXMP_EXPORT_VERSIONED extern int xmp_get_player_v43__(xmp_context, int)
-		__attribute__((alias("xmp_get_player_v40__")));
+		__attribute__((alias("xmp_get_player_v40__"))) LIBXMP_ATTRIB_SYMVER("xmp_get_player@XMP_4.3");
 LIBXMP_EXPORT_VERSIONED extern int xmp_get_player_v44__(xmp_context, int)
-		__attribute__((alias("xmp_get_player_v40__")));
+		__attribute__((alias("xmp_get_player_v40__"))) LIBXMP_ATTRIB_SYMVER("xmp_get_player@@XMP_4.4");
 
+#ifndef HAVE_ATTRIBUTE_SYMVER
 asm(".symver xmp_get_player_v40__, xmp_get_player@XMP_4.0");
 asm(".symver xmp_get_player_v41__, xmp_get_player@XMP_4.1");
 asm(".symver xmp_get_player_v42__, xmp_get_player@XMP_4.2");
 asm(".symver xmp_get_player_v43__, xmp_get_player@XMP_4.3");
 asm(".symver xmp_get_player_v44__, xmp_get_player@@XMP_4.4");
+#endif
 
 #define xmp_get_player__ xmp_get_player_v40__
 #else

@cmatsuoka
Copy link
Collaborator

Could you open a PR with that so we can also run it through the regression tests? In the meantime I'll set up a dev environment on a Fedora 34 VM.

sezero added a commit to sezero/libxmp that referenced this issue Jun 24, 2021
e.g. with gcc >= 10.
Co-authored-by: Claudio Matsuoka<notifications@github.com>
Closes: libxmp#385
@sezero
Copy link
Collaborator

sezero commented Jun 24, 2021

Could you open a PR with that

Done: #391

so we can also run it through the regression tests?

Is Travis fixed?

@cmatsuoka
Copy link
Collaborator

Is Travis fixed?

I think we should drop Travis and move windows and mac CI tests to github actions, wdyt?

@sezero
Copy link
Collaborator

sezero commented Jun 24, 2021

Is Travis fixed?

I think we should drop Travis and move windows and mac CI tests to github actions, wdyt?

Whatever works - so long that our unit tests are run

@cmatsuoka
Copy link
Collaborator

Ok, I'll check how to port existing tests from travis to gh actions.

@sezero
Copy link
Collaborator

sezero commented Jun 24, 2021

In the meantime, we should fix the travis url so that existing PRs are run

sezero added a commit to sezero/libxmp that referenced this issue Jun 24, 2021
e.g. with gcc >= 10.
Co-authored-by: Claudio Matsuoka <cmatsuoka@gmail.com>
Closes: libxmp#385
@sezero
Copy link
Collaborator

sezero commented Jun 24, 2021

In the meantime, we should fix the travis url so that existing PRs are run

I just tried changing https://notify.travis-ci.org/ to https://notify.travis-ci.com/
in libxmp settings -> webhooks, nothing happened

@AliceLR
Copy link
Contributor

AliceLR commented Jun 24, 2021

I think we should drop Travis and move windows and mac CI tests to github actions, wdyt?

That sounds OK to me.

edit: added actions for the sanitizers here: #392.

sezero added a commit to sezero/libxmp that referenced this issue Jun 24, 2021
e.g. with gcc >= 10.
Co-authored-by: Claudio Matsuoka <cmatsuoka@gmail.com>
Closes: libxmp#385
sezero added a commit to sezero/libxmp that referenced this issue Jun 25, 2021
e.g. with gcc >= 10.
Co-authored-by: Claudio Matsuoka <cmatsuoka@gmail.com>
Closes: libxmp#385
sezero added a commit to sezero/libxmp that referenced this issue Jun 26, 2021
e.g. with gcc >= 10.
Co-authored-by: Claudio Matsuoka <cmatsuoka@gmail.com>
Closes: libxmp#385
sezero added a commit to sezero/libxmp that referenced this issue Jun 27, 2021
e.g. with gcc >= 10.
Co-authored-by: Claudio Matsuoka <cmatsuoka@gmail.com>
Closes: libxmp#385
@sezero sezero removed the waiting label Jun 27, 2021
@sezero sezero added this to the 4.5.1 milestone Jul 14, 2022
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

Successfully merging a pull request may close this issue.

4 participants