How to force make to always rebuild a file from this answer more specifically, I was able to achieve my goal as a beginner, so I better commented on everything.
I have these 4 files in one directory; ls -F:
iterator Makefile test* test.cpp
where all the files should be self-explanatory, but I have some little feeling, the iterator may sound a bit odd, so just to be crystal clear, I want to store/show the information on how many times I recompiled the test.cpp source code.
Here I would politely like to ask HOW the forcing of rebuild/recompile actually works? I am no expert on Makefiles so that about sums it up.
Here is my actual Makefile with no changes at all:
CXX := g++-10
CXXFLAGS := -O2 -std=c++20 -Wall -Wextra -Werror -Wpedantic -pedantic-errors
APP_NAME := test
SRC_FILE := $(APP_NAME).cpp
# The following works!
# However, I have no idea how? :(
$(APP_NAME): .force_rebuild
.PHONY: .force_rebuild
$(APP_NAME): $(SRC_FILE)
# quickly delete terminal buffer
#clear
# increase test number
#expr $$(cat iterator) + 1 > iterator
# print test number description
#printf '%s' "Test Nr.: "
# set bright cyan color for the number
#tput bold; tput setaf 6
# print test number
#cat iterator
# reset to normal terminal color
#tput sgr0
# compile (always force rebuild)
#$(CXX) $(CXXFLAGS) $(SRC_FILE) -o $(APP_NAME)
# run my test app
#./$(APP_NAME)
For completeness, I work on Linux Mint 20.2 Cinnamon with Bash as shell and VS Code as a text editor using GNU Make 4.2.1.
Side note: It looks weird and less readable when without syntax highlight, which is the only why I am attaching a screenshot also:
From the manual:
One file can be the target of several rules. All the prerequisites mentioned in all the rules are merged into one list of prerequisites for the target. If the target is older than any prerequisite from any rule, the recipe is executed.
In your case you have two rules for the app target. The prerequisite .force_rebuild from the first rule is marked as .PHONY, which makes your app target always older than .force_rebuild. This triggers execution of the recipe for the app target. That recipe is in the second rule.
Just in case, also pointing out the paragraph following the above quote:
There can only be one recipe to be executed for a file. If more than one rule gives a recipe for the same file, make uses the last one given and prints an error message.
Related
I have created the following little makefile snippet. Note: I have made this a minimal example of my problem so it is a pointless makefile.
TARGET = none
OBJ_BASE_DIR = obj
# Linux x86 c++ compiler
.PHONY: build_cpp_x86Linux
build_cpp_x86Linux: TARGET = x86Linux
build_cpp_x86Linux: build
OBJ_DIR = $(addsuffix /$(TARGET),$(OBJ_BASE_DIR))
$(info TARGET IS: $(TARGET))
$(info OBJ_DIR IS: $(OBJ_DIR))
build: $(OBJ_DIR)/test.o
#echo building, OBJ_DIR: $(OBJ_DIR)
# pattern rule
$(OBJ_DIR)/%.o:
#echo "compiling $#"
Here is the output of calling make:
TARGET IS: none
OBJ_DIR IS: obj/none
compiling obj/none/test.o
building, OBJ_DIR: obj/x86Linux
From the output you can see that it is trying to compile obj/none/test.o, but what I want it to do is try to compile obj/x86Linux/test.o. I am not quite sure what is going on here. I think I understand that the makefile expands the variables on the first pass (which would result in TARGET=none), but I thought that it would re-expand the variables again once I have called the target build_cpp_x86Linux which sets the value of TARGET to x86Linux...
What I am doing wrong here and how should this be done?
You could also use:
TARGET?=none
And then override on the command line TARGET=x86Linux
You can also use ifdef or other scanning if operations to set different variables based on these arguments or environment variables.
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 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.
I'm running into a bizarre problem with a C++ makefile. I rewrote it this afternoon because the old one I was using made me want to kill myself, and I'm running into a weird problem regarding variable reassignment and dynamic dependancies.
for the purposes of this question, assume the following values:
OBJMOD_MODULENAME = obj/lib/foo.o obj/lib/bar.o obj/lib/quux.o
LIBDIR = lib/
CXX = g++
CXXLIBLINK = -shared
LIB = -lm -lpt
I have a target of the following format:
modulename: OBJ_CURRENTMOD = $(OBJMOD_MODULENAME)
modulename: $(OBJMOD_MODULENAME) lib/metrics.so
and later on, another of the following format:
$(LIBDIR)%.so: $(OBJ_CURRENTMOD)
$(CXX) $(CXXLIBLINK) -o $# $(OBJ_CURRENTMOD) $(LIB)
Lines in code blocks always appear in the order in which they are presented in the code blocks, however over the course of debugging I have changed the position of the blocks relative to each other.
The problem occurs after I change a source file and try to recompile with 'make modulename'. Building the object files works as expected, but rebuilding the library does not happen if the file already exists, i.e. the dependencies specified by $(OBJ_CURRENTMOD) are ignored. Using $(OBJMOD_MODULENAME) in the library dependencies works as expected. I have verified in a number of ways that the value of $(OBJ_CURRENTMOD) is as expected (stick echo
$(OBJ_CURRENTMOD) on the first line of the library target for example), but no matter what I try, the variable does not seem to update in time to trigger a recompile due to dependancy checking.
As I was typing this, I found a workaround:
OBJMOD_MODULENAME = obj/lib/foo.o obj/lib/bar.o obj/lib/quux.o
LIBDIR = lib/
CXX = g++
CXXLIBLINK = -shared
LIB = -lm -lpt
modulename: OBJ_CURRENTMOD = $(OBJMOD_MODULENAME)
modulename: $(OBJMOD_MODULENAME) lib/metrics.so
$(LIBDIR)%.so: herp $(OBJ_CURRENTMOD)
$(CXX) $(CXXLIBLINK) -o $# $(OBJ_CURRENTMOD) $(LIB)
herp: $(OBJ_CURRENTMOD)
This dummy target tacked in before the variable reference seems to force it to update and solves my problem. Is this a bug in make or something? make --version indicates GNU make 3.81. Can anyone else confirm this weird behavior? Am I just doing something horribly stupid? I've been staring at it for hours, I wouldn't be that surprised.
edit: turns out that wasn't really fixing it, it was just trapping it into running every time regardless of whether or not it needed it.
To verify the altered value:
$(LIBDIR)%.so: $(OBJ_CURRENTMOD)
echo $(OBJ_CURRENTMOD)
$(CXX) $(CXXLIBLINK) -o $# $(OBJ_CURRENTMOD) $(LIB)
As I said in one of my comments, I don't see how the $(LIBDIR)%.so pattern will match any pre-requisite of modulename but assuming metrics.so is meant to be lib/metrics.so then it will be used to build lib/metrics.so.
As interjay pointed out, "As with automatic variables, these values are only available within the context of a target's recipe (and in other target-specific assignments)." They can't be used in a target pattern or in a list of pre-requisites, which explains why the target doesn't get rebuilt when one of the pre-requisites in $(OBJ_MODULENAME) changes.
To make $(OBJ_CURRENTMOD) valid in the prerequisites list you'll need to use secondary expansion
.SECONDEXPANSION:
$(LIBDIR)%.so: $$(OBJ_CURRENTMOD)
$(CXX) $(CXXLIBLINK) -o $# $(OBJ_CURRENTMOD) $(LIB)
You are using the target-specific variable value OBJ_CURRENTMOD in the prerequisite list of the $(LIBDIR)%.so rule. This is not allowed: Target-specific variables may only be used in the recipe of a target.
Another issue is that you are defining the variable OBJ_MODULENAME and later accessing a different variable $(OBJMOD_MODULENAME), which hasn't been assigned to.