What is wrong in doing this (considering a parallel make)? - makefile

I have 2 dirs A and within A I have B.
Makefile in directory A looks like :
include rules.mk //defines common rules for generating *.o from *.cpp *.c
OBJECTS = test.o \
B\test1.o \
B\test2.o
test.lo : $(OBJECTS)
$(LD) $(LD_OPTS) -o $# $^
$(CREATE_CXX_SO)
As is B doesn't have a Makefile defined within it.
Is it mandatory for having Makefiles within the subdirs as well? For serial makes this doesn't seem to pose a problem but while doing parallel makes at times $(LD) tries making conn.lo even before B/test1.o and B/test2.o are compiled.
If what I am doing above is wrong, what are the options that I have?

I read an excellent article about the recursive use of make at... you guessed it, Recursive Make Considered Harmful. This article details the problems with the distressingly common recursive use of make, and how to build your Makefile such that it can run better and more reliably in parallel.
Or, you can use SCons which works brilliantly.

Related

Passing all object files in the project directory tree to a rule in makefile

I have a makefile that looks like this
CC=gcc
CFLAGS=-pedantic -ansi -Wall -O2
TARGET=assembler
SUBDIRS = utils preprocessor parser symbols
.PHONY: clean all subdirs $(SUBDIRS)
subdirs: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $#
all: subdirs
clean:
for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir clean; \
done
And I want to add
$(TARGET): subdirs $(TARGET).c
$(CC) $(CFLAGS) $(TARGET).c -o $#
But then I get linking error because the objects files from the subdirs aren't found. Is there a way to pass all object files under the project root directory?
Is there a way to pass all object files under the project root directory?
Usage of the word "pass" suggests that you have altogether the wrong mental model of makefiles and make operation. Makefiles are specifications, not scripts, and the rules within are not functions and do not operate like functions. Among other things, the targets and prerequisites of explicit rules are determined when the makefile is parsed, not dynamically at the time of (consideration of) rule execution.
It follows that what you propose to do is altogether unworkable, because you cannot rely on any of the object files -- they being built files -- to exist when make starts. You have a chicken and egg problem.
I fully agree with #Andreas that using globbing and similar dynamic target or prerequisite detection in a makefile is bad.* Targets and prerequisites that are named at all should be named explicitly (not to preclude assigning them to a variable or using substitution references or similar). But if you nevertheless do use globbing or another form of dynamic detection to locate files, then you should be locating files distributed with the project, not built ones.
If you want to maintain the modularity of your recursive make build system (which is not by any means a clear win), then one reasonable alternative would be for the make in each subdirectory to build a static archive named after the directory name. The top-level makefile then does not need to know any of the details of the subdirectory makes; it just includes the static library resulting from each one in the link.
*There are multiple reasons for this, but they are tangential to the question at hand.

GNU Makefile Multiple rules in multiple targets

I am doing a nasm project, and I need to execute the ej and use as a parameter the ex.asm . I tried searching through GNU how can I pick one by one the parameter. My solution has been writing ex1_ and ex2_, but I want to put those inside the $(ex) dependency, so I don't have to replicate multiple times the same code. Is there any way?
Thank you in advance
The code:
ej = ej1_gen ej2_gen
ex = ex1 ex2
# -----------------------------------------------
all: $(ej) $(ex)
exs: ex1_ ex2_
# -----------------------------------------------
$(ex): exs
nasm -g -o $#.o -f elf32 $#.asm
$(CC) $(FLAGS) -m32 -o $# $#.o alfalib.o
ex1_:
./ej1_gen ex1.asm
ex2_:
./ej2_gen ex2.asm
As I read the question, you have programs or scripts ej1_gen and ej2_jen in the project, serving to generate the wanted assembly sources. They each take the name of the output file as a command-line argument. Parts of this answer would need to be adjusted if that's a misinterpretation.
Rules to describe how to build the assembly files should designate the resulting assembly file(s) as the target. Also, supposing that the code-generator programs are part of the project, they should be designated as prerequisites, since changing those could cause them to produce different outputs. Any configuration files or similar that they read to inform their results should also be named as prerequisites (not shown). That leads to rules something like this:
ex1.asm: ej1_gen
./ej1_gen $#
ex2.asm: ej2_gen
./ej2_gen $#
It sounds like you may be asking for a way to express that via just one rule covering both, but I would not do so in this case. I don't think you get any clearer than the above, even if there are more than two assembly files to generate. It might be different if the same code generator program were being used, with different options, to generate all the assembly files, or perhaps if the generator name could be derived more directly from the target name.
With those rules in place, you can write a generic suffix rule or pattern rule to assemble the resulting files. Since you tag [gnu], I'll assume that a pattern rule is acceptable:
%.o: %.asm
nasm -g -o $# -f elf32 $<
And you can take a similar approach to expressing a link rule:
%: %.o alfalib.o
$(CC) $(FLAGS) -m32 -o $# $^
With that, you should be able to get rid of the ej variable and the exs target, too, leaving
all: $(ex)
as the only other rule (and it should still appear first in the file, as it does now).

How to handle dependencies from recursive Makefile invocations?

I have a C project that consists of a fairly large number of source files, and to make some sense of them, I have put them into subdirectories (with subdirectories). The whole project results in only one executable file, however.
In order to build this project, then, I am using recursive Makefiles, where the Makefile in each non-toplevel directory links all the object files produced in that directory into a concatenated lib.o file (using ld -r, that is). I do have a Makefile system that can build this and works rather fine for what it is, but it cannot support parallel make, which I would like to fix.
The problem is that I cannot figure out a proper way to both force make to descend into each directory's subdirectories, but also have the local lib.o target depend on that without being forced to rebuild even when nothing has changed.
This is how it works, somewhat abbreviated (leaving out CFLAGS and whatnot):
default: build
SUBOBJECTS = $(patsubst %,%/lib.o,$(SUBDIRS))
.PHONY: $(SUBDIRS)
$(SUBDIRS):
#$(MAKE) -C $#
build: $(SUBDIRS) lib.o
lib.o: $(OBJECTS) $(SUBOBJECTS)
$(LD) $(LDFLAGS) -r -o $# $^
This is from a Makefile.common which all other Makefiles include. Every other Makefile would also define their own SUBDIRS and OBJECTS. It might look like this, for instance:
SUBDIRS = dir1 dir2
OBJECTS = object1.o object2.o
include ../Makefile.common # Or ../../Makefile.common, &c.
As you can see from this, the main target is really the build target, which depends on the subdirectories and lib.o. If I invoke parallel make on this, it won't know that lib.o cannot be built until make has already run recursively on the subdirectories and will sometimes attempt that, causing errors. However, if I make lib.o depend on the subdirectories, then lib.o will always be unnecessarily rebuilt on each invocation, in each directory.
Is there a way to solve this? I've wrecked my brains on this for quite a while now without being able to find a way out. I'm only using GNU make, so don't worry too much about being POSIX-compatible.

Canonical 'simple project' makefile

Your small C/C++ project has reached a point where it's no longer practical to have all your code in one file. You want to split out a few components. So you make a src/ directory, and then... you have to write a real Makefile. Something more than hello: hello.o. Uh-oh... was it $# or $< or $^? Crap. You don't remember (I never do).
Do you have a 'one-size fits all' simple Makefile that can deal with straightforward source trees? If so, what's in it and why? I'm looking for the smallest, simplest Makefile that can compile a directory full of C files nicely without me having to edit the Makefile every time I add a file. Here's what I have so far:
CXX = clang++
CXXFLAGS = ...
LDFLAGS = ...
EXENAME = main
SRCS = $(wildcard src/*.cc)
OBJS = $(patsubst src%.cc,build%.o, $(SRCS))
all: $(EXENAME)
build/%.o: src/%.cc
#mkdir -p $(dir $#)
$(CXX) -c -o $# $^ $(CXXFLAGS)
$(EXENAME): $(OBJS)
$(CXX) -o $# $^ $(LDFLAGS)
clean:
rm -rf $(EXENAME) build/
This Makefile builds all the .cc files in the src/ directory into .o files in the build/ directory, then links them up into the parent directory.
What would you do differently?
I would reconsider you decision not to have an explicit list of sources-- I think it may cause you trouble in the long run. But if that's your decision, this makefile is pretty good.
In the %.o rule I would use $< instead of $^, so that later you can add dependencies like
build/foo.o: bar.h
And when you're ready, you can take a look at Advanced Auto-Dependency Generation.
I've never used CMake, so I really can't say anything about that. The best that I can offer is a program that we have at school called 'makemake', which automatically makes Makefiles - http://www.cs.rit.edu/~swm/makemake/ It's not a very advanced program, but it gets the job done. On the plus side, it's incredibly easy to use - simply do 'makemake > Makefile' in the directory and you have a Makefile which will build and link all the source files in that directory(C and C++). On the bright side, if you ever add more files, you just run makemake again and you have a new makefile. On the downside, there's no way to keep any custom targets that you've done from one generated makefile to the next.
As for 'one size fits all' makefiles, while you could definitely do that, it takes away from the purpose of the 'make' command in the first place - which is to keep track of the files last modified time, and thus only re-compile the files that have recently changed, or depend on header files that have just changed(although to generate the correct you can use 'makedepend' - http://www.x.org/archive/X11R7.5/doc/man/man1/makedepend.1.html ). You could use what you currently have plus makedepend in order to make a self-updating makefile.
Use automake tools. Its easy to make changes and less burden to the developer. Its as simple as specifying the SOURCES, LDLIBS, LDFLAGS as variables. At first it may seem like a bit weird. But it becomes your favorite as you do more on it.

makefile conditionals

Note: using MinGW's make (should be GNU make)
i have a couple of -include statements in my makefile to import dependencies which were generated using g++ -MM. However I would like to only do this when necessary. I have several different build targets and I don't want all of their respective dependency files to be included since this takes a while (suppose I'm running make clean: no need to include them in this case)
Here's the format of my makefile.
DEPS_debug = $(patsubst %.cpp,build_debug/%.d,$(SRC))
OBJ_debug = $(patsubst %.cpp,build_debug/%.o,$(SRC))
all: program_debug
-include $(DEPS_debug) #make: include: Command not found
program_debug: $(OBJ_debug)
$(CC) $(CFLAGS) $(OBJ_debug) -o $#
If you really don't want to include those files needlessly, you have a couple of options:
You can put in a conditional as Diego Sevilla suggests (but I would recommend using MAKECMDGOALS so that you can write a more flexible version, specific to targets, e.g. you'll include foo.d if and only if you're making foo.o).
You can use make recursively (heresy!), invoking $(MAKE) for each target object, using a makefile that includes that target's dependencies.
But actually including the file takes negligible time, it's the rebuilding of the file (automatic for any included file that's out of date) that takes time.
If needless rebuilding is what you want to avoid, you can use a very clever trick. When must foo.d be rebuilt? Only when something about foo has changed. But in that case foo.o must also be rebuilt. So don't have a seperate rule for foo.d, just rebuild it as a side effect of making foo.o. That way you can include all dependency files and not waste time rebuilding them if they aren't needed.
EDIT:
I'm astounded that merely including these files can add 2-3 seconds to make clean. My last paragraph is off the mark, so let me expand on the first two options.
If all is the only target for which these files should be included, and you make all from the command line (and not e.g. make all tests tarball install kitchenSink), then this will do it:
ifeq ($(MAKECMDGOALS),all)
-include $(DEPS_debug)
endif
Note that this will not include foo.d if you make foo.o. You can write a more sophisticated conditional, something like
$(foreach targ,$(MAKECMDGOALS),$(eval $(call include_deps $(targ)))...
but that's pretty advanced, so let's get a simple version working first.
If you'd rather avoid the conditional and use recursive Make, the simplest way is to split the makefile in two:
makefile:
all:
$(MAKE) -f makefile.all
clean:
rm whatever
...other rules
makefile.all:
DEPS_debug = $(patsubst %.cpp,build_debug/%.d,$(SRC))
OBJ_debug = $(patsubst %.cpp,build_debug/%.o,$(SRC))
-include $(DEPS_debug)
all: program_debug
program_debug: $(OBJ_debug)
$(CC) $(CFLAGS) $(OBJ_debug) -o $#
Indenting a line by a TAB makes make think it's a command to be passed to the shell (as you found out). It doesn't work that way.
The - in front of include suppresses errors that might result from DEPS_debug not existing (e.g. when running clean or release without having had a dependency-file-generating call first). Since DEPS_debug is not a dependency of those rules (clean / release), your dependency files do not get generated when you call them, and everything is fine. I don't really see the problem you're having - you don't have to make the include conditional.
Perhaps you'd like to change your approach, though. Instead of having a seperate *.d target, with a seperate -M preprocessor pass, you might want to try something like -MMD -MP which generates the dependency files inline during code generation, in your standard *.c -> *.o pass.
(I know this sounds completely wrong at first, but when you think about it, it makes sense. Makefile logic is a bit backwards that way, unless you're familiar with functional programming.)
includes are independent of the rules, as they are makefile indications, not compilation indications. You can, however, use makefile conditionals based on special makefile variables such as MAKECMDGOALS, that is set to the default goal:
ifeq ($(MAKECMDGOALS),all)
-include whatever
endif
This is included when no default goal is specified. You can change the condition to specify the exact goal you want to check to include other sub-makefiles.

Resources