Reputation: 57678
I need to have a makefile
work under Windows and Cygwin. I having problems with the makefile detecting the OS correctly and setting appropriate variables.
The objective is to set variables for the following commands, then invoke the commands in rules using the variables:
rm
in Cygwin, del
in Windows.rmdir
(different
parameters in Cygwin and Windows)cp
in Cygwin, copy
in
Windows.test
in Cygwin, IF EXIST
in Windows.cat
in
Cygwin, type
in Windows.Here is my attempt, which always uses the else
clause:
OS_KIND = $(OSTYPE) #OSTYPE is an environment variable set by Cygwin.
ifeq ($(OS_KIND), cygwin)
ENV_OS = Cygwin
RM = rm -f
RMDIR = rmdir -r
CP = cp
REN = mv
IF_EXIST = test -a
IF_NOT_EXIST = ! test -a
LIST_FILE = cat
else
ENV_OS = Win_Cmd
RM = del -f -Q
RMDIR = rmdir /S /Q
IF_EXIST = if exist
IF_NOT_EXIST = if not exist
LIST_FILE = type
endif
I'm using the forward slash character, '/', as a directory separator. This is a problem with the Windows command, as it is interpreting it as program argument rather than a separator. Anybody know how to resolve this issue?
I am using make with Mingw in both Windows Console and Cygwin.
Upvotes: 2
Views: 4665
Reputation: 499
Accurately detecting the build platform is the tricky part. This is how I do it.
ifeq '$(findstring ;,$(PATH))' ';'
UNAME := Windows
else
UNAME := $(shell uname 2>/dev/null || echo Unknown)
UNAME := $(patsubst CYGWIN%,Cygwin,$(UNAME)) # CYGWIN_NT-10.0 -> Cygwin
endif
The UNAME variable is set to Linux, Cygwin, Windows, FreeBSD, NetBSD (or presumably Solaris, Darwin, OpenBSD, AIX, HP-UX), or Unknown. It can then be compared throughout the remainder of the Makefile to separate any OS-sensitive variables and commands.
I discuss this further in another thread
Upvotes: 0
Reputation: 42323
CMake, suggested by Matt B., is one of the right answers to this question. Other right answers are SCons, Jam, and Bakefile.
Since you're using Cygwin, Autoconf+Automake also gives you the tools to solve your problem. It's more of a toolkit for solving the problem than an out-of-the-box solution, though.
The overarching point is to move up a layer of abstraction so you can support lots of build systems from only a single source.
Upvotes: 1
Reputation: 31342
I highly recommend you move to CMake to automatically generate your Makefiles. These problems have all been solved, and it supports MingW, MSYS and Cygwin.
RM: file(REMOVE [file1 ...])
RMDIR: file(REMOVE_RECURSE [file1 ...]) # (not quite the same functionality; deletes files, too)
CP: file(COPY files... DESTINATION...)
REN: file(RENAME <oldname> <newname>)
IF_EXIST: if(EXISTS file-name)
IF_NOT_EXIST: if(NOT EXISTS file-name)
LIST_FILE: file(READ filename variable [LIMIT numBytes] [OFFSET offset] [HEX])
All your paths are automagically converted to DOS-style if you are generating MinGW Makefiles. It's a beautiful thing.
And, finally, it makes the rest of your Makefile stuff much simpler, too.
Upvotes: 3