GNU make - enforcing target order - makefile

Could someone please tell me if there is a way to enforce sequential execution of specific Makefile targets. For example, I have a Makefile that builds Libraries and Executables. Now, Executables depend on Libraries, so they must be built after the Libraries are built and staged. This is what I currently have in a single Makefile:
.PHONY: all
all: all_lib all_bin
.PHONY: all_lib
all_lib: $(dep_lib)
.PHONY: all_bin
all_bin: $(dep_bin)
I have two targets all_lib and all_bin, one builds all libraries and the other builds all binary executables. When I pass -j to make to run parallel jobs, I get build failures, because all targets run in parallel and binaries can't find shared library objects and staged header files.
I tried changing it to this to try and force some dependency order:
.PHONY: all
all: all_bin
.PHONY: all_lib
all_lib: $(dep_lib)
.PHONY: all_bin
all_bin: all_lib $(dep_bin)
But for some reason all targets still run in parallel I still get the same build failures. Any ideas?

Make is entirely built around the concept of dependencies. You are simply not using it that way.
If an executable depends on a library, then you should list that library in the prerequisites list of the executable. I can't give you a relevant example because you don't provide any details about the contents of dep_lib or dep_bin above, but for example:
exe1 : exe1.o liblib1.a liblib2.a
etc. Now, exe1 won't attempt to be linked until after the liblib1.a and liblib2.a targets have been created.

Related

makefile last target not getting executed

word.o: word.c word.h
gcc -c word.c
line.h: word.h
touch line.h
Above is the contents of the makefile. when I execute make.
I see the file word.o is created. But the file line.h is not.
What could be the reason for this? As far as I know, the make doesn't
execute those targets which don't have any dependencies.
But here the dependency list is not empty, Still, it didn't get executed
Certainly make builds targets that don't have dependencies. If a target has no dependencies, then it is considered out of date if it doesn't exist.
The problem is that make doesn't build every single target in the makefile: that would be bad because many people include clean targets, test targets, and other targets that they only want to run sometimes not every time.
You can read the introduction in the GNU make manual, specifically this section, to understand what's happening.

Define order without imposing dependency in GNU Make

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

Can GNU make have targets that depend on the completion of targets from other makefiles?

I have several directories representing subparts of a project, each with its own Makefile.
I want to create a master Makefile with targets for each of those subparts, each target satisfying the following:
depend on a certain target from that subproject's Makefile.
This is the tricky part.
copy some resulting library/executable build by the subproject into a central directory (kind of like "make install"-ing it).
This I can already achieve using simple commands.
I could only find information about the include directive of GNU make, but that doesn't help me much as it seems not to encapsulate the rules (and execution) of the included makefile in its own directory, but instead just #includes them C-style (rather that thinking of them as packages with separate scopes).
INSTALLDIR := build
SRCDIR := src
TARGETS := projA projB
.PHONY: $(TARGETS)
TARGETS_PATH := $(addprefix $(SRCDIR)/, $(TARGETS))
MAKEFILES := $(addsuffix /osx.mak, $(TARGETS_PATH))
# include them somehow?
For such a setup as defined above, I now want each of $(TARGETS) to depend on the release target of its corresponding Makefile (something like projA: $(SRCDIR)/projA/osx.mak # release for projA, in my own language meaning that target projA depends on the successful execution of the release target in that specific Makefile).
Is there any way to achieve this?
You can suggest other tools apart from GNU make, but the subproject makefiles are already written as makefiles.
Have a look at recursive make.
You could do something like,
SRCDIR := src
TARGETS := projA projB
.PHONY: $(TARGETS)
$(TARGETS):
cd $(SRCDIR)/$#; $(MAKE) release

How to create a non-transitive dependency list (GCC)

Is there a way to generate dependencies of a C(++) source file similar to using the -MM option of GCC that only include the direct dependencies of said file, i.e. only the files directly included by this source file?
More context on why I'm looking for this functionality - maybe there is a completely different solution to my problem: I have a generic makefile with auto-detection of dependencies that suffices my needs but is slow. The basic structure is as follows:
Full dependencies of main.cpp are retrieved with gcc -MM
All *.h dependencies for which a corresonding *.cpp exists are changed to *.o dependencies
the altered dependencies are included in the makefile
All *.o targets are built, dependencies are retrieved with gcc -MM and included
All *.o targets are linked to create the executable
So far, this makefile has worked fine but -as said before- it is slow. I analyzed its execution path for one project and included all the generated dependencies by hand to try and optimize its speed. The result was by removing all transitive dependencies, the makefile retained its functionality but got much faster (also reflected in the number of lines of the debug output of make -d).
First of all, the method you are using is slightly confusing. All .h files used in the compilation of one .cpp file must be kept in its dependencies, and the automatic collection of *.o files shouldn't be that slow. I'd advise to go with classic -MM and to build the list of cpp files that are to be compiled by hand. automake does it that way, and if there was a really reliable way of figuring out the list of compilation units automatically, these guys would have found it :-).
Nevertheless, the -H option of the gcc helps you. It prints the names of all used files to stderr, with . prefixed for the level of inclusion. So,
cpp -I $< >/dev/null | sed -n -e 's/^\. //p'
should do the trick. Caveat: If a header file is included deeper in the hierarchy first and then later in the main file, it is not found. However, your dependency system should be able to handle that if you keep the 1-to-1 of .h and .cpp files.

What is the difference between make and gcc?

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 :)

Resources