flac icon indicating copy to clipboard operation
flac copied to clipboard

Cross-compiling vorbis/opus-tools with FLAC support is broken on MinGW-w64

Open Touceire opened this issue 3 years ago • 11 comments

Not sure if this is the right place to open an issue but cross-compiling vorbis/opus-tools with FLAC support is broken when using autotools and MinGW-w64.

/usr/bin/x86_64-w64-mingw32-ld: src/opusenc-flac.o:flac.c:(.text+0x29d): undefined reference to `__imp_FLAC__stream_decoder_process_single'
/usr/bin/x86_64-w64-mingw32-ld: src/opusenc-flac.o:flac.c:(.text+0xb28): undefined reference to `__imp_FLAC__stream_decoder_new'
/usr/bin/x86_64-w64-mingw32-ld: src/opusenc-flac.o:flac.c:(.text+0xb37): undefined reference to `__imp_FLAC__stream_decoder_set_md5_checking'
/usr/bin/x86_64-w64-mingw32-ld: src/opusenc-flac.o:flac.c:(.text+0xb3e): undefined reference to `__imp_FLAC__stream_decoder_set_metadata_respond'
/usr/bin/x86_64-w64-mingw32-ld: src/opusenc-flac.o:flac.c:(.text+0xbf2): undefined reference to `__imp_FLAC__stream_decoder_init_ogg_stream'
/usr/bin/x86_64-w64-mingw32-ld: src/opusenc-flac.o:flac.c:(.text+0xbff): undefined reference to `__imp_FLAC__stream_decoder_init_stream'
/usr/bin/x86_64-w64-mingw32-ld: src/opusenc-flac.o:flac.c:(.text+0xc28): undefined reference to `__imp_FLAC__stream_decoder_process_until_end_of_metadata'
/usr/bin/x86_64-w64-mingw32-ld: src/opusenc-flac.o:flac.c:(.text+0xc4a): undefined reference to `__imp_FLAC__stream_decoder_delete'
/usr/bin/x86_64-w64-mingw32-ld: src/opusenc-flac.o:flac.c:(.text+0xd02): undefined reference to `__imp_FLAC__stream_decoder_delete'

Touceire avatar Apr 15 '22 22:04 Touceire

Could you provide some more info as to how you're building opus-tools and how you're building FLAC? Could you also try again with the latest git, because just 22 hours ago a few patches concerning MinGW, specifically dllimport and dllexport attributes, were merged.

ktmf01 avatar Apr 16 '22 05:04 ktmf01

I set up a clean build environment with mingw-w64 10.0.0 on Debian sid and git master doesn't work. You can probably reproduce it by just cloning ogg, flac, opus, opusfile, libopusenc and opus-tools and then running

./autogen.sh
./configure --prefix=$mingw_prefix --host=x86_64-w64-mingw32
make
make install

I also doubled checked and confirmed that b917d45 is the commit in question.

Touceire avatar Apr 16 '22 06:04 Touceire

Many thanks for providing these details. I'll try to reproduce and work out a fix

ktmf01 avatar Apr 16 '22 07:04 ktmf01

I'm unable to reproduce this. I've updated my MSYS2 environment, which has packages for flac, ogg and libopusenc, and when compiling autotools with

./autogen.sh
./configure
make LDFLAGS='-lssp'

I get

make  all-recursive
make[1]: Entering directory '/home/m_van/opus-tools'
Making all in .
make[2]: Entering directory '/home/m_van/opus-tools'
  CC       src/opusenc-opus_header.o
  CC       src/opusenc-opusenc.o
  CC       src/opusenc-tagcompare.o
  CC       src/opusenc-audio-in.o
  CC       src/opusenc-diag_range.o
  CC       src/opusenc-flac.o
  CC       win32/opusenc-unicode_support.o
  CCLD     opusenc.exe
  CC       src/opusdec-opus_header.o
  CC       src/opusdec-wav_io.o
  CC       src/opusdec-wave_out.o
  CC       src/opusdec-opusdec.o
src/opusdec.c: In function 'main':
src/opusdec.c:1131:28: warning: unknown conversion type character 'I' in format [-Wformat=]
 1131 |             fprintf(stderr,"\r[%c] %02" I64FORMAT ":%02d:%02d",
      |                            ^~~~~~~~~~~~
src/opusdec.c:111:21: note: format string is defined here
  111 | # define I64FORMAT "I64d"
      |                     ^
src/opusdec.c:1131:28: warning: format '%d' expects argument of type 'int', but argument 4 has type 'opus_int64' {aka 'long long int'} [-Wformat=]
 1131 |             fprintf(stderr,"\r[%c] %02" I64FORMAT ":%02d:%02d",
      |                            ^~~~~~~~~~~~
 1132 |              spinner[last_spin&3], coded_seconds/3600,
      |                                    ~~~~~~~~~~~~~~~~~~
      |                                                 |
      |                                                 opus_int64 {aka long long int}
src/opusdec.c:1131:56: note: format string is defined here
 1131 |             fprintf(stderr,"\r[%c] %02" I64FORMAT ":%02d:%02d",
      |                                                     ~~~^
      |                                                        |
      |                                                        int
      |                                                     %02lld
src/opusdec.c:1131:28: warning: too many arguments for format [-Wformat-extra-args]
 1131 |             fprintf(stderr,"\r[%c] %02" I64FORMAT ":%02d:%02d",
      |                            ^~~~~~~~~~~~
  CC       src/opusdec-resample.o
  CC       src/opusdec-diag_range.o
  CC       win32/opusdec-unicode_support.o
  CCLD     opusdec.exe
  CC       src/opusinfo-opus_header.o
  CC       src/opusinfo-opusinfo.o
  CC       src/opusinfo-info_opus.o
  CC       src/opusinfo-picture.o
  CC       src/opusinfo-tagcompare.o
  CC       win32/opusinfo-unicode_support.o
  CCLD     opusinfo.exe
  CC       src/opusrtp.o
  CCLD     opusrtp.exe
make[2]: Leaving directory '/home/m_van/opus-tools'
make[1]: Leaving directory '/home/m_van/opus-tools'

Could you please share your config.log file when building opus-tools? Perhaps running make clean all V=1 > buildlog 2>&1 and uploading that too would help as well

ktmf01 avatar Apr 19 '22 06:04 ktmf01

On second thought, make clean all V=1 LDFLAGS='-Wl,--verbose' > buildlog 2>&1 would provide even more useful information

ktmf01 avatar Apr 19 '22 07:04 ktmf01

Could you try again with --disable-shared? config.log build.log

Touceire avatar Apr 19 '22 09:04 Touceire

Okay, I found the problem, I'll work on a fix.

ktmf01 avatar Apr 19 '22 11:04 ktmf01

Digging a little deeper, it turns out this is not something FLAC can fix, it is one of the intricacies of linking on Windows. See https://stackoverflow.com/questions/4841719/dllimport-dllexport-and-static-libraries-compilation-under-visual-c

From there I quote

So the rule is: the client must chose the method of linking to a library, the provider should provide both versions.

opus-tools is the client here, the provider libFLAC. Apparently opus-tools on Windows is meant to be used with DLLs. To accomplish static linkage, one must also define FLAC__NO_DLL. You can do this by adding -DFLAC__NO_DLL to CFLAGS somewhere, or by adding #define FLAC__NO_DLL to the config.h file of opus tools when linking to a static compile of FLAC. Could you let me know whether that fixes the problem?

I didn't know this either, one learns something new every day.

ktmf01 avatar Apr 19 '22 12:04 ktmf01

adding -DFLAC__NO_DLL to CFLAGS somewhere, or by adding #define FLAC__NO_DLL

That does seem to fix the issue for me.

Touceire avatar Apr 19 '22 18:04 Touceire

Let me know when you experience other issues. I'll leave this issue open as a TODO to check whether FLAC__NO_DLL is mentioned anywhere in the documentation

ktmf01 avatar Apr 19 '22 18:04 ktmf01

It is documented here https://xiph.org/flac/api/group__flac__export.html and here https://xiph.org/flac/api/group__flacpp__export.html but it is a rather short notice. I'll add some more explanation.

ktmf01 avatar Apr 30 '22 20:04 ktmf01