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 just discovered this line in a makefile:
%: Makefile
To me, that says "to make any target, you need this makefile", which strikes me as somewhat obvious.
Is there any situation in which this is not a no-op?
As Etan commented, this will cause every target to be rebuilt whenever the Makefile changes. This is necessary so that anytime you make a change in the build configuration parameters the target will be rebuilt. Otherwise make won't know to rebuild with the new configuration.
Automake 1.14 is causing us a few issues. At first, automake errored with the complaint:
warning: source file 'X' is in a subdirectory but option 'subdir-objects' is disabled
So I enabled subdir-objects, but now it isn't recompiling some files. For example, lets say
src/a/foo.c is compiled in SUBDIR a but in src/b, I would like to compile it again with different preprocessor flags, however since ../a/foo.o already exists, make doesn't rebuild it. This is because subdir-objects changes am_b_OBJECTS to look for ../a/foo.o instead of foo.o. Is there a way I can get around the original complaint and instruct make to build the file a second time with the appropriate preprocessor flags? This all worked on previous versions of automake.
I would settle for executing rm ../a/foo.o before compiling src/b but I don't know how to edit the Makefile.am to make that happen.
This happens if you're using subdir-objects under the same tree from different Makefile.am files. As automake can't see you're using the same source file with different parameters it'll assume it was rebuilt correctly.
The proper solution to this is to not use separate Makefile.am files and instead rephrase the build system as non-recursive automake and so in that case it would then build foo.c as foo-a.o and foo-b.o.
I have a project with autotools: automake, autoconf.
I want to prohibit make from remaking files configure, Makefile.in, etc; just to do compile job.
Some of files are edited by hand, and I know that I should not to do this. (Or the project was updated from CVS with all generated files stored in CVS).
But at the moment I have no correct version autotools installed.
What must be modification times of this files (which must be newer/older):
aclocal.m4
configure.in
confdb/ax_prefix_config_h.m4
Makefile.am
Makefile.in
Makefile
configure
config.status
Or: what sequence of touch commands must I do to achieve my goal?
First of all, if you edit a generated file directly, it wouldn't be rebuilt anyway, because it is then newer then its prerequisites.
Then, there are two separate things going on here: config.status and Makefile are created during the build. It's hard to prevent these from being remade during the build unless you make their timestamps newer.
The other files are generated by the various autotools. Recent versions of Automake do not create rules by default that remake them automatically. Depending on your package, you might want to use the configure option --disable-maintainer-mode. The Automake documentation contains some more interesting information about that option.
One trick I sometimes use with a package that I don't know much about or that has a pretty messed up build system is to run something like
make all AUTOCONF=: AUTOHEADER=: AUTOMAKE=: ACLOCAL=:
so that if these programs happen to be called, a noop would be substituted.
touch confdb/*.m4
touch configure.in
touch *.m4
touch *.am
touch Makefile.in */Makefile.in
touch *config.h.in */*config.h.in
touch configure
touch config.status
touch config.h
touch Makefile
Problems with automake & cvs are described here http://www.gnu.org/s/hello/manual/automake/CVS.html
Try to explicitly tell make those files should not be remade, via command-line
$ make -o configure -o Makefile.in
or by using MAKEFLAGS
$ MAKEFLAGS="-o configure -o Makefile.in" make
The excerpt from GNU make's manual
‘-o file’
‘--old-file=file’
‘--assume-old=file’
Do not remake the file file even if it is older than its prerequisites, and do not remake
anything on account of changes in file. Essentially the file is treated as very old and
its rules are ignored. See Avoiding Recompilation of Some Files.
If yours autotools template correctly uses $(MAKE) for subdirs, there should be no problems.
The last sentence in the article caught my eye
[F]or C/C++ developers and
students interested in learning to
program in C/C++ rather than users of
Linux. This is because the compiling
of source code is made simple in
GNU/Linux by the use of the 'make'
command.
I have always used gcc to compile my C/C++ programs, whereas javac to compile my Java programs. I have only used make to install programs to my computer by configure/make/make install.
It seems that you can compile apparently all your programs with the command make.
What is the difference between make and gcc?
Well ... gcc is a compiler, make is a tool to help build programs. The difference is huge. You can never build a program purely using make; it's not a compiler. What make does it introduce a separate file of "rules", that describes how to go from source code to finished program. It then interprets this file, figures out what needs to be compiled, and calls gcc for you. This is very useful for larger projects, with hundreds or thousands of source code files, and to keep track of things like compiler options, include paths, and so on.
gcc compiles and/or links a single file. It supports multiple languages, but does not knows how to combine several source files into a non-trivial, running program - you will usually need at least two invocations of gcc (compile and link) to create even the simplest of programs.
Wikipedia page on GCC describes it as a "compiler system":
The GNU Compiler Collection (usually shortened to GCC) is a compiler system produced by the GNU Project supporting various programming languages.
make is a "build tool" that invokes the compiler (which could be gcc) in a particular sequence to compile multiple sources and link them together. It also tracks dependencies between various source files and object files that result from compilation of sources and does only the operations on components that have changed since last build.
GNUmake is one popular implementation of make. The description from GNUmake is as follows:
Make is a tool which controls the generation of executables and other non-source files of a program from the program's source files.
Make gets its knowledge of how to build your program from a file called the makefile, which lists each of the non-source files and how to compute it from other files.
gcc is a C compiler: it takes a C source file and creates machine code, either in the form of unlinked object files or as an actual executable program, which has been linked to all object modules and libraries.
make is useful for controlling the build process of a project. A typical C program consists of several modules (.c) and header files (.h). It would be time-consuming to always compile everything after you change anything, so make is designed to only compile the parts that need to be re-compiled after a change.
It does this by following rules created by the programmer. For example:
foo.o: foo.c foo.h
cc -c foo.c
This rule tells make that the file foo.o depends on the files foo.c and foo.h, and if either of them changes, it can be built by running the command on the second line. (The above is not actual syntax: make wants the commands indented by a TAB characters, which I can't do in this editing mode. Imagine it's there, though.)
make reads its rules from a file that is usually called a Makefile. Since these files are (traditionally) written by hand, make has a lot of magic to let you shorten the rules. For example, it knows that a foo.o can be built from a foo.c, and it knows what the command to do so is. Thus, the above rule could be shortened to this:
foo.o: foo.h
A small program consisting of three modules might have a Makefile like this:
mycmd: main.o foo.o bar.o
$(CC) $(LDFLAGS) -o mycmd main.o foo.o bar.o
foo.o: foo.h bar.h
bar.o: bar.h
make can do more than just compile programs. A typical Makefile will have a rule to clean out unwanted files:
clean:
rm -f *.o core myapp
Another rule might run tests:
check: myapp
./myapp < test.input > test.output
diff -u test.correct test.output
A Makefile might "build" documentation: run a tool to convert documentation from some markup language to HTML and PDF, for example.
A Makefile might have an install rule to copy the binary program it builds to wherever the user or system administrator wants it installed.
And so on. Since make is generic and powerful, it is typically used to automate the whole process from unpacking a source tarball to the point where the software is ready to be used by the user.
There is a whole lot of to learn about make if you want to learn it fully. The GNU version of make has particularly good documentation: http://www.gnu.org/software/make/manual/ has it in various forms.
Make often uses gcc to compile a multitude of C or C++ files.
Make is a tool for building any complex system where there are dependancies between the various system components, by doing the minimal amount of work necessary.
If you want to find out all the things make can be used for, the GNU make manual is excellent.
make uses a Makefile in the current directory to apply a set of rules to its input arguments. Make also knows some default rules so that it executes even if it doesn't find a Makefile (or similar) file in the current directory. The rule to execute for cpp files so happens to call gcc on many systems.
Notice that you don't call make with the input file names but rather with rule names which reflect the output. So calling make xyz will strive to execute rule xyz which by default builds a file xyz (for example based on a source code file xyz.cpp.
gcc is a compiler like javac. You give it source files, it gives you a program.
make is a build tool. It takes a file that describes how to build the files in your project based on dependencies between files, so when you change one source file, you don't have to rebuild everything (like if you used a build script). make usually uses gcc to actually compile source files.
make is essentially an expert system for building code. You set up rules for how things are built, and what they depend on. Make can then look at the timestamps on all your files and figure out exactly what needs to be rebuilt at any time.
gcc is the "gnu compiler collection". There are many languages it supports (C, C++, Ada, etc depending on your setup), but still it is just one tool out of many that make may use to build your system.
You can use make to compile your C and C++ programs by calling gcc or g++ in your makefile to do all the compilation and linking steps, allowing you to do all these steps with one simple command. It is not a replacement for the compiler.
'gcc' is the compiler - the program that actually turns the source code into an executable. You have to tell it where the source code is, what to output, and various other things like libraries and options.
'make' is more like a scripting language for compiling programs. It's a way to hide all the details of compiling your source (all those arguments you have to pass the compiler). You script all of the above details once in the Makefile, so you don't have to type it every time for every file. It will also do nifty things like only recompile source files that have been updated, and handle dependancies (if I recompile this file, I will then need to recompile THAT file.)
The biggest difference is that make is turing complete (Are makefiles Turing complete?) while gcc is not.
Let's take the gcc compiler for example.
It only knows how to compile the given .cpp file into .o file given the files needed for compilation to succeed (i.e. dependencies such as .h files).
However, those dependencies create a graph. e.g., b.o might require a.o in the compilation process which means it needs to be compiled independently beforehand.
Do you, as a programer want to keep track of all those dependencies and run them in order for your target .o file to build?
Of course not. You want something to do that task for you.
Those are build tools - tools that help making the build process (i.e. building the artifacts like .o files) easier. One such tool is make.
I hope that clarifies the difference :)