Using Make, how to build multiple configuration in one make command - makefile

Thanks for all your time and response -
Currently, we are using the nested build, multiple Makefiles, and individual subdirectories having their own Makefile, all are connected with a top-level Makefile. We are running
make xxxxx_yyyy_defconfig
make
this builds and creates an output file which is xxxxx.elf file. --- Till here everything works fine.
Now we are having multiple def-configs(around 50), I want to build all configurations using one "make all" command. is that possible?
This is not a simple case where we can put all "all: prog01 prog02 prog03" as every program needs to have a different configuration. Configuration can be achieved by using "make xxxxx_yyyy_defconfig". The output of "make config" is the .config file, which is used during the "make" command.
Based on .config file many variables are exported which is used at the subdirectory level.
So How can I build multiple configurations using a single "make all" command?
Environment - Ubuntu, Cross compile for ARM, output file xxxx.elf.
With the use of script and make file I am able to solve, But I have to solve only using Makefile.
in Makefile add one PHONY target
all:
./build_all.sh #shell script calling.
Created one shell script like this
#! /usr/bin/bash
echo "Make All"
for entry in `ls conf`; do
make $entry
wait
make
if [ $? -eq 0 ] ; then
for xxxfile in `ls xxx*_*` ; do
xxxdir=$(echo $xxxfile | cut -b yy-zz)
mkdir -p $xxxdir
mv $xxxfile $xxxdir/
done
else
break
fi
done

If you want to build several configurations you must do this out of tree in separate build directories (make O=/tmp/builds/foo foo_defconfig; make -C /tmp/builds/foo) to avoid conflicts. A shell script could do this as well as a Makefile but if you insist on using a Makefile you could try the following that assumes your source tree is in /src/kernel and you want to build configuration foo in /tmp/builds/foo; adapt to your needs:
$ pwd
/tmp/builds
$ cat Makefile
CONFIGS := uuuu_vvvv xxxx_yyyy ...
BUILD := /tmp/build
KERNEL := /src/kernel
.PHONY: $(CONFIGS) all
all: $(CONFIGS)
$(CONFIGS):
rm -rf $#
mkdir -p $(BUILD)/$#
$(MAKE) -C $(KERNEL) O=$(BUILD)/$# $#_defconfig
$(MAKE) -C $(BUILD)/$#
$ make

Related

Makefile: Calling a recipe within another recipe will not run-dry it

Let's say I have a Makefile looking like this
file1:
$(MAKE) unittest
#echo "Making test file"
touch file1
unittest:
#echo Running test. In reality recipe will include many lines
.PHONY: unittest
My goal is to have a recipe to only run unit tests, but I also want to run them before creating the file (file1) and I don't want to run them if file1 exists.
This works when I run make, but I notice when I try
make file1 -n
file1 will be created and it is somehow due to having the make unittest call in the recipe.
Any clue about what is going on? Thanks in advance.
Either one of us is confused, or there's something about your makefile or environment you didn't share, or you have a buggy version of GNU make (what version do you have and what OS are you using? The version of GNU make that ships with MacOS is known to be old and Apple has made changes to it that have added bugs).
Doesn't reproduce on my system:
$ cat Makefile
file1:
$(MAKE) unittest
#echo "Making test file"
touch file1
unittest:
#echo Running test. In reality recipe will include many lines
.PHONY: unittest
$ ls file1
ls: cannot access 'file1': No such file or directory
$ make -n
make unittest
echo Running test. In reality recipe will include many lines
echo "Making test file"
touch file1
$ ls file1
ls: cannot access 'file1': No such file or directory
ETA
It's clear you don't want the file1 to be created if you run make -n.
But, your question didn't make clear whether you want the sub-make invocation of unittest to happen when you run make -n, or whether you don't want it to happen.
If you want unittest to be run but you don't want file1 to exist, but you do want to use .ONESHELL, then you're out of luck.
If you don't want unittest to run or file1 to exist when you run with -n, you can prevent it by fooling make into not noticing that the recipe is a recursive make invocation; all you have to do is not use the variable MAKE in the recipe. However, note that this has other side-effects particularly if you use -j to enable parallel builds:
NR_MAKE = $(MAKE)
file1:
$(NR_MAKE) unittest
#echo "Making test file"
touch file1

How can I build two interactive web-sites from one GNU makefile and mostly the same source?

I'm using GNU Make to build a dynamic web site but I need to build two versions. As a net result currently I run my makefile using two command line incantations. This is inefficient and can result in errors (I don't always remember to run both versions or make a typing error and they fail) thus I want to make it one build.
The Command Line incantations are:
sudo make release build=test
sudo make release build=release
The two incantations activate ifeq blocks that set the path and modify some files.
Part of the much simplified (to help readability) top level makefile:
subs = today tomorrow
files = index.php foot.php
ifeq ($(build),test)
export path = /var/www/html/cgi-test
$(shell cp -f head-test.php head.php)
$(shell sed -i '/"DB"/c\ define("DB", "db_test");' subs.php)
else ifeq ($(build),release)
export path = /var/www/html/cgi-new
$(shell cp -f head-release.php head.php)
$(shell sed -i '/"DB"/c\ define("DB", "db_new");' subs.php)
endif
.PHONY: all go
all:
$(MAKE) go
#for ALL in $(subs);\
do $(MAKE) -C $$ALL all || exit $$?;\
done;
go:
cp $(files) $(path)/.
The sub-makefiles have a very similar structure but don't need the ifeq blocks because the files and paths have already been setup.
I think I can simply move the shell commands into the .PHONY rules but I can't do that with the exports because I get errors "export: : bad variable name".
I could do it with a batch file and call the makefile twice but that sidesteps the problem rather than cures it and I wish to learn from the process.
So can anybody show me the way to do this in a makefile?
Thanks to Tripleee here is the answer that finally worked back ported to match my starting post. The one major change is that I have gone back to 'all' as the rule I expect to start the build habits die hard! - Thanks
.PHONY: all both rel-test rel-release
cgi-test := cgi-test
db-test := db_test
cgi-release := cgi-new
db-release := db_new
subs = today tomorrow
files = index.php foot.php
all: both
both: rel-test rel-release
rel-test rel-release: rel-%:
cp -f head-$*.php head.php
sed -i '/"DB"/c\ define("DB", "$(db-$*)");' subs.php
$(MAKE) go path=/var/www/html/strutts/$(cgi-$*)
#for ALL in $(subs);\
do $(MAKE) build=$* path=/var/www/html/strutts/$(cgi-$*) -C $$ALL all || exit $$?;\
done;
Something like this?
.PHONY: both rel-test rel-release
both: rel-test rel-release
cgi-test := cgi-test
db-test := db_test
cgi-release := cgi-new
db-release := db_new
rel-%:
cp -f head-$*.php head.php
sed -i '/"DB"/c\ define("DB", "$(db-$*)")' subs.php
$(MAKE) release build=$* path=/var/www/html/$(cgi-$*)
The reason the export can't be moved into a recipe is that you are using the export command of make itself, not the shell's command with the same name.
You absolutely should not use sudo unless you specifically require the output files to be owned and only writable by root. Even then, running as much as possible as a regular user would be proper hygiene; maybe add a sudo command inside the Makefile to copy the files to their final location.

Makefile - Execute a rule for every field in a variable

I have my project binary located at my repository's root, along with a Makefile used to build it.
This binary uses many of my self-made libraries, located in my lib/ folder
For the purpose of building (and cleaning) my repository's binary, I want to implement the following execution :
Instead of hardcoding the following lines,
clean_binaries:
make -C clean lib/folder1 -s
make -C clean lib/folder2 -s
make -C clean lib/another_folder -s
I created the BIN_PATH variable, containing the previous paths.
BIN_PATHS = lib/folder1 \
lib/folder2 \
lib/another_folder
And made a simple rule like this one :
clean_binaries: $(BIN_PATHS)
make -C clean $< -s
BUT it only executes the line for the first field of the variable (lib/folder1), which is not what I want to do.
I thought about using implicit rules(?), just like I compile the .c files, but I couldn't get it right.
In the end, I simply wonder how to execute a rule for every field of a given variable, and this inside a Makefile, if there is any way to do so.
Thank you for your answers :]
The way you get GNU make to generate a sequence of commands that vary by the
fields in a variable is to use the foreach function, e.g.
Makefile
BIN_PATHS := lib/folder1 lib/folder2 lib/another_folder
.PHONY: clean_binaries
clean_binaries:
$(foreach path,$(BIN_PATHS),make -C $(path) clean ;)
which runs like:
$ make
make -C lib/folder1 clean -s; make -C lib/folder2 clean -s; make -C lib/another_folder clean -s;
not requiring a shell-loop.
Note also that you need to correct:
make -C clean <directory>
to:
make -C <directory> clean

What's the standard makefile idiom for trying different ways to make a target

I have a makefile that uses a source file from the internet. There are two locations where the file resides, neither of which I consider very dependable, so I also keep a local copy. So the relevant lines of my makefile look like:
src.c:
wget -nv http://location.com/$# || wget -nv http://otherplace.com/$# || cp local/$# .
src.o: src.c
$(CC) -o $# $<
Is this the "right way" to do this? What if there are multiple steps in each different way of creating the target - how do I tell make "Try A. If A fails, try B. If B fails, ..."?
The right thing to do is this:
.PHONY: phony
src.c: phony
if (wget -nv http://location.com/$# -O $#.temp) && ! diff $#.temp $# >/dev/null; then \
mv $#.temp $#; \
fi
I shortened your command to a single wget but you can put whatever you want there, including a sequence of ||s to achieve "try this, if not, try that etc". Just make sure it outputs to a temporary file (and does not hang indefinitely !) .
It is in fact important to use phony here, and not only .PHONY. Can you see why?
Also, with this method, there is no longer a need to keep another "local" copy and/or use cp. Your target src.c is your "local copy" - the latest one you were able to successfully get from the Internet.

Understanding make-command in makefile?

I'm trying to modify a makefile to cross-compile binaries. The command in question is below:
# GNU Make solution makefile autogenerated by Premake
# Type "make help" for usage help
ifndef config
config=debug
endif
export config
PROJECTS := json openjaus openjaus-core openjaus-environment openjaus-mobility openjaus-manipulator openjaus-ugv Base Managed PingTest LargeMessageTest PdDemo GposDemo GposClientDemo StillImageSensorDemo StillImageClientDemo
.PHONY: all clean help $(PROJECTS)
all: $(PROJECTS)
json:
#echo "==== Building json ($(config)) ===="
#${MAKE} --no-print-directory -C .build -f json.make
As can be seen the makefile has several targets. They all have the same structure as the 'json' target. The command in question in question is
#${MAKE} --no-print-directory -C .build -f json.make
The '${MAKE}' variable = make (I have verified this with echo)
What does the -C do?
What does the .build do?
I'm good with -f json.make
Also, when I run make the json.make file gets created compiles file and deletes it self, so I do not have access to that file.
The error I receive when I modify the command in question is
==== Building json (debug) ====
make[1]: Nothing to be done for `/home/botbear/openwrt/trunk/staging_dir/toolchain- arm_v6k_gcc-linaro_uClibc-0.9.32_eabi/bin/arm-openwrt-linux-c++'.
The command after modifications looks like:
#${MAKE} /home/botbear/openwrt/trunk/staging_dir/toolchain-arm_v6k_gcc-linaro_uClibc-0.9.32_eabi/bin/arm-openwrt-linux-c++ --no-print-directory -C .build -f json.make
Any help is appreciated!
you can use man make to understand the parameters for make:
-C dir, --directory=dir
Change to directory dir before reading the makefiles or doing any-
thing else. If multiple -C options are specified, each is inter-
preted relative to the previous one: -C / -C etc is equivalent to
-C /etc. This is typically used with recursive invocations of
make.
-f file, --file=file, --makefile=FILE
Use file as a makefile.
so -C .build changes to the directory .build.
and i don't understand the part of your question about modifying the command.
Try to find where json.make lives. It seems that it's that makefile which creates & deletes the directory you were talking about.
From the command line it seems that make changes directory to .build and executes the json.make. Not sure how json.make ends up there. Is .build the directory which is created and then deleted?

Resources