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.
Related
I want to use an awk script to figure out the which modules have to be compiled before I can compile a FORTRAN source file. My project is structured in a way that I can obtain the filenames that provide the modules by running
awk '$1=/use/{print gensub(",","","g", $2) ".o"}' file.f90
on the file I want to compile.
However, my make command
%.o: $(shell awk '$$1=/use/{print gensub(",","","g", $$2) ".o"}' /path/to/%.f90)
fails with
awk: fatal: cannot open file `/path/to/%.f90' for reading: No such file or directory
So %.f90 does not get expanded. Why is that the case and how can I solve that issue?
Variables and functions in targets and prerequisites are expanded when the makefile is parsed, not when make is running the makefile. But, pattern rules are only expanded when make is running the makefile, trying to build a target that matches the pattern. So at the time these variables and functions are expanded, you only have the literal pattern string not its expansion into a real filename.
See How make reads a makefile in the docs.
There are a number of ways to do this. One option is using secondary expansion. However note you'll have to double-escape the $ you are escaping!!
.SECONDEXPANSION:
%.o: $$(shell awk '$$$$1=/use/{print gensub(",","","g", $$$$2) ".o"}' /path/to/$$*.f90)
ETA
You could alternatively not use .SECONDEXPANSION at all and instead use eval like this:
%.o:
...
SRCS := $(wildcard *.f90)
OBJS := $(SRCS:%.f90=%.o)
$(foreach O,$(OBJS),\
$(eval $O: $(shell awk '$$1=/use/{print gensub(",","","g", $$2) ".o"}' $(O:%.o=%.f90))))
Since you didn't give an actual example I just made up SRCS and OBJS variables. Maybe you have similar variables already.
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.
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.
I'm new to makefile, and I'm writing a simple C++ shared library.
Is there a way of finding a library's path dynamically by the makefile itself? What I want is something like this: (in my makefile)
INCLUDE_DIRS := `which amplex-gui`
LIBRARY_DIRS := `which amplex-gui`
amplex-gui is a library I use in my code, and I need to put its lib and include directories in my makefile. I want to figure out its path dynamically because each user might install it in a different path on their machine. Therefore, I need my makefile to dynamically parse the which command (or perhaps the $PATH environment variable) to find that path. How can I go about doing this?
Remember that backquoting is shell syntax. Make doesn't do anything special with backquotes. If you're using GNU make, you can use $(shell which amplex-gui) to get equivalent behavior as backquotes.
Regarding your comment above, I'm not sure exactly what you mean by "nest commands", but you can definitely use the shell's $() syntax within a make shell function. However, as with all strings that make expands, you need to double the dollar signs to quote them so that they are passed to the shell. So for example:
INCLUDE_DIRS := $(shell echo $$(dirname $$(dirname $$(which amplex-gui))))
Of course you can also use make functions; unfortunately the make dir function is annoying in that it leaves the final slash, so it cannot be used multiple times directly. You have to put a patsubst in there, like:
INCLUDE_DIRS := $(dir $(patsubst %/,%,$(dir $(shell which amplex-gui))))
Finally, if you have a sufficiently new version of GNU make there's the abspath function, so you could do something like this:
INCLUDE_DIRS := $(abspath $(dir $(shell which amplex-gui))../..)
How can I make GNU Make use a different compiler without manually editing the makefile?
You should be able to do something like this:
make CC=my_compiler
This is assuming whoever wrote the Makefile used the variable CC.
You can set the environment variables CC and CXX, which are used for compiling C and C++ files respectively. By default they use the values cc and g++
If the makefile is written like most makefiles, then it uses $(CC) when it wishes to invoke the C compiler. That's what the built-in rules do, anyway. If you specify a different value for that variable, then Make will use that instead. You can provide a new value on the command line:
make CC=/usr/bin/special-cc
You can also specify that when you run configure:
./configure CC=/usr/bin/special-cc
The configuration script will incorporate the new CC value into the makefile that it generates, so you don't need to manually edit it, and you can just run make by itself thereafter (instead of giving the custom CC value on the command line every time).
Many makefiles use 'CC' to define the compiler. If yours does, you can override that variable with
make CC='/usr/bin/gcc'
Use variables for the compiler program name.
Either pass the new definition to the make utility or set them in the environment before building.
See Using Variables in Make
Makefile:
#!MAKE
suf=$(suffix $(src))
ifeq ($(suf), .c)
cc=gcc
else
ifeq ($(suf), .cpp)
cc=g++
endif
endif
all:
$(cc) $(src) -o $(src:$(suf)=.exe)
clean:
rm *.exe
.PHONY: all clean
Terminal:
$ make src=main.c