How to use makedepend in a non-standard makefile name - c++

I am trying to use makedepend in a makefile named Makefile_abc.
Normally when I have to build a target trg, I say
make -f Makefile_abc trg
and this works beautifully.
I have added following lines in this makefile.
dep:
makedepend main.c
Now, when I do,
make -f Makefile_abc dep
I get the error,
makedepend: error: [mM]akefile is not present
make: *** [depend] Error 1
If I rename my makefile as Makefile, then following command works fine,
make depend
So, I am looking for a way to use makedepend on non-standard makefile names.

This is a basic 'read the manual' question.
Looking at makedepend(1), you need -fMakefile_abc in the recipe for the target dep (optionally with a space between -f and Makefile_abc):
dep:
makedepend -fMakefile_abc main.c
To update the dependencies, you'd run:
$ make -f Makefile_abc dep
This would cause make to run:
makedepend -fMakefile_abc main.c
(Note that the 'standard' — most common — name for the target is depend rather than dep, so you'd normally run make -fMakefile_abc depend or, with a plain makefile file, make depend.)
If you're using GNU Make, you might also add another line to Makefile_abc:
.PHONY: dep # Or depend, depending…
This tells make that there won't be a file dep created by the rule.
You can often get information about how to run a command by using makedepend --help or makedepend -: — the first may (or may not) give a useful help message outlining options, and the second is very unlikely to be a valid option which should generate a 'usage' message that summarizes the options.

Related

I need some Makefile wizardry explained

So I was following one of the Makefile by example tutorials (cause I'm fairly fresh) and thats how I ended up here.
files = src/main.cpp src/compiler.cpp
all: $(files)
%.cpp:
echo $#
And this for some reason produces this
echo src/compiler.cpp
src/compiler.cpp
echo all.cpp
all.cpp
g++ -c -o all.o all.cpp
cc1plus: fatal error: all.cpp: No such file or directory
compilation terminated.
make: *** [<builtin>: all.o] Error 1
I don't see any refrences to g++ at all and for some reason it's getting called. The idea here was to use it to compile all my stuff from /src to .o files in /obj then produce a binary. Any ideas on how to do that or explanations on how to not call g++ without even referencing it in the makefile is highly appreciated.
It's being called because you have created a target all, and you haven't given make any recipe to build that target. So, make looks through its built-in rules and it sees that it knows how to build a program x given a prerequisite x.cpp. Well, make knows how to build a all.cpp, because you provided a rule that tells it how to build any .cpp file.
So first it runs the rule to build all.cpp, then it runs its built-in rule to build a target all from that all.cpp (which doesn't exist because your rule that told make how to build %.cpp doesn't actually create that target).
If you don't actually want to build a target all, then you should declare it to be a phony target:
.PHONY: all

Call gnumake on all subdirs in parallel (-j) and only then run the linker-rule last (i.e. order important)

I have a c++ makefile project. It works great for non-parallel building. It works 99% for parallel building... the only problem I have is that I can't get my final executable link-line to run last (it must be the last thing that happens).
I have some constraints: I don't want to have any PHONY dependencies on my link line because this causes it to re-link every time. I.e. once my target is built, when I re-build it should not be re-linked.
Here is (slightly contrived) minimal example. Please don't try to pick holes in it, its really here just to show the problem, its not real, but the problem I am showing is. You should be able to just run this and see the same issue that I am.
# Set the default goal to build.
.DEFAULT_GOAL = build
#pretend subdirs (these don't really exist but it does not matter so long as they always try to be built)
MAKE_SUB_DIRS = 1 2 3
#pretend shared objects that are created by the pretend makefile sub directories (above)
OUTPUTS = out1.so out2.so out3.so
# Top level build goal - depends on all of the subdir makes and the target.out
.PHONY: build
build: $(MAKE_SUB_DIRS) target.out
#echo build finished
# Takes 1 second to build each of these pretend sub make directories. PHONY so always runs
.PHONY: $(MAKE_SUB_DIRS)
$(MAKE_SUB_DIRS):
#if [ ! -f out$#.so ] ; then echo making $#... ; sleep 1 ; echo a > out$#.so ; fi
# The main target, pretending that it needs out1,2 and 3 to link
# Should only run when target.out does not exist
# No PHONY deps allowed here
target.out:
#echo linking $#...
#ls $(OUTPUTS) > /dev/null
#cat $(OUTPUTS) > target.out
# Clean for convinience
clean:
#rm -rf *.so target.out
Now, I don't really care about make working, what I want is make -j to work. Here is me trying to run it:
admin#osboxes:~/sandbox$ make clean
admin#osboxes:~/sandbox$
admin#osboxes:~/sandbox$ make -j - 1st attempt
making 1...
making 2...
linking target.out...
making 3...
ls: cannot access 'out1.so': No such file or directory
ls: cannot access 'out2.so': No such file or directory
ls: cannot access 'out3.so': No such file or directory
makefile:24: recipe for target 'target.out' failed
make: *** [target.out] Error 2
make: *** Waiting for unfinished jobs....
admin#osboxes:~/sandbox$
admin#osboxes:~/sandbox$ make -j - 2nd attempt
linking target.out...
build finished
admin#osboxes:~/sandbox$
admin#osboxes:~/sandbox$ make -j - 3rd attempt
build finished
admin#osboxes:~/sandbox$
So I highlighted my three attempts to run it.
Attempt 1: you can see all 4 dependencies of build are started at the same time (approx). Since each of the makeing x... take 1 second and the linking is nearly instant we see my error. However all the three "libraries" are build correctly.
Attempt 2: The libraries only get created if they don't already exists (that's bash code - pretending to do what a makefile might have done). In this case they are already created. So the Linking passes now since it just requires the libraries to exist.
Attempt 3: nothing happens because nothing needs to :)
So you can see all the steps are there, its simply a matter of ordering them. I would like the the make sub dirs 1, 2, 3 to build in any order in parallel and then only once they are all completed I want target.out to run (i.e. the linker).
I don't want to call it like this though: $(MAKE) target.out because in my real makefile I have lots of variables all setup...
I have tried looking at (from othe answers) .NOT_PARALLEL and using the dep order operator | (pipe), and I have tried order a load of rules to get target.out to be last.... but the -j option just ploughs through all of these and ruins my ordering :( ... there must be some simple way to do this?
EDIT: add an example of ways to pass variables to sub-makes. Optimized a bit by adding $(SUBDIRS) to the prerequisites of build instead of making them in its recipe.
I am not sure I fully understand your organization but one solution to deal with sub-directories is as follows. I assume, a bit like in your example, that building sub-directory foo produces foo.o in the top directory. I assume also that your top Makefile defines variables (VAR1, VAR2...) that you want to pass to the sub-makes when building your sub-directories.
VAR1 := some-value
VAR2 := some-other-value
...
SUBDIRS := foo bar baz
SUBOBJS := $(patsubst %,%.o,$(SUBDIRS))
.PHONY: build clean $(SUBDIRS)
build: $(SUBDIRS)
$(MAKE) top
$(SUBDIRS):
$(MAKE) -C $# VAR1=$(VAR1) VAR2=$(VAR2) ...
top: top.o $(SUBOBJS)
$(CXX) $(LDFLAGS) -o $# $^ $(LDLIBS)
top.o: top.cc
$(CXX) $(CXXFLAGS) -c $< -o $#
clean:
rm -f top top.o $(SUBOBJS)
for d in $(SUBDIRS); do $(MAKE) -C $$d clean; done
This is parallel safe and guarantees that the link will take place only after all sub-builds complete. Note that you can also export the variables you want to pass to sub-makes, instead of passing them on the command line:
VAR1 := some-value
VAR2 := some-other-value
...
export VAR1 VAR2 ...
Normally you would just add the lib files as prerequisites of target.out:
target.out: $(OUTPUTS)
#echo linking $#...
The thing is, this will relink target.out if any of the output lib files are newer. Normally this is what you want (if the lib has changed, you need to relink target), but you specifically say you do not.
GNU make provides an extension called "order only prerequisites", which you put after a |:
target.out: | $(OUTPUTS)
#echo linking $#...
now, target.out will only be relinked if it does not exist, but in that case, it will still wait until after $(OUTPUTS) have finished being built
If your $(OUTPUT) files are build by subsirectory makes, you may find you need a rule like:
.PHONY: $(OUTPUT)
$(OUTPUT):
$(MAKE) -C $$(dirname $#) $#
to invoke the recursive make, unless you have other rules that will invoke make in the subdirectories
Ok, so I have found "a" solution... but it goes a little bit against what I wanted and is therefore ugly (but not that that ugly):
The only way I can fathom to ensure order in parallel build (again from other answers I read) is like this:
rule: un ordered deps
rule:
#echo this will happen last
Here the three deps will be made (or maked?) in any order and then finally the echo line will be run.
However the thing that I want to do is a rule and specifically so, such that it checks if anything has changed or if the file does not exist - and then, and only then, runs the rule.
The only way I know of to run a rule from within the bode of another rule is to recursively call make on it. However I get the following issues just calling make recursively on the same makefile:
Variables are not passed in by default
Many of the same rules will be re-defined (not allowed or wanted)
So I came up with this:
makefile:
# Set the default goal to build.
.DEFAULT_GOAL = build
#pretend subdirs (these don't really exist but it does not matter so long as they always try to be built)
MAKE_SUB_DIRS = 1 2 3
#pretend shared objects that are created by the pretend makefile sub directories (above)
OUTPUTS = out1.so out2.so out3.so
# Top level build goal - depends on all of the subdir makes and the target.out
export OUTPUTS
.PHONY: build
build: $(MAKE_SUB_DIRS)
#$(MAKE) -f link.mk target.out --no-print-directory
#echo build finished
# Takes 1 second to build each of these pretend sub make directories. PHONY so always runs
.PHONY: $(MAKE_SUB_DIRS)
$(MAKE_SUB_DIRS):
#if [ ! -f out$#.so ] ; then echo making $#... ; sleep 1 ; echo a > out$#.so ; fi
# Clean for convinience
clean:
#rm -rf *.so target.out
link.mk:
# The main target, pretending that it needs out1,2 and 3 to link
# Should only run when target.out does not exist
# No PHONY deps allowed here
target.out:
#echo linking $#...
#ls $(OUTPUTS) > /dev/null
#cat $(OUTPUTS) > target.out
So here I put the linker rule into a separate makefile called link.mk, this avoids recursive make calling on the same file (and therefore with re-defined rules). But I have to export all the variables I need to pass through... which is ugly and adds a bit of a maintenance overhead if those variables change.
... but... it works :)
I will not mark this any time soon, because I am hopeful some genius will point out a neater/better way to do this...

GNU Make Exits Due to Syntax Error in If Statement

I'm building a C++ project using GNU Make (version 3.80). The makefile is auto-generated from the tool I'm using (IBM Rational Rhapsody). An example of this makefile is at the end of this post.
This makefile has a mechanism that allows me to specify a directory for object files (the OBJ_DIR variable). If this is set, the variable CREATE_OBJ_DIR is set up with the command if not exist $(OBJ_DIR) mkdir $(OBJ_DIR). This is then called for each object file in the project.
Running this makefile without setting an object file directory works as expected; the code is compiled without issues. But running it with OBJ_DIR set to 'build' causes the following error:
C:\Users\XXX\AppData\Local\Temp\make52963.sh: C:\Users\XXX\AppData\Local\Temp\make52963.sh: line 2: syntax error: unexpected end of file
C:\Tools\XXX\x86-win32\bin\make.exe: *** [build/Example.o] Error 2
I'm certain the issue is within the rule for '/build/Example.o', when $(CREATE_OBJ_DIR) is called. If I manually edit the rule and replace $(CREATE_OBJ_DIR) with mkdir $(OBJ_DIR), the command is executed correctly. If I then replace it with if not exist build mkdir build directly, to eliminate any issues due to variable expansion, the same error appears.
Other things I have tried:
Run a cmd shell with the same environment variables set as when the makefile is called, and attempted to run the if not exist build mkdir build command. No issues with this.
Ensure that no trailing characters are present in the command run within the makefile. None appear to be present.
My only conclusion at this point is that something about if statements causes the makefile to fail, but I'm not sure what. Is there anything else I should try to track down the source of this problem? Am I missing something obvious.
Let me know if more details are required.
Note: I've edited this makefile pretty heavily, so it's just to give an idea of what I'm using, and probably won't execute. Some of the environment variables below are set up in a batch file prior to calling make, but I'm confident they're not part of the issue I'm seeing, as the makefile works correctly except in the situation described above.
CPU = XXX
TOOL = gnu
INCLUDE_QUALIFIER=-I
LIB_CMD=$(AR)
LINK_CMD=$(LD)
CPP_EXT=.cpp
H_EXT=.h
OBJ_EXT=.o
EXE_EXT=.out
LIB_EXT=.a
TARGET_NAME=Example
all : $(TARGET_NAME)$(EXE_EXT) Example.mak
TARGET_MAIN=Example
LIBS=
INCLUDE_PATH=
ADDITIONAL_OBJS=
OBJS= \
build/Example.o \
OBJ_DIR=build
ifeq ($(OBJ_DIR),)
CREATE_OBJ_DIR=
else
CREATE_OBJ_DIR= if not exist $(OBJ_DIR) mkdir $(OBJ_DIR)
endif
build/Example.o : src/Example.cpp
#echo Compiling src/Example.cpp
$(CREATE_OBJ_DIR)
#$(CXX) $(C++FLAGS) -o build/Example.o src/Example.cpp
You are thinking to complex. A far simpler solution here is to use:
mkdir -p $(OBJ_DIR)
This will also make it work if OBJ_DIR=my/little/obj/dir/deep/down/the/rabit/hole.
Look at the following Makefile:
OBJ_DIR=foo
CREATE_OBJ_DIR= if not exist $(OBJ_DIR) mkdir $(OBJ_DIR)
$(info CREATE_OBJ_DIR=$(CREATE_OBJ_DIR))
all:
$(CREATE_OBJ_DIR)
and it's output:
% make
CREATE_OBJ_DIR=if not exist foo mkdir foo
if not exist foo mkdir foo
/bin/sh: 1: Syntax error: end of file unexpected (expecting "then")
Makefile:8: recipe for target 'all' failed
make: *** [all] Error 2
Your "if" statement is simply not valid shell syntax. On the other hand if OBJ_DIR is empty then CREATE_OBJ_DIR is empty and that is valid.

make not executing correct Makefile

I should preface this by saying I am very new to Makefiles.
I created the following Makefile:
all: tiling_graph.o
g++ -o tiling_graph tiling_graph.o -L/usr/local/lib -ligraph
I am trying to make sure that -ligraph is included. However, when I type "make", I get the following output: "c++ -c -o tiling_graph.o tiling_graph.cpp"
Why is it not using the Makefile that I created in the current directory? I have tried using "make -f Makefile" and "make --file=Makefile" but none of these are working.
Also, right after I first made the Makefile, it worked correctly. The output after typing make was
"g++ -o tiling_graph tiling_graph.o -L/usr/local/lib -ligraph"
I executed ./tiling_graph and it was successful.
Then I edited tiling_graph.cpp, ran make again, and the output was "c++ -c -o tiling_graph.o tiling_graph.cpp" and has been ever since.
I would really appreciate any help. Thanks!
A simple way to think about a make rule:
target: dependency list
commands to make the target
is that it is a recipe for making the file called target from the list of files in the dependency list. Since make can see the file system, it can tell whether any file in the dependency list is newer than the file named target, which is its signal for recreating target. After all, if none of the dependencies have changed, the target must be up-to-date.
Note that make knows quite a lot about how to build files. In particular, it has a lot of built-in "pattern" rules, so it knows, for example, how to make an object file (prog.o) from a C++ source file (prog.cpp) or from a C source file (prog.c) or many other things. So you only need to actually write a makefile when you have other requirements, like a library (and even then you could just add that to an environment variable, but the makefile is better).
Now, you don't actually want to build a file called all. You want to build a file called tiling_graph. So the correct make rule would be:
tiling_graph: tiling_graph.o
g++ -o tiling_graph tiling_graph.o -L/usr/local/lib -ligraph
Since make already knows how to create tiling_graph.o, it can actually figure out how to make tiling_graph from tiling_graph.cpp.
So where does this all come from? The usual way to use all is:
all: program1 program2 program3
which tells make that the all target requires program1, program2 and program3. So if you need to build all three of those programs, the all rule would let you just do one make command. Since there is no file named all, that's a "phony" target and (with gnu make, at least) it should be declared as a phony target:
all: tiling_graph
.PHONY: all
But you really don't need that if you just want to build one program.
When you just type make (as opposed to make target), make chooses the first target in the makefile. So if you put the thing you usually want to build first, you'll save some typing.

Make uses old Makefile

I'm using make to build a C++ project. During the course of the project, I wanted to make some changes to the Makefile. Unfortunately, ever since I executed make once, it keeps using that particular version of the Makefile and just doesn't do anything with the changes at all.
I have run make clean, I have renamed the makefile, I've searched for other Makefiles which might be used instead, all to no avail. There is no mention of any caching mechanism in the man pages for make, nor anywhere on Google.
Does anyone have any idea why make isn't using the new version and what I can do about it? I'm compiling on a Ubuntu 12.04.2 LTS (x86_64) box, with (GNU) make version 3.81.
Update:
Some additional information. It seems make is using the current version of the makefile after all. If I change something in the main target, it's working just fine. But if I change something in the obj/%.o target, it just keeps running the same command, no matter what changes I make to that target.
Full Makefile an be found here: http://pastebin.com/WK43NRcL
CC_FILES = $(shell find -name "*.cc" -exec echo "{}" +;)
That find command is incorrect, shouldn't it be looking in the src directory? And why use echo to print the name when that's what find does anyway?
That means your list of CC_FILES and so also list of OBJ_FILES is empty.
I think you want:
CC_FILES := $(shell find src -name "*.cc")
Note that this uses := not = because otherwise the shell function gets run every time you reference the CC_FILES variable. Using := means it is run and evaluated only once.
However, since it seems all your .cc files are in the same directory you don't need a recursive find, just do:
CC_FILES := $(wildcard src/*.cc)
As you've realised, your patsubst is broken, you can just do:
OBJ_FILES := $(patsubst src/%.cc,obj/%.o,$(CC_FILES))
(Again, use := here)
Also:
obj/%.o: obj src/%.cc
$(CXX) $(CFLAGS) -c -o $# $<
I think you need to read what the $< variable expands to, because the rule above isn't going to do what you expect.
This makefile is full of errors, you need to use echo in pattern rules to print out the values of variables, so you can verify they have the values you expect. (As another option for debugging, set SHELL=bash -x so every shell command is echoed)
make does not somehow magically keep track of your old makefile; it will use whatever file is first in the list of files it looks for, in the current directory.
To find out which Makefile is actually used, see this question: Getting the name of the makefile from the makefile
Since you're using GNU make, check its excellent manual on what filenames it looks for, and in which order.