make on gnu utils - print windows path - makefile

I am experimenting with makefiles and trying to create a simple cross platform makefile.
PROG = at
INCLUDES =
LIBPATH =
ifeq ($(PLATFORM), linux)
obj_ext = .o
CC = g++
endif
ifeq ($(PLATFORM), winnt)
obj_ext = .obj
exe_ext = .exe
CC = cl
INCLUDES = C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include
endif
printme:
echo PLATFORM $(PLATFORM)
echo Object extension $(obj_ext)
echo $(INCLUDES)
This is giving me the error:
>make printme
echo PLATFORM winnt
PLATFORM winnt
echo Object extension .obj
Object extension .obj
echo C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include
/usr/bin/sh: -c: line 0: syntax error near unexpected token `('
/usr/bin/sh: -c: line 0: `echo C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include'
make: *** [printme] Error 258
I don't understand the unexpected token `(' error. Anyone any ideas why?
My make is:
>make -version
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for i386-pc-mingw32

Here:
printme:
...
echo $(INCLUDES)
This calls echo with an unpredictable string as its argument. Many magic characters will make the shell behave in unexpected ways. Redirections, wildcards, and then there is (list) (in your case: (x86)) to execute a list of commands in a subshell.
printme:
...
echo '$(INCLUDES)'
This should be safe.

Related

Problem while using objcopy with "thin archive" file

Please use following shell commands to reproduce the problem:
# create subdirectory
mkdir subdir
# create source files with dummy functions
echo 'void func1(){}' > file1.c
echo 'void func2(){}' > ./subdir/file2.c
# compiling sources into object files
gcc -c file1.c -o file1.o
gcc -c ./subdir/file2.c -o ./subdir/file2.o
# creating "thin archive" file from object files
ar crT out.a file1.o ./subdir/file2.o
# running objcopy, which leads to an error
objcopy out.a out_copy.a
As a result, following error occurs:
objcopy:st0AENRL/subdir/file2.o: No such file or directory
P.S. Problem with objcopy occurs when "thin" archive is composed of object files from subdirectories.
Does anybody know if such objcopy's behavior is ok?
This is really a bug.
It was reported here.
Support of thin archives was temporary disabled.

.SUFFIXES refuses to work in Automake

I have the following construct in my Makefile.am, which I need to port for use in Automake.
.SUFFIXES: .o .c .cpp
Now I tried using 'automake -a --foreign' but that gives me the following error:
Makefile.am:73: error: use variable 'SUFFIXES', not target '.SUFFIXES'
If I change the Makefile.am to look like:
SUFFIXES: .o .c .cpp
Then automake runs successfully, but on running "make", I get:
cd . && /bin/bash ./config.status Makefile
config.status: creating Makefile
(CDPATH="${ZSH_VERSION+.}:" && cd . && )
/bin/bash: -c: line 0: syntax error near unexpected token `)'
/bin/bash: -c: line 0: `(CDPATH="${ZSH_VERSION+.}:" && cd . && )'
make: *** [config.h.in] Error 1
Any idea where I'm going wrong? Any help would be greatly appreciated, as there's not much to go about it online. Thanks :)
You're using incorrect syntax for SUFFIXES
SUFFIXES = .o .c .cpp
automake probably knows about those suffixes already, so without more context, it's hard to say if you really need SUFFIXES or not.

Debuild Error - Installing files in non-standard directory without getting errors

I'm creating a debian package for my libspellcheck library, and it has turned out to be quite a hassle. After a lot of work, I have been able to eliminate all but one fatal error:
make[1]: Entering directory `/home/iandun/Desktop/deb-build/libspellcheck-1.15'
mkdir /home/iandun/Desktop/deb-build/libspellcheck-1.15/debian/tmp/usr/etc/
mkdir: cannot create directory `/home/iandun/Desktop/deb-build/libspellcheck-1.15/debian/tmp/usr/etc/': No such file or directory
make[1]: *** [install] Error 1
make[1]: Leaving directory `/home/iandun/Desktop/deb-build/libspellcheck-1.15'
dh_auto_install: make -j1 install DESTDIR=/home/iandun/Desktop/deb-build/libspellcheck-1.15/debian/tmp returned exit code 2
make: *** [binary] Error 29
dpkg-buildpackage: error: fakeroot debian/rules binary gave error exit status 2
debuild: fatal error at line 1350:
dpkg-buildpackage -rfakeroot -D -us -uc failed
Here is my makefile:
# SPELLCHECK Makefile
# Copyright (C) 2013 Ian Duncan
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
all: libspellcheck spellcheck
spellcheck: meta.o spellcheck.o
g++ -m32 -o spellcheck spellcheck.o meta.o libspellcheck.a
libspellcheck: checker.o
ar -cvr libspellcheck.a checker.o
spellcheck.o: spellcheck.cpp
g++ -m32 -Wall -c spellcheck.cpp
meta.o: meta.cpp
g++ -m32 -Wall -c meta.cpp
checker.o: checker.cpp
g++ -m32 -Wall -c checker.cpp
clean:
rm -rf *o
install:
mkdir $(DESTDIR)/usr/etc/
cp libspellcheck.a $(DESTDIR)$(libdir)/libspellcheck.a
cp spellcheck.h $(DESTDIR)$(includedir)/spellcheck.h
cp spellcheck $(DESTDIR)$(bindir)/spellcheck
cp english.dict $(DESTDIR)/usr/etc/english.dict
chmod 777 $(DESTDIR)/usr/etc/english.dict
deinstall:
rm /usr/lib/libspellcheck.a
rm /usr/include/spellcheck.h
rm /usr/bin/spellcheck
rm /usr/etc/english.dict
rm /usr/local/man/man1/spellcheck.1.gz
Now, I can see from the error that its having trouble creating the /usr/etc directory in the $DESTDIR folder. However, if I remove $DESTDIR, it will create /usr/etc in the / directory, which is not where I want it. I do not want to have to relocate my dictionary file, because that would create a lot of problems with code consistency and such. There must be a way to do this.
Your mkdir command should have a -p parameter: mkdir -p $(DESTDIR)/usr/etc/

What would make a good portable clean target in a Makefile?

What is the appropriate form for a clean target for a portable Makefile? $(RM) does not work for me. I work both from the Windows (7) command prompt and within Eclipse. They both report the same version of make (I do have multiple on my path):
make --version
GNU Make 3.82
Built for i386-pc-mingw32
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Within Eclipse:
make clean
rm -f *.o testScaffolding_* runner.cpp runner.exe *.d
From cmd:
rm -f *.o testScaffolding_* runner.cpp runner.exe *.d
process_begin: CreateProcess(NULL, rm -f *.o testScaffolding_* runner.cpp runner.exe *.d, ...) failed.
make (e=2): The system cannot find the file specified.
make: *** [clean] Error 2
Both report $(OS) as Windows_NT and $(RM) as rm -f. I have which installed as well and if I call it within the Makefile, both environments report the same path.
This is the best I've come up with so far. You can specify UNAME as an environment variable or on the command line. If not specified it tries to run uname. If that fails it assumes Windows. Subsequently, you have a reasonable guess as to your shell environment and can define the corresponding commands appropriately.
Note that this has seen only limited testing and I merely consider it functional, not elegant or 'correct'. Also, the likes of an executable extension (.exe vs. nothing) is probably better identified by the use of $(OS).
ifeq ($(strip $(UNAME)),)
# if not already specified, try running uname
UNAME = $(shell uname)
endif
ifeq ($(strip $(UNAME)),)
# if still not specified, assume Windows
UNAME = Windows
endif
ifeq ($(UNAME),Windows)
define TO_WIN
$(subst /,\,$1)
endef
define MKDIR
-mkdir $(call TO_WIN,$1)
endef
define RM
del $(call TO_WIN,$1)
endef
CAT := type
else
define MKDIR
mkdir -p $1
endef
define RM
rm -f $1
endef
CAT := cat
endif

Copy a file using a makefile at runtime

I used to compile my programs with batch scripts on windows but I recently discovered makefiles which are much more efficient.
I had this line in my .bat file that copied some dlls to the current directory at runtime and it worked perfectly.
copy C:\lib\glfw\glfw.dll
I tried the same line in my makefile and even tried the alternative cp but my terminal prints this error even tho the file is IN the location I specified
process_begin: CreateProcess(NULL, copy C:\lib\glfw\glfw.dll, ...) failed
make (e=2): The system cannot find the file specified.
make: *** [core.exe] Error 2
Here is the full makefile that I am using. Mind you, absent the copy line it works like a charm.. what am I doing wrong or is this possible?
EXEC = core.exe
OBJS = src/obp.o
CC = g++
CFLAGS = -W -Wall
LIBS = -lSOIL -lglew32 -lglfw -lopengl32
LDFLAGS =
$(EXEC): $(OBJS)
$(CC) $(LDFLAGS) -o $# $(OBJS) $(LIBS)
copy C:\lib\glfw\glfw.dll
clean:
rm -f $(EXEC) $(OBJS) *~
It looks like you are running this from an MSYS (or MinGW) environment, which does not know about copy. Instead, you can use
cp C:\lib\glfw\glfw.dll .
If you want to avoid the *nix like cp, then you could use xcopy as follows:
xcopy //Y C:\lib\glfw\glfw.dll
Note the double // which is required to escape the /.
Or you could run this in a regular MS-DOS environment, in which case your clean target will not work because rm will not be found and you should use del.
With your current setup, any built-in DOS command will not be found. See Choosing the shell to read about how make determines which shell to use.
You may need to double the backslashes in order for make to understand what you want:
copy c:\\lib\\glfw\\glfw.dll
Make comes from a Unix background where the file separator is /, so it's sometimes a bit awkward to use it in a Windows environment.

Resources