Reuse makefile rule - makefile

I'm learning makefiles and I'm trying to figure out how to reuse a rule. Right now I have the following:
CPP = cl
CPPFLAGS = /Od /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Gm /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc90.pdb" /W3 /nologo /c /ZI /TP /errorReport:prompt
.SUFFIXES: .exe .cpp
Exercise35.exe:
$(CPP) Exercise35.cpp $(CPPFLAGS)
debug:
$(CPP) Exercise35.cpp $(CPPFLAGS) /D "_DEBUG"
It seems bad that the debug rule essentially repeats the Exercise35 rule with an extra command-line parameter. Is there a better way?

Recursive make, and append your debugging flag to CPPFLAGS.
debug:
$(MAKE) CPPFLAGS="$(CPPFLAGS) /D _DBEBUG" Exercise35.exe

You should check out the following properties of the make and look at the sample below:
$# - means the name of the current target file, in this case it corresponds to the value of APP.
$< - means a single file that is newer than the target on which the target is dependant.
$? - means a list of files newer than the current target on which the target is dependant.
.SUFFIXES: .cpp.exe
CPP = cl
EXTRAFLAGS =
CPPFLAGS = /Od /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Gm /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc90.pdb" /W3 /nologo /ZI /TP /errorReport:prompt
FILES = Exercise35
APP = Exercise35.exe
.cpp.exe:
$(CPP) $(EXTRAFLAGS) $(CPPFLAGS) /c $<
all : $(APP)
$(APP) : $(FILES)
$(CPP) $(EXTRAFLAGS) $(CPPFLAGS) $# $(FILES)
clobber : clean mrproper
clean:
del $(FILES)
mrproper:
del $(APP)
I got this from my old makefile template, notice that the make will appear 'intelligent' and flexible as you can override the flag specifically for debugging/release within the one make file by executing like this
make EXTRAFLAGS="/D _DDEBUG"
This will pass in the extra define into the makefile to include the _DDEBUG macro, if you wish to build a release, leave out the EXTRAFLAGS on the command line.
Edit:
As per Mike's point-out, I thought it would be useful to include the extra rules so that you can clean the directory with exe's and object code lying around...This was my original template makefile from AIX (which I've used under Linux also...) Thanks Mike for the heads up!
Hope this helps,
Best regards,
Tom.

G'day,
I'd be more inclined to make the debug option a macro within the Makefile.
CPP = cl
CPPFLAGS = /Od /D "WIN32" /D "_CONSOLE" /D \
"_UNICODE" /D "UNICODE" /Gm /EHsc /RTC1 \
/MDd /Fo"Debug\\" /Fd"Debug\vc90.pdb" /W3 \
/nologo /c /ZI /TP /errorReport:prompt
#DEBUG = /D "_DEBUG"
DEBUG =
.SUFFIXES: .exe .cpp
Exercise35.exe:
${CPP} Exercise35.cpp ${CPPFLAGS} ${DEBUG}
and then comment out the version of the DEBUG macro that you don't want to use.
BTW It's better to refer to Makefile macros using ${} rather than $() as round brackets are used for object substitution into archives and curly brackets aren't.
Edit: If you're learning make and makefiles then I'd highly recommend having a read of the first few chapters of "Managing Projects with GNU Make". It'll help you get your head around some non-intuitive aspects of the behaviour of make, esp. it's backwards-chaining behaviour.
If you can find a copy of the small first edition which isn't so gmake specific then even better. It's explanation is much better IMHO.
Edit 2: Here's a link to the Amazon site for the first edition of the book simply called "Managing Projects with Make". As I said above, great description of why make behaves as it does.
HTH
cheers,

Related

How do I specify additional directories for a linker in a cl compiler

I use the cl /EHsc fileName.cpp command in powershell to compile cpp files, and the thing is I cannot find on the web how to specify the paths to additional dependencies for a linker to know where to look for lib files. Same goes with headers
It's right there in the documentation.
cl /I c:\myheaders /I ..\onemore mycode.c /link /LIBPATH:.\foo /LIBPATH:c:\bar

How to use arm-none-eabi with multiple files?

I'm trying to make a modified version of the FlySky FS-i6 firmware. After a bit of searching, I found someone who decompiled the source code here.
I'm trying to compile using arm-none-eabi, which I already have installed from the Arduino IDE.
Here's a batch file I made to compile the files, which are just a bunch of .c and .h files under several directories, but I have no clue what arguments I'm supposed to be giving the arm-none-eabi-gcc command...
#echo off
set EABI_PATH="%LocalAppData%\Arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1\bin"
#RD /S /Q temp
mkdir temp
for /D %%d in (*) do (
echo ---- Compiling Directory: %%d
rem C Files:
for %%f in (%%d/*.c) do (
"%EABI_PATH%/arm-none-eabi-gcc" -c -mcpu=cortex-m0plus -g "%%d/%%f" -o "temp/%%~nf.o" -mthumb -g3
)
rem Header Files:
rem for %%f in (%%d/*.h) do (
rem "%EABI_PATH%/arm-none-eabi-gcc" -c -mcpu=cortex-m0plus -g "%%d/%%f" -o "temp/%%~nf.o" -mthumb -g3
rem )
)
I've searched everywhere, but I can't find any tutorials or anything about how to use the tool. All I want to do is compile the files to a firmware.hex file, you'd think it would just be a simple one-liner...

Makefile no longer works (Windows)

I created this makefile almost two years ago in Windows 7:
SRC_DIRS = ./src/oasis ./src/oasis/commands/basic ./src/oasis/commands/immortal ./src/oasis/commands/socials ./src/oasis/util
COMPILE_FLAGS = -d ./classes
DOC_FLAGS = -quiet -private -d ./doc -sourcepath ./src -subpackages oasis -linkoffline http://java.sun.com/j2se/1.4.2/docs/api .
all:
#echo Compiling source code...
#javac $(COMPILE_FLAGS) $(foreach dir,$(SRC_DIRS),$(dir)/*.java)
#echo Creating javadocs...
#javadoc $(DOC_FLAGS)
#echo Done.
class:
#echo Compiling source code...
#javac $(COMPILE_FLAGS) $(foreach dir,$(SRC_DIRS),$(dir)/*.java)
#echo Done.
docs:
#echo Creating javadocs...
#javadoc $(DOC_FLAGS)
#echo Done.
clean:
#echo Removing classes...
#rmdir classes /q /s
#mkdir classes
#echo Removing javadocs...
#rmdir doc /q /s
#mkdir doc
#echo Done.
I used to navigate to its folder with cmd.exe, and then type "make all" or "make class" or whatever... and it would work! Now I'm returning to this project almost 2 years later, on a new computer (also Windows 7) and the "make" command isn't recognized. I don't remember installing any special software to use makefiles in Windows. Why won't it work anymore?

print.c is missing from lua 5.2, trying to build from source

I am trying to build Lua from source and when I look at http://www.lua.org/source/5.2/ I basically see what I got in the source file, and I don't see print.c.
In my build.bat (I am doing this on Windows 7) I have this:
cl /MD /O2 /W3 /c /DLUA_BUILD_AS_DLL *.c
del *.o
ren lua.obj lua.o
ren luac.obj luac.o
ren print.obj print.o
link /DLL /IMPLIB:lua5.2.lib /OUT:lua5.2.dll *.obj
link /OUT:lua.exe lua.o lua5.2.lib
lib /out:lua5.2-static.lib *.obj
link /OUT:luac.exe luac.o print.o lua5.2-static.lib
If I just remove all references to print.o will there be a problem with what I compile when I try to embed this in my game?
In lua 5.1, under compiler you will see print.c, so I wonder if I should not do 5.2.
http://www.lua.org/source/5.1/
UPDATE
So, what I did was change my build.bat and removed the print.obj, but I think the rename was useful in order to not include lua.obj and luac.obj in the .lib file, so I rename them and then rename them back.
cl /MD /O2 /W3 /c /DLUA_BUILD_AS_DLL *.c
del *.o
ren lua.obj lua.o
ren luac.obj luac.o
link /DLL /IMPLIB:lua5.2.lib /OUT:lua5.2.dll *.obj
link /OUT:lua.exe lua.o lua5.2.lib
lib /out:lua5.2-static.lib *.obj
ren lua.o lua.obj
ren luac.o luac.obj
link /OUT:luac.exe luac.obj lua5.2-static.lib
You don't need print.c in Lua 5.2, the only public function it defined is moved to luac.c. See PrintFunction() now found in luac.c.
Also, it is not a good idea to rename .obj to .o in Windows. Use whatever object file name is preferred by your tool chain.
Edit: I now see the purpose of the renaming, and while it does work, I still think it is a bad practice.
The trick is that the CL command in your batch file is compiling every .c file in your current directory with identical options. As it happens, that isn't a problem, but it isn't a conventional way of doing this sort of thing.
Then, because a few of those files aren't actually part of the DLL you want to build, you rename those so that you can fit the rest on the LINK command line as a single wild card *.obj.
If you are going to use a batch file to build Lua yourself, then it would be better to list the .obj files that make up the DLL and each application on each relevant link line rather than depend on a wild card. As it is, if you had a build error in the CL command, you still build a DLL with all the rest of the objects, or worse, possibly with an out of date object for the file that didn't compile.
Then you might or might not successfully link lua.exe and luac.exe even though there were errors.
The right answer here is to use a build tool of some form to compile and link. Microsoft should have provided you NMake, it might have provided you their internal tool (used to drive builds of the Windows kernel and device drivers, I know it comes with the DDK tools but I think it is also in the Platform SDK and may be buried in VS) named BUILD, and there is always the option of adding a more broadly used build system such as GNU Make, CMAKE, or countless others.
If you insist on using the renaming trick because it is more expedient than learning to do it the right way right now, then please at least add some testing for the successful completion of each compile and link step with IF ERRORLEVEL 1 GOTO :EOF commands to end the batch file after a failure, as shown below.
As I edited the batch file, I notice another potential issue. You built all the OBJ files with /DLUA_BUILD_AS_DLL, but then make a static library and link luac.exe from it. I don't know offhand what features of the source text are modified by that definition, but it probably isn't wise to make a static library from OBJ files compiled with it instead of a DLL.
cl /MD /O2 /W3 /c /DLUA_BUILD_AS_DLL *.c
if ERRORLEVEL 1 goto :EOF
del *.o
ren lua.obj lua.o
ren luac.obj luac.o
link /DLL /IMPLIB:lua5.2.lib /OUT:lua5.2.dll *.obj
if ERRORLEVEL 1 goto :EOF
link /OUT:lua.exe lua.o lua5.2.lib
if ERRORLEVEL 1 goto :EOF
cl /MD /O2 /W3 /c *.c
if ERRORLEVEL 1 goto :EOF
del *.o
ren lua.obj lua.o
ren luac.obj luac.o
lib /out:lua5.2-static.lib *.obj
if ERRORLEVEL 1 goto :EOF
ren lua.o lua.obj
ren luac.o luac.obj
link /OUT:luac.exe luac.obj lua5.2-static.lib
if ERRORLEVEL 1 goto :EOF

MakeFile Set Variable at Runtime

I have a makefile as follows.. At the first line that says windows.. Then on that same line, I try to set the variable to windows and jmp to $(WinDIR)/$(WinOUT)
How can I do that?
windows: ObjDIR=Windows $(WinDIR)/$(WinOUT)
#echo
#echo "Finished Making windows.."
clean:
#echo " Cleaning Build Files."
#rm -rf $(BinDIR) $(ObjDIR)
$(WinDIR)/$(WinOUT): $(ObjFiles)
#echo
#echo "Linking Object Files.."
Um...
windows: ObjDIR=Windows
windows: $(WinDIR)/$(WinOUT)
#echo
#echo "Finished Making windows.."
But I'm not sure you understand how Make works. It won't "jump to" $(WinDIR)/$(WinOUT), it will -- perhaps -- execute the $(WinDIR)/$(WinOUT) rule first.

Resources