Daily Archives: June 21, 2013

Adding Linux and command line building

Originally I wrote the projects here for Windows and OSX only. That was because I wanted to use Visual Studio and XCode IDEs and produce project files for them. Linux doesn’t really have an equivalent IDE, the standard way to build is via the command line using make. I didn’t like missing out building Linux, as it is part of the main 3 desktop OSes (Windows, OSX, and Linux). So I created a makefile that would work for Linux. It also worked for OSX as that has make.

I also decided I didn’t really like XCode’s IDE environment for building. It was rather tedious, and I was only using it to build, I use Visual Studio to edit the files. So I decided to scrap the XCode project files. I also didn’t like the way they were directories when viewing in Windows.

Now I had a convenient makefile for building in OSX and Linux, I decided I wanted to include Windows in that. Visual Studio comes with nmake, which is not very compatible with gnu make which Linux and OSX has. So I decided to ignore it and use make from Cygwin. Additionally this allowed me to easily compile using the Windows DDK libraries rather than the SDK ones with Visual Studio. I like to do this for the following reason: msvcrt.dll

Back with Visual Studio 6, when you compiled against the DLL version of the C Run-time library (CRT) it linked against msvcrt.dll. This is a DLL that has been shipped with almost every version of Windows, and still is in Windows 8. However after Visual Studio 6, Microsoft decided that you shouldn’t do this, and instead link to specific versions of the CRT that come with Visual Studio. The problem is these DLLs are not shipped standard with the Operating System. Microsoft says to distribute them with its “handy” tool. However I like single .exe programs that don’t depend on anything. For that reason I link with the static runtime library when using Visual Studio. That way it doesn’t not depend on a DLL, it does however increase the executable size. I also like small exe files.

Despite Microsoft saying you shouldn’t like to msvcrt.dll anymore, it turns out that they do for all their tools. The WinDDK (or WinWDK) libraries bind to msvcrt.dll for its usermode building. While WinDDK is used for Kerenl mode development, it also has a lot of usermode libraries. Personally I like to use the Visual Studio compiler, but with the WinDDK libraries, and falling back to the VS ones for the libraries that the DDK does not have.

This can be setup in the IDE using the include paths and library paths in the project files. However I want to keep those simple and standard. Not everyone is going to install the WinDDK. So I am leaving the project files using static linking with Visual studio libraries. However I extended the makefile to build using WinDDK libraries when building in Windows.

Seen I was using Cygwin for the make tool (and I always have cygwin installed), I thought I’d add the option of compiling using gcc in Cygwin, and producing Cygwin .exe files. These however are 32bit files as Cygwin is still only 32 bit. I also added to the make file the option to create 32bit Windows exe targeted for Windows XP. The x64 ones are targeted for Vista. When I release projects here in the future I will include x64 binaries for Windows, OSX, and now Linux. I won’t include either cygwin or x86 Windows, I just like to verify I can compile for them.

The following is my template makefile. This is fairly rough at this stage. For Windows it looks to see if the Visual Studio environment variables are set (which are set if you run the VS command prompt). Otherwise it uses Cygwin

INCLUDES = -I ./lib

all: Md5String Sha1String

Md5String: dir
	$(COMPILE) projects/Md5String/Md5String.c lib/LibMd5.c lib/LibSha1.c lib/LibSha256.c lib/LibSha512.c $(TAIL)

Sha1String: dir
	$(COMPILE) projects/Sha1String/Sha1String.c lib/LibSha1.c $(TAIL)

	@mkdir -p $(OUTDIR)

###### Setup build parameters #####
ifeq ($(OS),Windows_NT)
        ifeq ($(Platform),X64)
            PLATFORM = Windows
            PLATFORM = WindowsX86
        INTDIR = Build/$(PLATFORM)/$@
        COMPILE = @echo & echo ::::: Building $(PLATFORM) $@ & mkdir -p $(INTDIR) & cl $(INCLUDES) /nologo /Ox /Oi /Ot /GL /MD /W4 /WX /Fe$(OUTDIR)/$@ /D_CRT_SECURE_NO_WARNINGS /Fo$(INTDIR)/ 
    else ifneq (,$findstring /cygwin/,$(PATH))
        PLATFORM = Cygwin
        COMPILE = @echo ::::: Building $(PLATFORM) $@ & gcc $(INCLUDES) -O3 -Wall -Werror -o $(OUTDIR)/$@
        STRIP = @strip $(OUTDIR)/$@
        PLATFORM = None
        COMPILE = echo
        STRIP = 
        $(error Windows requires VS environment, or Cygwin)
    PLATFORM = $(shell uname)
    ifeq ($(PLATFORM),Darwin)
    else ifeq ($(PLATFORM),Linux)
        $(error Unsupported platform. Non Windows platform support: OSX and Linux)
    COMPILE = @echo ::::: Building $(PLATFORM) $@ & gcc $(INCLUDES) -O3 -Wall -Werror -pthread -o $(OUTDIR)/$@
    STRIP = @strip $(OUTDIR)/$@
    TAIL = -lm

In order to build Windows, you need to a command prompt that is setup correctly. I made a little batch file that calls the VS batch file for setting up environment variables, then sets the CL environment variable to include link path to WinDDK libraries. The batch file assume the default locations for Visual Studio 2010, and WinDDK 7.1

@echo off
call "c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" amd64
set CL=/link /LIBPATH:C:\WinDdk\7600.16385.1\lib\wlh\amd64 /LIBPATH:C:\WinDdk\7600.16385.1\lib\crt\amd64 /subsystem:console,6.0
cmd /k title Build Environment for Windows Vista x64

I moved the Visual Studio project files (.vcxproj and .vcxproj.filters) into a seperate directory called VsProjectFiles. This keeps the source directories completely free of extra files that aren’t .c or .h. The property files are also in there. When compiling with Visual Studio from the sln file it uses purely the Visual Studio libraries, and statically links against the CRT.