I have a simple Makefile
name=xxx
build:
docker build -t $(name) .
run:
docker run --rm -it $(name)
.PHONY: default
default: build run
When I do make, only build runs; but make default executes both build and run phrase.
Any ideas?
default isn't any special, a Makefiles default target is the one which was specified first.
name=xxx
.PHONY: default
default: build run
build:
docker build -t $(name) .
run:
docker run --rm -it $(name)
should do the trick.
The "default" target, i.e.: the target to be built by default if no target was specified to make (as opposed to the target with the name default), is the first target found in the makefile.
Just place the following line:
default: build run
before any other target in the makefile. This will turn the target named default into the default target.
The default target is the first rule in the makefile unless special steps are taken. See:
Arguments to Specify the Goals
You can change the default goal using .DEFAULT:
Special Built-in Target Names
Related
I have a make target which is not a file name.
BUILD_DIR := <my build directory path>
build : $(BUILD_DIR)
recipe
release : build
I observed that when I call build for the first time, it executes the recipe of build which is expected. However, when I call release followed by build it re-executes build. I have a clue on why this is happening, I read from GNU make references that -
If you write a rule whose recipe will not create the target file, the recipe will be executed every time the target comes up for remaking.
Do we have a way to avoid build getting re-built ? I cannot simply call release. My expectation is to call build followed by release and build should not re-execute when release is called. I know I can simply remove the dependency of release but I am not preferring it that way. Can someone recommend a better way out ?
The reason people are having a hard time replying is because your question is not at all clear. What exactly does my expectation is to call build followed by release and build should not re-execute when release is called mean? The term call build has no meaning in make: you don't "call" targets. If you showed us exactly what commands you ran and the output you got, and explained what you wanted instead, then it would be much simpler to provide correct answers.
I will assume you mean, you run make build followed by make release and you don't want to create a file named build and you don't want the build recipe to be run when you run make release even though you do want build to be listed as a prerequisite of release in the makefile.
In short, that's not possible.
Make decides whether a file should be rebuilt by comparing the modification time of the target file against the modification time of the prerequisites. If any of the latter are newer than the former, it runs the recipe. If the former (target) doesn't exist then the recipe is always invoked. Make doesn't maintain any sort of database between invocations saying when the last time a recipe was run or what targets were built the last time it ran: the only "database" it has is the modification times on the filesystem.
Since your build target doesn't create a file, how is make supposed to know when you do want the build target recipe to be invoked, and when you do not want the recipe to be invoked?
Release should have the build artifacts as prerequisites instead of the (phony) build target.
I'm going to try and give you a practical answer, but you really should look at the other answers for better practice.
You want the opposite of .PHONY. .PHONY is a phony target that is always built, you want a non-fake target that gets rebuilt conditionally... which is a regular target.
You want make to remember that it already called build, but make doesn't have any cache, it just uses files and mtime, so that's what you do:
BUILD_DIR := ./target
.PHONY: build release
$(BUILD_DIR):
mkdir $#
$(BUILD_DIR)/file.elf: $(BUILD_DIR) src.c
cp src.c $#
.built: $(BUILD_DIR)/file.elf
touch $#
build: .built
release: build
$ make release
mkdir target
cp src.c target/file.elf
touch .built
$ make build
make: Nothing to be done for 'build'.
The idea is in order to considered the codebase to be "built" (.built), a list of artifacts (in this case, just $(BUILD_DIR)/file.elf) needs to be up-to-date. And each such artifact has its own recipe.
Then make release will re-run the build target, but it will do nothing if the codebase is .built.
Notice how you could just skip .built and have build directly depend on $(BUILD_DIR)/file.elf as was suggested in the comments:
$(BUILD_DIR)/file.elf: $(BUILD_DIR) src.c
cp src.c $#
build: $(BUILD_DIR)/file.elf
If you instead go your way:
build: $(BUILD_DIR)
cp src.c $(BUILD_DIR)/file.elf
touch $#
Then when src.c gets updated, file.elf doesn't get rebuilt. To fix that, you'd have to list all the sources as dependencies of the build target, and that means your build won't be incremental: whenever it needs to rebuild anything, it will rebuild everything.
The only reason I can think of to actually use something like .built is if it's not feasible to list all the artifacts, for example if you build recipe creates a complicated, uncached set of artifacts:
.built:
bazel clean
bazel build //... # builds all packages
touch $#
build: .built
Or if the build is not specified by a file:
.has_container_image:
docker build --no-cache .
touch $#
build: .has_container_image
I'm using to building code with CMake; but I'm now faced with using meson to build a certain repository. With CMake and make, if I use something like:
cmake -DCMAKE_INSTALL_PREFIX=/some/where` build_dir
make -C build_dir
make -C build_dir install
then instead of the files going under /usr/local by default, they will go under /some/where, e.g. /some/where/bin for executables, /some/where/lib, for libraries etc.
What's the meson equivalent of doing this?
Inspired by: What is CMake equivalent of 'configure --prefix=DIR && make all install '?
It's actually similar to the autotools convention in terms of the switch:
meson setup --prefix=/path/of/installation/destination build_dir
ninja -C build_dir
ninja -C build_dir install
(you could drop the first ninja command; ninja install will build before it installs.)
I want phony clean target is always executed before build target but nothing else (like build target does not trigger clean).
I know solutions that don't rely on GNU Make language:
Launch them sequentially when order is needed:
make clean
make build
Encode sequential execution into required recipes:
.PHONY: install
install:
$(MAKE) clean
$(MAKE) build
Above "workarounds" suffer from being non-generic. I have to remember not to run make clean build!
My question is about expressive power of GNU Make language, if it is possible to define order without imposing dependency.
Other build systems have optional dependency declaration obeying order, like Gradle's mustRunAfter.
Actually there is a way to do what I think you want to do, but note my caveat above about depth-first order.
Your question is not completely clear but I think what you want to say is, if the user asked for both clean and build on the command line be sure that clean is performed first before build.
You can do this like:
build: $(filter clean,$(MAKECMDGOALS))
This will cause build to depend on clean IFF clean was specified as one of the command-line goals to build.
However note my comment above: this won't be enough if you invoke make with parallelism enabled, because it will not realize that all the object files etc. ALSO must wait for clean to complete. In order to make this really foolproof you'd have to add this prerequisite to EVERY target.
I have to remember not to run make clean build!
You could test the MAKECMDGOALS variable for presence of both clean and build, then throw error if they are both in there:
ifeq (clean, $(filter clean, $(MAKECMDGOALS)))
ifeq (build, $(filter build, $(MAKECMDGOALS)))
$(error Cannot have clean and build goals at the same time)
endif
endif
I am studying a Makefile obtained from a compiler course project. Only a part of it is pasted here.
# Retain intermediate bitcode files
.PRECIOUS: %.bc
# The default target builds the plugin
plugin:
make -C lib/p1
# create .bc from source
%.bc: %.c
clang -emit-llvm -O0 -c $*.c -o $*.bc
# run printCode on a .bc file
%.printCode: %.bc plugin
opt -load Debug/lib/P1.so -printCode $*.bc
As you see, the target 'plugin' has no dependencies, which, if I understand correctly, should mean that its recipe never runs (unless it is declaared as a phony target, which is not the case here)
However, when I type 'make printCode', (printCode is the last target in the list) the plugin target does execute. How is this made possible? Is there some implicit rule stating that the first target of a Makefile is regarded as a phony target, such as 'all'?
You've got things a little backward.
A rule like the plugin rule can run. You can run it by executing 'make plugin', or 'make' if it's the default target (which it is in this case by virtue of being the first), or if it is a prerequisite of another target that must be built.
I'm not sure exactly what happens when you 'make printCode', since you are showing us only part of the makefile and there is no rule that fits, but judging by this rule:
%.printCode: %.bc plugin
opt -load Debug/lib/P1.so -printCode $*.bc
I'd guess that the printCode rule depends on either plugin or something like foo.printCode that depends on plugin. So Make sees that plugin is a prerequisite, sees that no such file exists, and determines therefore that plugin must be built. It then looks for a rule to build plugin, finds it and runs it.
This is my Makefile:
REBAR=./rebar
REBAR_COMPILE=$(REBAR) get-deps compile
all: compile
compile:
$(REBAR_COMPILE)
test:
$(REBAR_COMPILE) skip_deps=true eunit
clean:
-rm -rf deps ebin priv doc/*
docs:
$(REBAR_COMPILE) doc
ifeq ($(wildcard dialyzer/sqlite3.plt),)
static:
$(REBAR_COMPILE) build_plt analyze
else
static:
$(REBAR_COMPILE) analyze
endif
I can run make compile multiple times and get
aromanov#alexey-desktop:~/workspace/gm-controller/lib/erlang-sqlite$ make compile
./rebar get-deps compile
==> erlang-sqlite (get-deps)
==> erlang-sqlite (compile)
However, for some reason running make test always gives
aromanov#alexey-desktop:~/workspace/gm-controller/lib/erlang-sqlite$ make test
make: `test' is up to date.
even if the files are not compiled. The question is, why?
Running the same command directly works:
aromanov#alexey-desktop:~/workspace/gm-controller/lib/erlang-sqlite$ ./rebar get-deps compile skip_deps=true eunit
==> erlang-sqlite (get-deps)
==> erlang-sqlite (compile)
Compiled src/sqlite3_lib.erl
Compiled src/sqlite3.erl
==> erlang-sqlite (eunit)
...
Maybe you have a file/directory named test in the directory. If this directory exists, and has no dependencies that are more recent, then this target is not rebuild.
To force rebuild on these kind of not-file-related targets, you should make them phony as follows:
.PHONY: all test clean
Note that you can declare all of your phony targets there.
A phony target is one that is not really the name of a file; rather it is just a name for a recipe to be executed when you make an explicit request.
It happens when you have a file with the same name as Makefile target name in the directory where the Makefile is present.
EDIT: This only applies to some versions of make - you should check your man page.
You can also pass the -B flag to make. As per the man page, this does:
-B, --always-make Unconditionally make all targets.
So make -B test would solve your problem if you were in a situation where you don't want to edit the Makefile or change the name of your test folder.
my mistake was making the target name "filename.c:" instead of just "filename:"