May I suggest you start with a minimal Makefile, and only add decorations and options after you get it working?
Let's start with a simple GTK+ 2 example program, split into two files just to make sure our Makefile will work right. I'm not suggesting you split your applications this way; I do not, this is just to test the Makefile logic. (I prefer to put GTK+ stuff in my main C file, and put non-GTK processing in separate files, if I can test them separately. Otherwise in the same file all they go.)
src/example.c:
Code:
#include <stdlib.h>
#include <gtk/gtk.h>
#include "mystuff.h"
int main(int argc, char *argv[])
{
GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(window, "delete-event", G_CALLBACK(gtk_main_quit), NULL);
gtk_window_set_title(GTK_WINDOW(window), "Example");
gtk_window_set_role(GTK_WINDOW(window), "example-gtk-program");
gtk_window_set_decorated(GTK_WINDOW(window), TRUE);
mystuff(window);
gtk_widget_show(window);
gtk_main();
return EXIT_SUCCESS;
}
src/mystuff.h:
Code:
#ifndef MYSTUFF_H
#define MYSTUFF_H
#include <gtk/gtk.h>
void mystuff(GtkWidget *window);
#endif /* MYSTUFF_H */
src/mystuff.c:
Code:
#include <gtk/gtk.h>
void mystuff(GtkWidget *window)
{
GtkWidget *view;
view = gtk_text_view_new();
gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(view)), "Hello, world!", -1);
gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(view), FALSE);
gtk_text_view_set_editable(GTK_TEXT_VIEW(view), FALSE);
gtk_container_add(GTK_CONTAINER(window), view);
gtk_widget_show(view);
}
Typically, the following Makefile should work on any architecture and OS:
Code:
GTKVER := 2.0
PKGCONFIG := pkg-config
CC := gcc
CFLAGS := $(shell $(PKGCONFIG) --cflags gtk+-$(GTKVER))
LD := $(CC)
LDFLAGS := $(shell $(PKGCONFIG) --libs gtk+-$(GTKVER))
EXAMPLE_BIN := example
EXAMPLE_OBJS := example.o mystuff.o
PROGS := $(EXAMPLE_BIN)
OBJDIR := build
SRCDIR := src
.PHONY: all clean
all: $(addprefix $(OBJDIR)/, $(PROGS))
clean:
rm -rf $(OBJDIR)
$(OBJDIR):
mkdir $(OBJDIR)
$(OBJDIR)/%.o: $(SRCDIR)/%.c $(OBJDIR)
$(CC) $(CFLAGS) -c $< -o $@
$(OBJDIR)/$(EXAMPLE_BIN): $(addprefix $(OBJDIR)/, $(EXAMPLE_OBJS))
$(LD) $^ $(LDFLAGS) -o $@
However, if you have OS/architecture specific files you may need to compile in, I guess something like the following Makefile might work:
Code:
GTKVER := 2.0
OBJDIR := build
SRCDIR := src
EXAMPLE_OBJS := example.o mystuff.o
#
# Automagic architecture detection.
#
ifeq ($(ARCH),)
ifeq ($(OS),Windows_NT)
ifeq ($(PROCESSOR_ARCHITECTURE),AMD64)
ARCH := win64
endif
ifeq ($(PROCESSOR_ARCHITECTURE),x64)
ARCH := win32
endif
endif
ifeq ($(shell uname -s),Linux)
ARCH := linux
endif
endif
#
# Defaults for ARCH=linux
#
ifeq ($(ARCH),linux)
CC := gcc
CFLAGS := $(shell pkg-config --cflags gtk+-$(GTKVER))
LD := $(CC)
LDFLAGS := $(shell pkg-config --libs gtk+-$(GTKVER))
EXAMPLE_BIN := example
endif
#
# Defaults for ARCH=win64
#
ifeq ($(ARCH),win64)
CC := x86_64-w64-mingw32-gcc.exe
MINGWDIR := "C:/Program Files/mingw-w64"
GTKDIR := "$(MINGWDIR)/gtk+-3.6.4_win64"
CFLAGS := "-I$(GTKDIR)/include/gtk-3.0" \
"-I$(GTKDIR)/include/cairo" \
"-I$(GTKDIR)/include/pango-1.0" \
"-I$(GTKDIR)/include/atk-1.0" \
"-I$(GTKDIR)/include/cairo" \
"-I$(GTKDIR)/include/pixman-1" \
"-I$(GTKDIR)/include" \
"-I$(GTKDIR)/include/freetype2" \
"-I$(GTKDIR)/include" \
"-I$(GTKDIR)/include/libpng15" \
"-I$(GTKDIR)/include/gdk-pixbuf-2.0" \
"-I$(GTKDIR)/include/libpng15" \
"-I$(GTKDIR)/include/glib-2.0" \
"-I$(GTKDIR)/lib/glib-2.0/include"
LD := $(CC)
LDFLAGS := "-L$(MINGWDIR)/lib" \
"-L$(MINGWDIR)/x86_64-5.1.0-posix-seh-rt_v4-rev0/mingw64/opt/lib"
EXAMPLE_BIN := example.exe
endif
ifeq ($(ARCH),)
$(error ARCH unset.)
endif
#
# Recipes
#
.PHONY: all clean
all: $(OBJDIR)/$(EXAMPLE_BIN)
clean:
rm -rf $(OBJDIR)
$(OBJDIR):
mkdir $(OBJDIR)
$(OBJDIR)/%.o: $(SRCDIR)/%.c $(OBJDIR)
$(CC) $(CFLAGS) -c $< -o $@
$(OBJDIR)/$(EXAMPLE_BIN): $(addprefix $(OBJDIR)/, $(EXAMPLE_OBJS))
$(LD) $^ $(LDFLAGS) -o $@
but I definitely do not recommend the latter approach, unless the first one cannot be made to work.
In both cases the default target compiles the binary (although I personally prefer to use make clean all ). To override the architecture, use make ARCH=linux clean all for example.