I am launching multiple builds of a verilog compiler using Make. I am only using Make to take advantage of the -j flag. My file looks something like this
allfpga: fpga0 fpga1 fpga2 fpga3 fpga4 fpga5 fpga6
fpga0:
cd fpgas/$(#)/build && $(MAKE)
fpga1:
cd fpgas/$(#)/build && $(MAKE)
fpga2:
cd fpgas/$(#)/build && $(MAKE)
fpga3:
cd fpgas/$(#)/build && $(MAKE)
fpga4:
cd fpgas/$(#)/build && $(MAKE)
fpga5:
cd fpgas/$(#)/build && $(MAKE)
fpga6:
cd fpgas/$(#)/build && $(MAKE)
And I invoke one of make -j2 allfpga or make -j2 fpga0 fpag3 fpga5 fpga6
However if there is a typo (such as in the command I gave fpag3), in the second make target, the system will happily spend minutes building, and then stop early.
My question, how can I get make to stop initially if some of the targets are not real ones?
There's no good way to get make to "pre-screen" all your requested targets. Make can't know if a target is buildable until it tries to build it (for example it could be created based on some other target using a pattern rule or something).
However, you could do something like this:
ALLFPGAS := fpga0 fpga1 fpga2 fpga3 fpga4 fpga5 fpga6
# Get any command line goal which is not one of ALLFPGAS
unknown := $(filter-out $(ALLFPGAS),$(MAKECMDGOALS))
# If there are any, bail!
$(if $(unknown),$(error Unknown FPGA: $(unknown)))
allfpga: $(ALLFPGAS)
$(ALLFPGAS):
cd fpgas/$#/build && $(MAKE)
.PHONY: allfpga $(ALLFPGAS)
Related
I'm pretty much a makefile novice so I don't even know the terminology I'm looking for. I'm trying to build the latest valgrind release alongside other 3rdparty tools my company uses. I basically have
../3rdparty/
/Makefile <- What gets called to recursively build everything
/valgrind/Makefile <- What I'm pasting below
/valgrind/valgrind-3.16.1/Makefile <- what gets configure'd
So I can go into ../3rdparty/valgrind/valgrind-3.16.0/ and call...
./configure --host=arm-linux-gnueabihf
make
...and have it succeed without issue. However, when I try to build it from the Makefile in ../3rdparty/valgrind I get errors due to configuration generated variables being lost. I can see it clean up everything, I can see configuration succeed, but when the make process starts I get warnings that aren't seen using the process above.
cc1: warning: switch -mcpu=cortex-a8 conflicts with -march=armv7ve switch
Which eventually leads to an error
<command-line>:0:5: error: expected identifier or β(β before numeric constant pub_core_basics.h:78:12: note: in expansion of macro βARMβ
I basically copy pasted what is used for other 3rd party libs in our codebase and made changes where applicable....
include ../common.mak
VERSION=valgrind-3.16.1
all: configure build #install
configure: configure_$(TARGET)
configure_$(TARGET):
$(MAKE) distclean
#echo -e "\nConfiguring $(VERSION) for $(TARGET)...\n"
pushd $(VERSION)/ \
&& bash configure --host=${TARGET} \
&& popd
touch $#
#echo -e "\nConfiguration $(VERSION) complete for $(TARGET)...\n"
build: configure
$(MAKE) "-SC" $(VERSION)
install: build
$(MAKE) -SC $(VERSION) $#
# call folder's makefile targets verbatim
clean distclean:
test -f $(VERSION)/Makefile && $(MAKE) -SC $(VERSION) $# || :
rm -f configure_*
uninstall:
$(MAKE) -SC $(VERSION) $#
I'm guessing it's a one line thing, but I'd also be interested in any docs or websites that would be
useful. A lot of makefile tutorials go over the same super basic stuff.
Hi i have a makefile that compiles my library and then compiles the program. What i want to do is that the makefile recompile alway i modify my library's files for that i thought in this
ifneq ("$(wildcard $(PATH_LIB.A)","")
FILE_EXIST = 1
else
FILE_EXIST = 0
endif
$(MAIN_PROCESS): $(PATH_LIB.A) check_lib
...thing to do...
$(PATH_LIB.a):
FILE_EXIST = 0
check_lib:
ifeq("$(FILE_EXIST)","0")
$(MAKE) -C $(PATH_MAKEFILE_LIB.A)
endif
My problem es that when i compile it relinks all time "...thins to do..." because is checking all time check_lib as updateable what do you suggest for do what i want to do?
Make is not a scripting language like bash or python. What it needs is a description of inter-dependencies between targets and prerequisites, plus recipes to build them. In your case (but I am not sure I understood all details) you could try:
$(MAIN_PROCESS): $(PATH_LIB.A)
...thing to do...
$(PATH_LIB.A):
$(MAKE) -C $(PATH_MAKEFILE_LIB.A)
And that's all (but continue reading, there is more to understand). This tells make that:
$(MAIN_PROCESS) depends on $(PATH_LIB.A), plus the things to do to build $(MAIN_PROCESS) if it does not exist or if it is older than $(PATH_LIB.A).
$(PATH_LIB.A) depends on nothing, plus what to do if it does not exist.
It almost works. Almost only because if $(PATH_LIB.A) already exists but is out of date (with respect to its own source files) it will not be rebuilt. A solution is to declare it as phony:
.PHONY: $(PATH_LIB.A)
$(MAIN_PROCESS): $(PATH_LIB.A)
...thing to do...
$(PATH_LIB.A):
$(MAKE) -C $(PATH_MAKEFILE_LIB.A)
This way make will always try to rebuild it, even if it already exists. The sub-make will do it if needed, else it will just tell you that it was up to date. But it is not the whole story: as make always tries to rebuild $(PATH_LIB.A), it will consider that $(MAIN_PROCESS) must also be rebuilt, even if the sub-make didn't do anything because $(PATH_LIB.A) was up-to-date.
If this is a problem, more tricky solutions can be used, like using one more sub-make. The idea is the following:
Use make conditionals to create two different contexts of invocation with two different rules for your $(MAIN_PROCESS) target.
On the first invocation of make, the first context is used where $(MAIN_PROCESS) depends on the phony $(PATH_LIB.A) but its recipe, instead of ...thing to do... is a second invocation of make, in the other context.
For this second invocation $(MAIN_PROCESS) depends on the non-phony $(PATH_LIB.A) and will have its normal recipe.
The two contexts are distinguished thanks to a dedicated make variable (SECONDPASS in the code below).
Example:
host> cat lib/Makefile
foo.a: foo.c
touch $#
host> cat Makefile
ifeq ($(SECONDPASS),)
$(MAIN_PROCESS): $(PATH_LIB.A)
$(MAKE) SECONDPASS=1
.PHONY: $(PATH_LIB.A)
$(PATH_LIB.A):
$(MAKE) -C $(dir $#)
else
$(MAIN_PROCESS): $(PATH_LIB.A)
touch $#
endif
host> make --no-print-directory
make -C lib/
touch foo.a
make SECONDPASS=1
touch bar
host> make --no-print-directory
make[1]: 'foo.a' is up to date.
make SECONDPASS=1
make[1]: 'bar' is up to date.
host> touch lib/foo.c
host> make --no-print-directory
make -C lib/
touch foo.a
make SECONDPASS=1
touch bar
host> touch lib/foo.a
host> make --no-print-directory
make -C lib/
make[1]: 'foo.a' is up to date.
make SECONDPASS=1
touch bar
In my project, I have a set of programs that are build from sources:
SRC_FILES = $(wildcard $(SRC_DIR)/*.cpp)
TARGETS = $(patsubst $(SRC_DIR)/%.cpp,$(BIN_DIR)/%,$(SRC_FILES))
My build target is simple, and works fine:
all: $(TARGETS)
#echo "- Done target $#"
Now, I want a run target so that all these programs are run from the shell on request. Say, if I have 3 files, I want make to run automatically:
>$ ./test1
>$ ./test2
>$ ./test3
Or
>$ ./test1 && ./test2 && ./test3
I tried this:
run: $(TARGETS)
$(addsuffix && ,$(TARGETS))
That generates the following command:
./test1&& ./test2&&
but it fails, due to the trailing &&
(Of course, I want these to be generated automatically as there can be 3... or 30.)
Edit: actually, the && separator is not required, so something like this:
>$ ./test1; ./test2; ./test3;
will be fine too.
Have some .PHONY line near start of Makefile with
.PHONY: all run
You might have
run: $(TARGETS)
$(addsuffix && ,$(TARGETS)) true
but it is a dirty trick.
Maybe you want to produce the output of test2 into test2.out then you might have
TESTSCRIPTS= $(wildcard test*[0-9])
run: $(patsubst %, %.out, $(TESTSCRIPTS))
test%.out: test%
# here some command to run the test%
As alternatives to Basile Starynkevitch's entirely correct answer here there are (at least) two other options as well.
You can avoid the need to run an unnecessary command (builtin though it might be) to end the list by manually pulling off the first entry (this may in fact be more costly then the shell builtin though).
run: $(TARGETS)
$< $(addprefix &&,$(wordlist 2,$(words $^),$^))
A better option I think, assuming that connecting the commands with && isn't a necessity would be to use $(foreach) to generate the command to be run.
run: $(TARGETS)
$(foreach t,$^,$t;)
The trailing ; in that is crucial as the output from $(foreach) is a single line and you need ; to terminate each shell command (or it is seen as one long command with arguments).
I have a simple makefile with 3 build rules:
clean (that cleans the .o)
debug (compiles my code with debgging stuff)
release (compiles my code with optimization stuff)
sometimes I want to switch between debug mode and release so I would issue this
make clean debug -j8
or
make clean release -j8
that has a drawback because while it's doing the clean stuff, the -j8 allows make to jump some command since the .o are still there Then those .o are removed by the clean rule and the compiler complains because it can't find those .o
I could do something like
make clean; make debug -j8
but since I use an odd makefile in another dir, the command becomes
make -C ../src -f nMakefile clean ; make -C ../src -f nMakefile -j8 release
that is more annoying. I was wondering if there was an hiddedn-guru-mode-rule that allows me to do it in one line
Hope it's clear enough...
I needed to solve this very same problem, and the solution I came up was to parse the MAKECMDGOALS for clean, and dispatch a shell command to do the actual cleaning work; RATHER than clean the build as a target. This way, any MAKECMDGOALS that include "clean" will clean the build as part of that build, first, sequentially, rather than clean running asynchronously as its own target.
-include $(deps)
bin/%.o : %.cpp
#mkdir -p $#D
g++ $(flags) $(includes) -MMD -c $< -o $#
.PHONY : clean
clean:
#echo rm -rf bin/
ifneq ($(filter clean,$(MAKECMDGOALS)),)
$(shell rm -rf bin/)
endif
As I stated above, the normal practice is to have different sub directories for the object files. As you are running in parallel I would think you need to enforce serial execution so that clean is completed before release. One way of doing it could be:
clean_release: clean
+#$(MAKE) -s --no-print-directory release
or if you prefer
clean_release:
+#$(MAKE) -s --no-print-directory clean && $(MAKE) -s --no-print-directory release
When recursively invoking nmake, via the $(MAKE) macro, how can I pass on the target specified on the command line to the new instance?
So, say I execute the following from the command line:
c:\nmake clean
I want the recursive call to nmake to pass the 'clean' target to the new nmake instance.
you can write rule like this:
clean all:
cd dir1 && $(MAKE) $*
cd dir2 && $(MAKE) $*
$* will be substituted by target name ("clean" or "clean" in this example)
I'm not sure I understand the question but you normally have the rule by virtue of the fact that your executing a specific part of the makefile, such as:
clean:
cd dir1 && $(MAKE) clean
cd dir2 && $(MAKE) clean
all:
cd dir1 && $(MAKE) all
cd dir2 && $(MAKE) all
If you have some other setup in your makefile, your best bet is to post it so we can do a better analysis.