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.