Skip to content
Cecil Coupe edited this page Feb 24, 2016 · 5 revisions

Shoes 2 and 3 is absolutely, positively, 100% dependent on Cairo - the C library, not the city. Shoes 4 doesn't use Cairo so that's the project for those folks who don't want to deal with Cairo everything that goes with it. Most of this post is actually about how to build Windows dependent libraries.

When Shoes script creates a button the C code calls on Gtk (for Linux and Windows) or Cocoa for OSX. Other native widgets like edit_line and edit_box are also done by Gtk or Cocoa. Checking the shoes manual, you'll note that hell of lot of Shoes isn't native widgets - like para and shapes like oval. Who draws those things? Cairo!

Shoes 3.2 on Windows switched from using Microsoft Widgets and Cairo drawing to using Gtk widgets and Cairo drawing to Gtk things Those gtk things do end up using the Microsoft native facilities. While that decision makes it easier to maintain and enhance Shoes it also exposed some font problems that need fixing and we'll have to dive deeper into Cairo subsystems on Windows to find them and fix them. There's an OSX font annoyance too. Maybe we can fix that too if we learn enough.

Shoes para's are drawn by Cairo using the font type and size specified (inscription or banner textblocks in Shoes). Cairo uses the Pango library to get drawing information about the string and the characters inside. Pango can also be told via plugins (pango modules) about right to left reading systems and other oddities of the worlds written languages. Shoes is left to right, mostly Latin characters and unlikely to change but there is that complexity in pango and cairo.

Of course Pango needs to know about the font before it can advise or respond to Cairo. For GTK, it often calls Fontconfig and/or Freetype. It calls something on OSX to get the font info. For windows, where the font problems are more apparent it probably calls some Windows stuff, if needed and it might be doing it wrong in some situations.

If you skim the documentation of Cairo and Pango you might be wondering which one actually loads the fonts - good question. And on Windows, does it really have to be so complex that we need fontconfig.dll and font.conf and other mysteries?

To fix something we'll need the source and the ability to compile it. You've already guessed that it's a lot of source code to extract, configure and build. You might also know that once we fixed something, it's our tar baby forever. So, I decided to upgrade all the Windows dependencies and build them from source. That way I'll have the little configure scripts and current source code if madness ever strikes again.

I cross compile - because it is so much easier. It hasn't been that easy. Damn near everything depends on zlib (or libz) and libpng. You change one of those and everything gets rebuilt. I do mean everything So that's what I did first. Allow several long days to get this working.

These instructions are similiar but for build on Windows and without the Shoes and ruby stuff.

I created a /home/ccoupe/Projects/shoesdep/mingw - that will be like /usr - every thing will be installed in there. In there I created empty bin,etc,include,lib,man,share. The installs will usually create any missing folders but I like doing things the hard way, sometimes. All of the shell scripts below use a ${dest} variable that you'll want to replace with your own value. If you insist on doing this on Windows then please don't overwrite a working msys and devkit unless you know what your doing.

Instead of building all the Windows dependencies from source, you can download the 43MB monster which has the pre-compiled dll's and includes and shares. Everything you need to build Shoes on Windows or for Windows. Includes both gtk2 and and gtk3.

zlib

All the cool stuff uses version 1.2.8 (except OSX 10.6 but that's a different story). And Shoes on Windows doesn't either. Download zlib-1.2.8.tar.gz, expand it. Create this script, cross-zlib.sh, chmod +x cross-zlib.sh if needed.

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
export INCLUDE_PATH=${dest}/include
export LIBRARY_PATH=${dest}/lib
export BINARY_PATH=${dest}/bin
make -fwin32/Makefile.gcc
make install -fwin32/Makefile.gcc SHARED_MODE=1

cd into zlib-1.2.8 and type ../cross-zlib.sh This not only configures, it builds and installs. Zlib is just special that way. It would be different if you do this on Windows.

libpng

This one isn't quite as crufty as zlib (but close). Here's cross-png.sh:

#! /bin/bash
# execute it instead of ./configure
export dest=/home/ccoupe/Projects/shoesdeps/mingw
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
export PKG_CONFIG_PATH=${dest}/lib/pkgconfig
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --prefix=${dest}

I chose libpng-1.6.16 so cd into it, ../cross-png, make, make install

Now would be a good time to see if the ${dest} bin,include,lib and lib/pkgconfig directories have what you think should be there. I'm not going to repeat the cd. ../cross-xxx, make, make install instructions.

iconv 1.14

cross-iconv.sh:

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --prefix=${dest}

Don't get cocky. That was an easy one.

libffi-3.2.1

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --prefix=${dest}

libxml2-2.9.2

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --with-zlib=${dest} \
  --without-python \
  --prefix=${dest}

gettext-0.19.4 (libintl)

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --prefix=${dest}

Yes, you could take a nap while it configures and builds. You could ./configure --help and cut out some options if you know what you're doing. I don't.

glib-2.42.2

! /bin/bash
# execute this instead of ./configure
export dest=/home/ccoupe/Projects/shoesdeps/mingw
export CC=i686-w64-mingw32-gcc
export CFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
export PKG_CONFIG_PATH="${dest}/lib/pkgconfig"
export LIBFFI_CFLAGS="-I${dest}/lib/libffi-3.2.1/include"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --cache-file=win32.cache \
  --with-threads=win32 \
  --prefix="${dest}"

Ruby deps that might be shared with gtk

Some of these are easy. Lets do them now. - yaml, jpeg, gif, openssl.

yaml-0.1.4 - cross-yaml.sh

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
./configure \
  --enable-shared \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --prefix="$dest"

jpeg-9 -- cross-jpeg.sh

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --prefix=${dest}

giflib-4.2.3 - cross-gif.sh

export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --prefix=${dest}

openssl-1.0.2 -- cross-openssl.sh

This is not like the others. Pay attention.

#! /bin/bash
# execute it instead of ./Configure
export dest=/home/ccoupe/Projects/shoesdeps/mingw
export CPPFLAGS="-I${dest}/include"
export LDFLAGS=-L${dest}/lib
./Configure \
  --cross-compile-prefix=i686-w64-mingw32- mingw zlib-dynamic shared \
  -I${dest}/include \
  --prefix="${dest}"

gdbm-1.11 - cross-gdbm.sh

This is a pain. gdbm needs a patch and you have to find it. If you don't use patch often enough and I don't then you have to figure out that command too.

ccoupe@bronco:~/Projects/shoesdeps/src/gdbm-1.11$ patch -p0 <../gdbm-win32-support.patch

Assuming that applies cleanly, then run the configure script below, make, make install.

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --enable-shared \
  --prefix=${dest}

NOTE: I'm not building 'dbm' compat. Ruby will only have 'gdbm' and 'sdbm'. I doubt any Shoeser will know or care.

decision time

Now we have to deal with the confusing stuff. How to configure fontconfig, harfbuzz, cairo, pango and fellow travelers and eventually gtk2. I'm not going to use harfbuzz. It wasn't used before is my defense. You really need to read the ./configure --help displays to figure out what options you need (and why you want them)

freetype 2.5.5 - cross-freetype.sh

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
export LIBPNG_CFLAGS="-I ${dest}/include/libpng16"
export LIBPNG_LIBS="-L${dest}/lib -lpng16"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --enable-shared \
  --with-harfbuzz=no \
  --prefix=${dest}

After you do the make install, check that you have {dest}/bin/libfreetype-6.dll. If you don't, fix something.

fontconfig 2.11.1 - cross-fontconfig.sh

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
#export PKG_CONFIG_PATH="${dest}/lib/pkgconfig"
export FREETYPE_CFLAGS="-I${dest}/include/freetype2"
export LIBXML2_CFLAGS="-I${dest}/include/libxml2"
export LIBXML2_LIBS="-L/${dest}/lib -lxml2"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --enable-libxml2 \
  --prefix=${dest}

Notice that we explicitly pointed to where freetype and libxml2 are. When cross compiling the configure has a tendency to use the building linux settings if we don't force it to use the cross-compiled locations. Look at the options available with ./configure --help.

Do the make; make install and keep reading.

NOTE: we need to copy fonts.conf to our Shoes source code so it can be copied from there when building an windows installer for Shoes. cp fonts.conf /home/ccoupe/Projects/shoes3.2/platform/msw

While we're doing hard things we don't understand, let's copy fc-cache.exe too - we might need it. We want the one we installed in bin (129KB). ccoupe@bronco:~/Projects/shoesdeps/mingw/bin$ cp fc-cache.exe /home/ccoupe/Projects/shoes3.2/platform/msw/

pixman-0.32.6 - cross-pixman.sh

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
export PNG_CFLAGS="-I${dest}/include/libpng16"
export PNG_LIBS="-L${dest}/lib -lpng16"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --prefix=${dest}

Options? There are some. Do I want them? I have no idea. [UPDATE] - This wasn't in the 3.2.21/gtk bundle. We probably don't need it (referenced from Cairo)

cairo-1.14.0 - cross-cairo.sh

I had to download . I entered the two changes by hand.

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
export png_CFLAGS="-I${dest}/include/libpng16"
export png_LIBS="-L${dest}/lib -lpng16"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --enable-xcb=no \
  --enable-xlib=no \
  --enable-xlib-xrender=no \
  --prefix=${dest}

You do want to see what the ./configure --help options are. Notice that I make sure no X11 stuff leaks into it from the build system. After the ../cross-configure.sh The last 40 lines of the terminal display shows the options selected or detected. You probably want to copy that somewhere in case we did it wrong.

harfbuzz-0.8.38 - cross-harfbuzz.sh

I'm in uncharted territory for Shoes. Pango 1.36.8 won't build without it. Is this correct?

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
export PKG_CONFIG_PATH="${dest}/lib/pkgconfig"
export FREETYPE_CFLAGS="-I${dest}/include/freetype2"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --prefix=${dest}

pango-1.36.8 - cross-pango.sh

Another one to read the options and make choices. Painful and I don't know if it's correct.

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
#export PKG_CONFIG_PATH="${dest}/lib/pkgconfig"
export FREETYPE_CFLAGS="-I${dest}/include/freetype2"
export FONTCONFIG_CFLAGS="-I${dest}/include/fontconfig"
export CAIRO_CFLAGS="-I${dest}/include/cairo"
export GLIB_CFLAGS="-I${dest}/include/glib-2.0 -I${dest}/lib/glib-2.0/include"
export HARFBUZZ_CFLAGS="-I${dest}/include/harfbuzz"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --without-xft \
  --with-cairo \
  --with-included-modules=yes \
  --disable-debug --disable-gtk-doc \
  --prefix=${dest}

atk-2.14.0 - cross-atk.sh

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
./configure \
  --build=x86_64-linux-gnu 
  --host=i686-w64-mingw32 \
  --disable-debug \
  --prefix=${dest}

gdk-pixbuf-2.30.8 -- cross-gdk-pixbuf.sh

It took some work to discover export PKG_CONFIG_LIBDIR="${dest}/lib/pkgconfig" is really important here.

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
export PKG_CONFIG_PATH="${dest}/lib/pkgconfig"
export PKG_CONFIG_LIBDIR="${dest}/lib/pkgconfig"
export PNG_CFLAGS="-I${dest}/include/libpng16"
export PNG_LIBS="-L${dest}/lib -lpng16"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --with-included-loaders=yes \
  --disable-debug \
  --prefix=${dest}

gtk+-2.24.26 - cross-gtk.sh

#! /bin/bash
# execute it instead of ./configure
export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
export PKG_CONFIG_PATH="${dest}/lib/pkgconfig"
export PKG_CONFIG_LIBDIR="${dest}/lib/pkgconfig"
export PNG_CFLAGS="-I${dest}/include/libpng16"
export PNG_LIBS="-L${dest}/lib -lpng16"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --with-gdktarget=win32 \
  --disable-debug --disable-gtk-doc \
  --disable-debug \
  --prefix=${dest}

[UPDATE] libpangowin32.dll is not used by this configurate. In the gtk2 bundle it's used. This could easily explain some issues with font choices.

Run the configure but don't do the make or make install Now it's going to get ugly. Part of the make is to run gtk_update_icon_cache_program.exe to build a gtkbuiltincache.h. That doesn't work on a cross compile and I suspect it may not work on a native compile. Even when run with the native linux gtk_update_icon_cache_program it fails for not having a theme.index. Although the code is told to ignore that problem it still fails.

In gtk/Makefile (around line 5713) we need to comment out the code the causes the Makefile to run gtk_update_icon_cache_program.exe. The directory already has a gtkbuiltincache.h which is good enough to finish the compile with. One could argue the change belongs in gtk/Makefile.in

gtkbuiltincache.h:  stamp-icons
	$(MAKE) $(AM_MAKEFLAGS) gtk-update-icon-cache$(EXEEXT)
	#$(gtk_update_icon_cache_program) --force --ignore-theme-index		\
	#   --include-image-data							\
	#   --source builtin_icons stock-icons > gtkbuiltincache.h.tmp &&        \
	#mv gtkbuiltincache.h.tmp gtkbuiltincache.h

Now you can make; make install

Put a note in your worry folder about icons. In Shoes these would displayed in dialogs like ask or alert. Put another note in there for themes and theme engines.

gtk+-3.6.4 - cross-gtk3.sh

This is a very similar .sh to the cross-gtk.sh. (You could use that one) Success depends on the Gtk3 version. 3.6.4 is a fairly old version of gtk3 but a good place to start. Even it has problems in a cross compile. gtk/Makefile:97 wants to compile gtk-launch.exe (which fails because of a missing <gio/gdesktopappinfo.h> which is in glib so something is amiss. I deleted the build of gtk-launch.exe at line 97. make and make install work and I didn't need the icon theme hack used in building gtk2.

gtk+-3.10.9 - cross-gtk3.sh

export dest="/home/ccoupe/Projects/shoesdeps/mingw"
export CC=i686-w64-mingw32-gcc
export CPPFLAGS="-I${dest}/include"
export LDFLAGS="-L${dest}/lib"
export PKG_CONFIG_FOR_BUILD="/usr/bin/pkg-config"
export PKG_CONFIG_PATH="${dest}/lib/pkgconfig"
export PKG_CONFIG_LIBDIR="${dest}/lib/pkgconfig"
export PNG_CFLAGS="-I${dest}/include/libpng16"
export PNG_LIBS="-L${dest}/lib -lpng16"
./configure \
  --build=x86_64-linux-gnu \
  --host=i686-w64-mingw32 \
  --enable-win32-backend \
  --enable-gtk2-dependency \
  --enable-installed-tests \
  --enable-explicit-deps=no \
  --with-included-immodules=ime \
  --disable-debug --disable-gtk-doc \
  --prefix=${dest}

Although the Gtk folks have attempted to improve cross compiling support it's still spotty and very undocumented. One problem is that gdk.def handling is wrong.

You may have to apply this patch manually

Then you will discover that when compiling extract-strings.c in gtk/ gets you big load of failing because this is supposed to be built on the build system with the includes and libs, not the target (--host in Gnu speak). You might even come across various ENV vars to set when cross compiling. They mostly don't work as expected for 3.10.9 so I resorted to going cowboy on gtk/Makefile.am. Somewhere around Line 1431 you'll make it look like this:

extract_strings_cflags = $(GLIB_CFLAGS_FOR_BUILD)
extract_strings_ldadd = $(GLIB_LIBS_FOR_BUILD)
extract-strings$(BUILD_EXEEXT): $(extract_strings_sources)
	@rm -f extract-strings$(BUILD_EXEEXT)
	$(AM_V_CCLD)$(CC_FOR_BUILD) -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include $^ -lglib-2.0 $(LIBS_FOR_BUILD) -o $@
#	$(AM_V_CCLD)$(CC_FOR_BUILD) $(extract_strings_cppflags) $(CPPFLAGS_FOR_BUILD) $(extract_strings_cflags) $(CFLAGS_FOR_BUILD) $^ $(LDFLAGS_FOR_BUILD) $(extract_strings_ldadd) $(LIBS_FOR_BUILD) -o $@
EXTRA_DIST += $(extract_strings_sources)

Not pretty what I did there but I tried to work the commented out line as written and just gave up.

When you make changes to Makefile.am, you need to run that figure script again. If you run autoconf you'll probably loose the changes altogether.

Ruby 2.1.5 - cross-ruby.sh

Yes we are going to build ruby from source to make sure it uses our newer zlib and our newer gdbm and ff and libintl.dll and... Yes it takes a while. I'm also going to put it in usr/local of my deps dir. And we'll have to update ruby gems the hard way.

Rubygems 2.4.5 - by hand

make a directory somewhere /home/cross/gemtest for this example. expand the rubygems-2.4.5. cd into it. We are going to install it into that gemtest directory and copy from there. Because that works for me. No doubt there is a better way.

Inside the rubygems-2.4.5

ruby setup.rb --prefix=/home/cross/gemtest
cd /home/cross/gemtest/lib

now we want to copy from there (lib) to our ruby that we built site_ruby cp -r * /home/ccoupe/Projects/shoesdeps/mingw/usr/local/lib/ruby/site_ruby/2.1.0/ That was easy.

You dependencies are up to date.

You should create the xwin7-custom.yaml (see the wiki)

Clone this wiki locally