Allegro.cc - Online Community

Allegro.cc Forums » Installation, Setup & Configuration » Cross-compilation: stuck on freetype again...

This thread is locked; no one can reply to it. rss feed Print
Cross-compilation: stuck on freetype again...
amarillion
Member #940
January 2001
avatar

I'm giving cross-compilation from linux to windows another go. I'm on an ubuntu focal based system (Linux Mint 20 to be exact). AFAICT I have to

  • I start by installing mingw: apt get mingw-w64

  • Then I have to compile and install dependencies one by one. For the time being I'm just doing zlib, libpng and freetype.

  • Then compile allegro with Toolchain-mingw.cmake

  • (If you know an easier way, do tell!)

I found some useful instructions on cross-compiling various dependencies for OpenTTD which I'm adapting from

Actually compiling the dependencies goes well, here is the script I used:

#SelectExpand
1wget http://zlib.net/zlib-1.2.11.tar.gz -O- | tar xfz - 2cd zlib* 3# zlib 'configure' script is currently broken, use win32/Makefile.gcc directly 4sed -e s/"PREFIX ="/"PREFIX = i686-w64-mingw32-"/ -i win32/Makefile.gcc # automatic replacement 5make -f win32/Makefile.gcc 6sudo BINARY_PATH=/usr/i686-w64-mingw32/bin \ 7 INCLUDE_PATH=/usr/i686-w64-mingw32/include \ 8 LIBRARY_PATH=/usr/i686-w64-mingw32/lib \ 9 make -f win32/Makefile.gcc install 10cd .. 11 12wget http://downloads.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.gz -O- | tar xfz - 13cd l*png* 14./configure \ 15 --host=i686-w64-mingw32 \ 16 --prefix=/usr/i686-w64-mingw32 \ 17 CPPFLAGS="-I/usr/i686-w64-mingw32/include" \ 18 LDFLAGS="-L/usr/i686-w64-mingw32/lib" 19make 20sudo make install 21cd .. 22 23wget http://downloads.sourceforge.net/project/freetype/freetype2/2.10.1/freetype-2.10.1.tar.gz -O- | tar xfz - 24cd freetype* 25./configure \ 26 --host=i686-w64-mingw32 \ 27 --prefix=/usr/i686-w64-mingw32 \ 28 --enable-static \ 29 CPPFLAGS="-I/usr/i686-w64-mingw32/include" \ 30 LDFLAGS="-L/usr/i686-w64-mingw32/lib" \ 31 PKG_CONFIG_LIBDIR=/usr/i686-w64-mingw32/lib/pkgconfig 32make 33sudo make install 34cd ..

Freetype configure ends with the following

configure:

Library configuration:
  external zlib: yes (pkg-config)
  bzip2:         no
  libpng:        yes (pkg-config)
  harfbuzz:      no

Which looks like everything is OK.

Then I continue compiling from my working copy of allegro:

mkdir Build/Mingw-w64
cd Build/Mingw-w64
cmake -DCMAKE_TOOLCHAIN_FILE=../../cmake/Toolchain-mingw.cmake ../..

Unfortunately, freetype is found but not picked up. cmake reports (full output attached):

-- Found Freetype: /usr/i686-w64-mingw32/lib/libfreetype.a (found version "2.10.1") 
-- Performing Test TTF_COMPILES
-- Performing Test TTF_COMPILES - Failed
-- Performing Test TTF_COMPILES_WITH_EXTRA_DEPS
-- Performing Test TTF_COMPILES_WITH_EXTRA_DEPS - Failed
CMake Warning at addons/CMakeLists.txt:137 (message):
  FreeType doesn't compile.  Disabling support.

CMakeError log is attached, I think this is the interesting bit:

/usr/bin/i686-w64-mingw32-gcc  -msse -W -Wall -Wpointer-arith -Wmissing-declarations -Wstrict-prototypes -Wdeclaration-after-statement -DTTF_COMPILES_WITH_EXTRA_DEPS    -Wl,--whole-archive CMakeFiles/cmTC_a42c1.dir/objects.a -Wl,--no-whole-archive  -o cmTC_a42c1.exe -Wl,--out-implib,libcmTC_a42c1.dll.a -Wl,--major-image-version,0,--minor-image-version,0 @CMakeFiles/cmTC_a42c1.dir/linklibs.rsp
/usr/bin/i686-w64-mingw32-ld: /usr/i686-w64-mingw32/lib/libfreetype.a(sfnt.o): in function `Load_SBit_Png':
/home/martijn/prg/alleg/allegro-buildenv/alleg5-crosscompile/freetype-2.10.1/src/sfnt/pngshim.c:290: undefined reference to `png_create_read_struct'
/usr/bin/i686-w64-mingw32-ld: /home/martijn/prg/alleg/allegro-buildenv/alleg5-crosscompile/freetype-2.10.1/src/sfnt/pngshim.c:300: undefined reference to `png_create_info_struct'
/usr/bin/i686-w64-mingw32-ld: /home/martijn/prg/alleg/allegro-buildenv/alleg5-crosscompile/freetype-2.10.1/src/sfnt/pngshim.c:308: undefined reference to `png_set_longjmp_fn'
/usr/bin/i686-w64-mingw32-ld: /home/martijn/prg/alleg/allegro-buildenv/alleg5-crosscompile/freetype-2.10.1/src/sfnt/pngshim.c:441: undefined reference to `png_destroy_read_struct'
/usr/bin/i686-w64-mingw32-ld: /home/martijn/prg/alleg/allegro-buildenv/alleg5-crosscompile/freetype-2.10.1/src/sfnt/pngshim.c:314: undefined reference to `png_set_read_fn'
/usr/bin/i686-w64-mingw32-ld: /home/martijn/prg/alleg/allegro-buildenv/alleg5-crosscompile/freetype-2.10.1/src/sfnt/pngshim.c:316: undefined reference to `png_read_info'

Lot's of undefined references to png functions. Apparently, freetype is not happy finding libpng after all. Why not? Any suggestions on how to troubleshoot this further?

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

amarillion
Member #940
January 2001
avatar

Thanks Edgar, that does the trick! My cmake command is now:

cmake  -DCMAKE_TOOLCHAIN_FILE=../../cmake/Toolchain-mingw.cmake \
  -DFREETYPE_PNG=on \
  -DFREETYPE_ZLIB=on \
  -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  -DWANT_DEMO=off \
  -DWANT_EXAMPLES=off \
  -DWANT_DOCS=off \
  ../..

png, zlib, freetype, ogg and vorbis are included now. I finally managed to cross-compile one of my games with it. Next, I'll give DUMB a go.

Some further questions:

  • Is there a way to tell cmake to look for libraries in /usr/local/i686-w64-mingw32 instead of /usr/i686-w64-mingw32? It would be nice to keep my homebrew stuff separate from the packaging system. I tried -DCMAKE_INCLUDE_PATH:PATH=/usr/local/i686-w64-mingw32/include -DCMAKE_LIBRARY_PATH:PATH=/usr/local/i686-w64-mingw32/lib </code> but that doesn't seem to have any effect.


  • I also notice that freetype has a lot of optional dependencies. What would be the use of e.g. harfbuzz?

edit; and:

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

amarillion
Member #940
January 2001
avatar

Ok, a little further. I figured out minimp3 and I got DUMB almost working.

For reference, I fetch & cross-compile DUMB with:

#SelectExpand
1git clone https://github.com/kode54/dumb.git --depth 1 2 3cd dumb* 4mkdir -p build/release 5cd build/release 6cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \ 7 -DCMAKE_TOOLCHAIN_FILE=Toolchain-mingw.cmake \ 8 -DCMAKE_INSTALL_PREFIX=/usr/i686-w64-mingw32 \ 9 -DBUILD_SHARED_LIBS:BOOL=OFF \ 10 -DBUILD_EXAMPLES:BOOL=OFF \ 11 -DBUILD_ALLEGRO4:BOOL=OFF \ 12 ../.. 13make 14sudo make install 15sudo ldconfig

Custom Toolchain-mingw.cmake for DUMB:

#SelectExpand
1# the name of the target operating system 2SET(CMAKE_SYSTEM_NAME Windows) 3 4# which compilers to use for C and C++ 5SET(CMAKE_C_COMPILER i686-w64-mingw32-gcc) 6SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) 7SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres) 8 9# here is the target environment located 10SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32 ) 11 12# adjust the default behaviour of the FIND_XXX() commands: 13# search headers and libraries in the target environment, search 14# programs in the host environment 15set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 16set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 17set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

With all of that, DUMB compiles, and allegro's cmake picks it up.

edit(2):

I got a new problem. I suddenly started showing up so I thought it was related to DUMB, but it's actually caused by static compilation (with -DWANT_STATIC_RUNTIME=on)

It's strangely inconsistent though, sometimes it works and sometimes it doesn't For now I'm skipping the static build.

It's also similar to this: https://stackoverflow.com/questions/11267877/mingw-multiple-definition-of-unwind-resume

[ 71%] Building C object addons/image/CMakeFiles/allegro_image.dir/tga.c.obj
[ 72%] Building C object addons/image/CMakeFiles/allegro_image.dir/dds.c.obj
[ 72%] Building C object addons/image/CMakeFiles/allegro_image.dir/identify.c.obj
[ 73%] Building CXX object addons/image/CMakeFiles/allegro_image.dir/gdiplus.cpp.obj
[ 74%] Linking CXX shared library ../../lib/allegro_image-debug-5.2.dll
/usr/bin/i686-w64-mingw32-ld: /usr/lib/gcc/i686-w64-mingw32/9.3-win32/libgcc_eh.a(unwind-sjlj.o):(.text+0x400): multiple definition of `_Unwind_SjLj_Register'; ../../lib/liballegro-debug.dll.a(d000067.o):(.text+0x0): first defined here
/usr/bin/i686-w64-mingw32-ld: /usr/lib/gcc/i686-w64-mingw32/9.3-win32/libgcc_eh.a(unwind-sjlj.o):(.text+0x490): multiple definition of `_Unwind_SjLj_Unregister'; ../../lib/liballegro-debug.dll.a(d000070.o):(.text+0x0): first defined here
/usr/bin/i686-w64-mingw32-ld: /usr/lib/gcc/i686-w64-mingw32/9.3-win32/libgcc_eh.a(unwind-sjlj.o):(.text+0x780): multiple definition of `_Unwind_SjLj_Resume'; ../../lib/liballegro-debug.dll.a(d000068.o):(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
make[2]: *** [addons/image/CMakeFiles/allegro_image.dir/build.make:187: lib/allegro_image-debug-5.2.dll] Error 1
make[1]: *** [CMakeFiles/Makefile2:407: addons/image/CMakeFiles/allegro_image.dir/all] Error 2
make: *** [Makefile:130: all] Error 2
The command '/bin/sh -c ./build-alleg5-mingw-debug.sh &&        ./build-alleg5-mingw-monolith.sh &&     ./build-alleg5-mingw-release.sh &&      ./build-alleg5-mingw-static.sh &&         rm -rf /home/builder/allegro5/Build' returned a non-zero code: 2
make: *** [makefile:7: build] Error 2

How do I end up with multiple definitions of libgcc_eh.a(unwind-sjlj.o) (whatever that is?)

Any advice to get static compilation working?

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

It happens because libgcc is linked twice, once dynamically with allegro, and once statically with your exe.

Make sure allegro is built statically linked to gcc by editing CFLAGS and adding -static at the beginning and -static-libgcc and -static-libstdc++ at the end.

You may also want to statically link -lpthread since it is used by mingw and allegro.

amarillion
Member #940
January 2001
avatar

It happens because libgcc is linked twice, once dynamically with allegro, and once statically with your exe.

That makes sense, but the error occurs during the build of allegro, not my exe (allegro_image addon to be precise). Could the same conflict occur between allegro and one of the dependent libs? How do I find out which lib contains the offending duplicate definition?

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

amarillion
Member #940
January 2001
avatar

Still no luck with the static library. I can give more details though (edit, I found a workaround, but I still have questions...)

Here are the preparation steps:

mkdir -p /home/builder/allegro5/Build/MingwStatic
cd /home/builder/allegro5/Build/MingwStatic
cmake \
  -DCMAKE_TOOLCHAIN_FILE=../../cmake/Toolchain-mingw.cmake \
  -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  -DWANT_STATIC_RUNTIME=on \
  -DFREETYPE_PNG=on \
  -DFREETYPE_ZLIB=on \
  -DWANT_DEMO=off -DWANT_EXAMPLES=off -DWANT_DOCS=off \
  ../..

Here is the exact command that is failing:

make VERBOSE=1
/usr/bin/i686-w64-mingw32-g++   -msse -W -Wall -Wpointer-arith -O2 -g -DNDEBUG -static-libgcc -static-libstdc++ -static -lpthread -shared -o ../../lib/allegro_image-5.2.dll -Wl,--out-implib,../../lib/liballegro_image.dll.a -Wl,--major-image-version,5,--minor-image-version,2 -Wl,--whole-archive CMakeFiles/allegro_image.dir/objects.a -Wl,--no-whole-archive @CMakeFiles/allegro_image.dir/linklibs.rsp

Do you see anything wrong with this?

Contents of referred file in addons/image/CMakeFiles/allegro_image.dir/linklibs.rsp:

 ../../lib/liballegro.dll.a /usr/i686-w64-mingw32/lib/libgdiplus.a -luuid -luser32 -lgdi32 -lcomdlg32 -lole32 -lwinmm -lkernel32 -lpsapi -lshlwapi /usr/i686-w64-mingw32/lib/libd3d9.a /usr/i686-w64-mingw32/lib/libdinput8.a -lopengl32 -lglu32 -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32

Here is again the (same) error I'm getting:

/usr/bin/i686-w64-mingw32-ld: /usr/lib/gcc/i686-w64-mingw32/9.3-win32/libgcc_eh.a(unwind-sjlj.o):(.text+0x400): multiple definition of `_Unwind_SjLj_Register'; ../../lib/liballegro.dll.a(d000067.o):(.text+0x0): first defined here
/usr/bin/i686-w64-mingw32-ld: /usr/lib/gcc/i686-w64-mingw32/9.3-win32/libgcc_eh.a(unwind-sjlj.o):(.text+0x490): multiple definition of `_Unwind_SjLj_Unregister'; ../../lib/liballegro.dll.a(d000070.o):(.text+0x0): first defined here
/usr/bin/i686-w64-mingw32-ld: /usr/lib/gcc/i686-w64-mingw32/9.3-win32/libgcc_eh.a(unwind-sjlj.o):(.text+0x780): multiple definition of `_Unwind_SjLj_Resume'; ../../lib/liballegro.dll.a(d000068.o):(.text+0x0): first defined here

I've examined a few object files with nm like you say.

nm /usr/lib/gcc/i686-w64-mingw32/9.3-win32/libgcc_eh.a | grep SjLj_Register
nm: unwind-dw2.o: no symbols
00000400 T __Unwind_SjLj_Register

nm CMakeFiles/allegro.dir/objects.a | grep SjLj_Register
    U __Unwind_SjLj_Register

As far as I can tell this is correct, libgcc_eh.a contains the type definition, CMakeFiles/allegro.dir/objects.a lists the symbol as undefined. This is how it should be, right?

edit:

So I found a workaround. If I manually run that one compilation step with the extra flags "-Wl,-allow-multiple-definition" (as adviced here https://stackoverflow.com/questions/11267877/mingw-multiple-definition-of-unwind-resume) that one step completes, and I can finish continue the entire library with make.

Would there be a downside to just always adding those flags?

edit 2:

Also, is there a way to override those flags when you invoke cmake?
I tried calling cmake with -DCMAKE_STATIC_LINKER_FLAGS=-Wl,-allow-multiple-definition. I can confirm that the flag appears in CMakeCache.txt, but compilation fails anyway with the same error as above.

edit 3:

So, weirdly enough, it works when I pass -DCMAKE_SHARED_LINKER_FLAGS=-Wl,-allow-multiple-definition to cmake when doing the static build of allegro.

All that remains now is figuring out what can be improved to the allegro build files so this hack isn't necessary.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

amarillion
Member #940
January 2001
avatar

Check CMakeFiles/allegro.dir/linklibs.rsp and see what it contains before building but after generation with CMake

What am I looking for exactly? I notice that the -Wl,-allow-multiple-definition flag ends up in link.txt, not linklibs.rsp.

Quote:

It would also be much easier to use cmake-gui, even on Linux.

I never understood cmake-gui. The tool just baffles me. The only useful thing it does is that, by scanning a long list of (undocumented) options, you might have a chance of guessing the right one that you need to change.

edit: ok here is what I see.

# contents of addons/image/CMakeFiles/allegro_image.dir/linklibs.rsp
 ../../lib/liballegro.dll.a /usr/i686-w64-mingw32/lib/libgdiplus.a -luuid -luser32 -lgdi32 -lcomdlg32 -lole32 -lwinmm -lkernel32 -lpsapi -lshlwapi /usr/i686-w64-mingw32/lib/libd3d9.a /usr/i686-w64-mingw32/lib/libdinput8.a -lopengl32 -lglu32 -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 

# contents of addons/font/CMakeFiles/allegro_font.dir/linklibs.rsp
 ../../lib/liballegro.dll.a -luser32 -lgdi32 -lcomdlg32 -lole32 -lwinmm -lkernel32 -lpsapi -lshlwapi /usr/i686-w64-mingw32/lib/libd3d9.a /usr/i686-w64-mingw32/lib/libdinput8.a -lopengl32 -lglu32 -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 

# contents of addons/color/CMakeFiles/allegro_color.dir/linklibs.rsp
 ../../lib/liballegro.dll.a -luser32 -lgdi32 -lcomdlg32 -lole32 -lwinmm -lkernel32 -lpsapi -lshlwapi /usr/i686-w64-mingw32/lib/libd3d9.a /usr/i686-w64-mingw32/lib/libdinput8.a -lopengl32 -lglu32 -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 

# contents of addons/primitives/CMakeFiles/allegro_primitives.dir/linklibs.rsp
 ../../lib/liballegro.dll.a -luser32 -lgdi32 -lcomdlg32 -lole32 -lwinmm -lkernel32 -lpsapi -lshlwapi /usr/i686-w64-mingw32/lib/libd3d9.a /usr/i686-w64-mingw32/lib/libdinput8.a -lopengl32 -lglu32 -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 

# contents of addons/ttf/CMakeFiles/allegro_ttf.dir/linklibs.rsp 
 ../../lib/liballegro_font.dll.a /usr/i686-w64-mingw32/lib/libfreetype.dll.a ../../lib/liballegro.dll.a -luser32 -lgdi32 -lcomdlg32 -lole32 -lwinmm -lkernel32 -lpsapi -lshlwapi /usr/i686-w64-mingw32/lib/libd3d9.a /usr/i686-w64-mingw32/lib/libdinput8.a -lopengl32 -lglu32 -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

okay, amarillion - after reading more closely a few things appear.

The multiple definition occurs in allegro_image and links to allegro, which has already been linked to the static versions of gcc and stdc++. I take back what I said, static versions should not be linked to anything except system libraries. Remove the commands I told you earlier -static-libgcc and -static-libstdc++ as they are also in the wrong place in the command. You want to add them to your programs link options, so they're only linked once.

Hope this helps. Again, static versions are to remain unlinked until final linkage occurs, otherwise you get multiple definition errors.

Go to: