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.