Compiling open-zwave with MinGW


Open-zwave is a great project, it provides a software interface to z-wave networks. Z-wave is a popular home automation protocol.
With more and more devices coming I was interested in adding z-wave support to my own home automation software.
Being a python fanatic, I wanted to use open-zwave from within python. The first step in this process was getting open-zwave to compile with MingW, which I can then use to create a python wrapper later on (hint, some more posts coming soon 🙂 )
MinGW is a minimalist GNU implementation for Windows, and it’s widely used for several python modules.

MinGW also uses a make command, to built and maintain c/c++ programs. So the first step I had to take was to create a Makefile for MinGW.
This was actually quite easy, I took the Linux Makefile and modified it accordingly:

#
# Makefile for OpenZWave Linux build
# Greg Satz
# Modified for use with MinGW by Maarten Damen

# Requires libudev-dev

.SUFFIXES:	.d .cpp .o .a
.PHONY:	default clean

CC     := $(CROSS_COMPILE)gcc
CXX    := $(CROSS_COMPILE)g++
LD     := $(CROSS_COMPILE)g++
AR     := $(CROSS_COMPILE)ar rc
RANLIB := $(CROSS_COMPILE)ranlib

DEBUG_CFLAGS    := -Wall -Wno-format -g -DDEBUG -DLOG_STDERR
RELEASE_CFLAGS  := -Wall -Wno-unknown-pragmas -Wno-format -O3

DEBUG_LDFLAGS	:= -g

# Change for DEBUG or RELEASE
CFLAGS	:= -c $(DEBUG_CFLAGS)
LDFLAGS	:= $(DEBUG_LDFLAGS)

LIBDIR	:= ../../lib/windows-mingw32

INCLUDES	:= -I ../../src -I ../../src/command_classes/ -I ../../src/value_classes/ \
	-I ../../src/platform/ -I ../../src/platform/windows -I ../../tinyxml/ -I ../../hidapi/hidapi/
SOURCES		:= ../../src ../../src/command_classes ../../tinyxml ../../hidapi/windows \
	../../src/value_classes ../../src/platform ../../src/platform/windows

VPATH = ../../src:../../src/command_classes:../../tinyxml:../../hidapi/windows:\
	../../src/value_classes:../../src/platform:../../src/platform/windows

%.d : %.cpp
	@set -e; rm -f $@; \
	$(CXX) -MM $(INCLUDES) $< > $@.$$$$; \
	sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
	rm -f $@.$$$$

tinyxml := $(notdir $(wildcard ../../tinyxml/*.cpp))
hidapi := $(notdir $(wildcard ../../hidapi/linux/hid.c)) # we do not want the libusb version
cclasses := $(notdir $(wildcard ../../src/command_classes/*.cpp))
vclasses := $(notdir $(wildcard ../../src/value_classes/*.cpp))
pform := $(notdir $(wildcard ../../src/platform/*.cpp)) \
	$(notdir $(wildcard ../../src/platform/windows/*.cpp))
indep := $(notdir $(wildcard ../../src/*.cpp))

%.o : %.cpp
	$(CXX) $(CFLAGS) $(INCLUDES) -o $@ $<

%.o : %.c
	$(CC) $(CFLAGS) $(INCLUDES) -o $@ $<

default:	$(LIBDIR)/openzwave.a

clean:
	rm -f *.d *.o

-include $(tinyxml:.cpp=.d)
-include $(hidapi:.c=.d)
-include $(cclasses:.cpp=.d)
-include $(vclasses:.cpp=.d)
-include $(pform:.cpp=.d)
-include $(indep:.cpp=.d)

vers.c:
	echo 'char ozw_vers[] = "OpenZWave version 1.0.'`svnversion ../..`'";' > vers.c

vers.o:	vers.c

$(LIBDIR)/openzwave.a:	$(patsubst %.cpp,%.o,$(tinyxml)) \
			$(patsubst %.c,%.o,$(hidapi)) \
			$(patsubst %.cpp,%.o,$(cclasses)) \
			$(patsubst %.cpp,%.o,$(vclasses)) \
			$(patsubst %.cpp,%.o,$(pform)) \
			$(patsubst %.cpp,%.o,$(indep)) vers.o
	$(AR) $@ $?

For the sake of maintainability I created the following folders in the open-zwave folder structure:

– openzwave/cpp/build/windows-mingw32 <- for the custom Makefile - openzwave/cpp/lib/windows-mingw32 <- for the output library file After setting all of this up, I was ready to run the 'make' command. Uh oh, troubles:

This is caused because a non c++ standard function “sprintf_s” is used within some of open-zwave’s files.
Fortunately there is a similar standard c++ function called snprintf, the fix was easy (put this on top of the cpp/src/platform/windows/HidControllerImpl.cpp file):

#define sprintf_s snprintf

Will it build now? No, way..

This is again caused by use of non-standard functions: fprint_s and fopen_s. The fix is to put this in the head section of the cpp/src/platform/windows/LogImpl.cpp file:

#define sprintf_s snprintf

The fix for the fopen_s command is a bit trickier, I replaced it with the standard fopen command. Replace all parts in the LogImpl.cpp file where opening of files takes place:

FILE* pFile = NULL;
if( !fopen_s( &pFile, m_filename.c_str(), "a" ) )

Replace it with the fopen equivalent:

FILE* pFile = fopen( m_filename.c_str(), "a" );
if ( pFile != NULL )

Rerun the ‘make’ command and open-zwave should now compile correctly with MinGW! The output library is roughly 31MB.

Maarten

Hi, I am Maarten and I am the owner of this weblog. I post on various IT subjects that matter in my life as an IT professional.

Recent Posts