Search code examples
clinkergtktravis-cixfce

GTK2 link error on Travis-CI


I'm developing an xfce4 plugin and I'm trying to use Travis-CI. I've written a Makefile.am in my root directory like so:

SUBDIRS = src
dist_doc_DATA = README.md

Consequently, in my src directory there is a Makefile.am like this:

bin_PROGRAMS = visualaudio
visualaudio_SOURCES = visualaudio.c
visualaudio_CFLAGS = $(GTK_CFLAGS) $(LIBXFCE4PANEL_CFLAGS) -W -Wall
visualaudio_LDFLAGS = $(GTK_LIBS) $(LIBXFCE4PANEL_LIBS)

I'm using the following commands to configure and build the project:

xdt-autogen && make && make test

This results in the following being run:

Preparing package directory     /home/travis/build/alex/visualaudio...
Running aclocal-1.11   -I /usr/share/xfce4/dev-tools/m4macros -I /usr/share/xfce4/dev-tools/m4macros...
Running autoheader...
Running automake-1.11 --force-missing --add-missing --copy --gnu...
Running autoconf...
Running /home/travis/build/alex/visualaudio/configure --enable-maintainer-mode ...
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether to enable maintainer-specific portions of Makefiles...  yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
checking for pkg-config... /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking for gtk+-2.0 >= 2.6.0... 2.24.10
checking GTK_CFLAGS... -pthread -I/usr/include/gtk-2.0 -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12  
checking GTK_LIBS... -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lglib-2.0  
checking for pkg-config... (cached) /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking for libxfce4panel-1.0 >= 4.8.0... 4.8.6
checking LIBXFCE4PANEL_CFLAGS... -pthread -I/usr/include/xfce4/libxfce4panel-1.0 -I/usr/include/gtk-2.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/xfce4  
checking LIBXFCE4PANEL_LIBS... -Wl,--export-dynamic -pthread -lxfce4panel-1.0 -lgtk-x11-2.0 -lgmodule-2.0 -lrt -lxfce4util -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lglib-2.0  
configure: creating ./config.status
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating config.h
config.status: executing depfiles commands
Now type "make" to compile.
(CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/bash   /home/travis/build/alex/visualaudio/missing --run autoheader)
rm -f stamp-h1
touch config.h.in
cd . && /bin/bash ./config.status config.h
config.status: creating config.h
config.status: config.h is unchanged
make  all-recursive
make[1]: Entering directory `/home/travis/build/alex/visualaudio'
Making all in src
make[2]: Entering directory `/home/travis/build/alex/visualaudio/src'
gcc -DHAVE_CONFIG_H -I. -I..    -pthread -I/usr/include/gtk-2.0 -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12   -pthread -I/usr/include/xfce4/libxfce4panel-1.0 -I/usr/include/gtk-2.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/xfce4   -W -Wall -g -O2 -MT visualaudio-visualaudio.o -MD -MP -MF .deps/visualaudio-visualaudio.Tpo -c -o visualaudio-visualaudio.o `test -f 'visualaudio.c' ||     echo './'`visualaudio.c
mv -f .deps/visualaudio-visualaudio.Tpo .deps/visualaudio-visualaudio.Po
gcc -pthread -I/usr/include/gtk-2.0 -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12   -pthread -I/usr/include/xfce4/libxfce4panel-1.0 -I/usr/include/gtk-2.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12 -I/usr/include/xfce4   -W -Wall -g -O2 -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lglib-2.0   -Wl,--export-dynamic -pthread -lxfce4panel-1.0 -lgtk-x11-2.0 -lgmodule-2.0 -lrt -lxfce4util -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgobject-2.0 -lglib-2.0    -o visualaudio visualaudio- visualaudio.o  
visualaudio-visualaudio.o: In function `on_window_destroy_event':
/home/travis/build/alex/visualaudio/src/visualaudio.c:6: undefined reference to `gtk_main_quit'
visualaudio-visualaudio.o: In function `main':
/home/travis/build/alex/visualaudio/src/visualaudio.c:12: undefined reference to `gtk_init'
/home/travis/build/alex/visualaudio/src/visualaudio.c:14: undefined reference to `gtk_window_new'
/home/travis/build/alex/visualaudio/src/visualaudio.c:15: undefined reference to `gtk_widget_show'
/home/travis/build/alex/visualaudio/src/visualaudio.c:17: undefined reference to `gtk_window_get_type'
/home/travis/build/alex/visualaudio/src/visualaudio.c:17: undefined reference to `g_type_check_instance_cast'
/home/travis/build/alex/visualaudio/src/visualaudio.c:17: undefined reference to `gtk_window_set_decorated'
/home/travis/build/alex/visualaudio/src/visualaudio.c:20: undefined reference to `g_type_check_instance_cast'
/home/travis/build/alex/visualaudio/src/visualaudio.c:20: undefined reference to `g_signal_connect_data'
/home/travis/build/alex/visualaudio/src/visualaudio.c:22: undefined reference to `gtk_main'
collect2: ld returned 1 exit status
make[2]: *** [visualaudio] Error 1
make[2]: Leaving directory `/home/travis/build/alex/visualaudio/src'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/home/travis/build/alex/visualaudio'
make: *** [all] Error 2

Locally, this succeeds without any warnings whatsoever. That's with -W and -Wall. On Travis-CI, it seems the correct libraries aren't being linked, even though in the gcc command, it does seem to reference the correct libraries. My system is running Debian Wheezy with gcc version 4.7.2.

Edit: Just changed the C compiler on Travis-CI to be Clang. Everything compiled and linked successfully. I'm guessing it has to do with the newer version of GCC on Ubuntu compared to Debian. Maybe it's the order of the flags?


Solution

  • Automake manual is hiding the relevant information into its convoluted structure but... you are abusing LDFLAGS.

    By careful reading the section on automake variables you will discover:

    • LIBADD should contain extra objects and libtool libraries (i.e. .la files) to add to a library;
    • LDADD should contain extra objects, libtool libraries and -l, -L, -dlopen and -dlpreopen flags to add to a program;
    • LDFLAGS should contain everything else.

    Furthermore you should note the order of objects, libraries, -l and -L flags is important. This is not a gcc itch but it is dictated by the c99 standard. And this probably means clang built successful because it is not in C99 mode.

    I also suspect libxfce4panel has already a dependency on GTK+ and if you got the flags via pkg-config (as it seems by your configure output) you can just use libxfce4panel only.

    At the end I think the correct Makefile.am could be:

    bin_PROGRAMS = visualaudio
    visualaudio_CFLAGS = $(LIBXFCE4PANEL_CFLAGS)
    visualaudio_LDADD = $(LIBXFCE4PANEL_LIBS)
    

    visualaudio.c as source file is implied. Additional flags should be added by outside via configure, not hardcoded into the makefile, e.g. in your .travis.yml you can use ./configure CFLAGS='-W -Wall'.