Use Cygwin to install your favorite unix userland tools under Microsoft Windows.

Be sure to include the following packages:

  • make
  • gdb
  • mingw64-i686-binutils
  • mingw64-i686-gcc-core
  • mingw64-i686-gcc-g++
  • mingw64-i686-headers
  • mingw64-i686-runtime
  • mingw64-i686-runtime-debuginfo
  • w32api-headers
  • w32api-runtime
  • w32api-headers-debuginfo

Building Under Linux (Debian / Ubuntu)

To build under Debian-based distributions like Ubuntu or Mint, install the following:

NOTE: I’m typically writing 32-bit windows applications. If you’re targeting x86_64, use wine64 instead, replace occurrences of i686 with x86-64 (but leave the -w64 suffixes!), and skip the dpkg --add-architecture line.

# ADD i386 FOR wine32
dpkg --add-architecture i386 

# UPDATE PACKAGE LIST
sudo apt-get update

# 32-bit WINE FOR TESTING
sudo apt-get install wine32 

# MINGW FOR WINDOWS LIBS, HEADERS, & BUILD TOOLS
sudo apt-get install mingw-w64 mingw-w64-common mingw-w64-i686-dev mingw-w64-tools 

# gcc AND g++ FOR COMPILING
sudo apt-get install g++-mingw-w64 gcc-mingw-w64

# make AND gdb FOR BUILDING AND DEBUGGING
sudo apt-get install make gdb-mingw-w64 gdb-mingw-w64-target

Project Layout

/+
 +-lib/           < any external libraries to include
 +-obj/           < intermediate binaries
 +-res/           < windows resources, .rc files
 +-src/           < .c, .cpp, .h files
 |-Makefile       < The following Makefile

Makefile

# This Makefile will build the MinGW Win32 application.
CC = i686-w64-mingw32-g++

ifneq (, $(shell which i686-w64-mingw32-windres))
   RC = i686-w64-mingw32-windres
else ifneq (, $(shell which windres))
   RC = windres
else
   $(error "NEITHER windres NOR i686-w64-mingw32-windres FOUND IN SYSTEM PATH")
endif

# https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
# http://www.transmissionzero.co.uk/computing/win32-apps-with-mingw/
# http://win-builds.org/doku.php

#       GUI Application: -Wl,--subsystem,windows
# Win32 Common Controls: -lcomctl32

# -lMyLib2 -Wl,-Bstatic -lMyLib1 -Wl,-Bdynamic

APPNAME     = "my-app.exe"

RESOURCE_SRC = $(wildcard res/*)
RESOURCE_OBJ = obj/resource.o
CFILE_SRC    = $(wildcard src/*.c)
CFILE_HDR    = $(wildcard src/*.h)
CFILE_OBJ    = $(addprefix obj/, $(notdir $(CFILE_SRC:.c=.o)))

# $@: the target filename.
# $*: the target filename without the file extension.
# $<: the first prerequisite filename.
# $^: the filenames of all the prerequisites, separated by spaces, discard duplicates.
# $+: similar to $^, but includes duplicates.
# $?: the names of all prerequisites that are newer than the target, separated by spaces.

CHARSET = UNICODE
BUILD   = DEBUG

# LINK OPTIONS
LDFLAGS      = -Wl,--subsystem,windows -lcomctl32 -mwin32 -mwindows -static-libgcc

# COMPILER OPTIONS
CFLAGS       = -Ires -Wall -ansi -mthreads -mwin32 -mwindows -D_WIN32_WINNT=0x501
#-D__USE_MINGW_ANSI_STDIO=1

ifeq (${BUILD}, DEBUG)
   CFLAGS  += -g -O0
else
   CFLAGS  += -O3
   LDFLAGS += -s
endif

# Compile UNICODE version (NOTE: WINDOWS WIDE-CHARS, NOT UTF-8)
ifeq (${CHARSET}, UNICODE)
   CFLAGS  += -Wl,-municode -DUNICODE -D_UNICODE
   LDFLAGS += -municode
endif

all: ${APPNAME}

${APPNAME}: ${CFILE_OBJ} ${RESOURCE_OBJ}
   ${CC} -o $@ $^ ${LDFLAGS}

obj/%.o: src/%.c ${CFILE_HDR}
   ${CC} ${CFLAGS} -c $< -o $@

${RESOURCE_OBJ}: ${RESOURCE_SRC}
   ${RC} --include-dir="./res" --target=pe-i386 res/resource.rc $@

clean:
   rm -f obj/*.o
   rm -f ${APPNAME}

debug:
   @echo "RESOURCES:" ${RESOURCE_SRC}
   @echo "   WNDRES:" ${RC}
   @echo "  SOURCES:" ${CFILE_SRC}
   @echo "  HEADERS:" ${CFILE_HDR}
   @echo "      OBJ:" ${CFILE_OBJ} ${RESOURCE_OBJ}
   @echo "   CFLAGS:" ${CFLAGS}
   @echo "  LDFLAGS:" ${LDFLAGS}

Miscellaneous Notes

  • If you get a missing header error, try all lowercase. Unix is case-sensitive, Windows isn’t.
  • Headers are in /usr/share/mingw-w64/include/
  • Library link objects are in /usr/i686-w64-mingw32/lib/
  • I am no Makefile wizard, so there is probably room for improvement here.
  • You can run the app from the Linux shell with wine32 ./my-app.exe.
  • You can also run it from the Wine shell with wine32 cmd then typing the app name from there.

← Older Newer →

Leave a Reply

You must be logged in to post a comment.