make - remove intermediate files silently - makefile

When building a chain rule make automatically invokes rm to remove any intermediate files at the end of the build process. Since I have about 400 intermediate files to delete that way, that floods console output badly.
Is there a way to silently rm those intermediate files, so that eighter nothing will be echoed after the build is finished oder a message like "Removing intermediate files" is echoed?

You could run make -s or build your very own version of make with this patch applied:
diff --git file.c file.c
index ae1c285..de3c426 100644
--- file.c
+++ file.c
## -410,18 +410,6 ## remove_intermediates (int sig)
{
if (! doneany)
DB (DB_BASIC, (_("Removing intermediate files...\n")));
- if (!silent_flag)
- {
- if (! doneany)
- {
- fputs ("rm ", stdout);
- doneany = 1;
- }
- else
- putchar (' ');
- fputs (f->name, stdout);
- fflush (stdout);
- }
}
if (status < 0)
perror_with_name ("unlink: ", f->name);

Expanding on the accepted answer, you can modify Make's flags from within the Makefile itself (as demonstrated here). So, for your situation, you can include this at the top of your Makefile:
MAKEFLAGS += --silent
The only thing to be aware of is that the --silent flag silences all Make's output. Including the "Nothing to be done" notices.
Edit:
You can also add your target as a dependency to .SILENT, as described at https://www.gnu.org/software/make/manual/html_node/Special-Targets.html.

Related

`cmse_check_address_range` changes behaviour with compiler upgrade

I'm using a Cortex-M33 with arm trust-zone. I have a secure api inside my secure firmware that I can call from my non-secure firmware. All works as expected - at least until I upgraded my compiler from gcc-arm-none-eabi-7-2018-q2-update to gcc-arm-none-eabi-10-2020-q4-major.
The function in question looks like this:
bool __attribute__((cmse_nonsecure_call)) (*Callback_Handler)();
__unused __attribute__((cmse_nonsecure_entry))
bool Secure_SetSomeCallbackHandler(bool (*handler)()) {
// this cmse-check fails with the compiler in `version gcc-arm-none-eabi-10-2020-q4-major`
// it works with the `gcc-arm-none-eabi-7-2018-q2-update` though
handler = cmse_check_address_range(handler, 4, CMSE_NONSECURE);
if (handler == NULL) {
return false;
}
Callback_Handler = handler;
return true;
}
I make sure the supplied pointer really is in non-secure space by using cmse_check_address_range. That works for the version 7, but if I compile the code with version 10, NULL is returned. I did not change anything in the source or any other part, just the compiler.
I checked for any changes in that function, but even https://github.com/gcc-mirror/gcc/commits/master/libgcc/config/arm/cmse.c does not show any changes whatsoever.
Did anything change? Maybe I'm using the function not as intended (do I need different flags for functions? But then again, it works with version 7.
Update:
I also posted this in arm embedded toolchain forum:
https://answers.launchpad.net/gcc-arm-embedded/+question/695596
#HsuHau https://stackoverflow.com/a/66273629/1358283 posted a bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99157
It seems to be a GCC bug when libgcc checking CMSE support.
It checks $? for the return value of a gcc command, but in Makefile it should use $$? instead.
diff --git a/libgcc/config/arm/t-arm b/libgcc/config/arm/t-arm
index 364f40ebe7f9..3625a2590bee 100644
--- a/libgcc/config/arm/t-arm
+++ b/libgcc/config/arm/t-arm
## -4,7 +4,7 ## LIB1ASMFUNCS = _thumb1_case_sqi _thumb1_case_uqi _thumb1_case_shi \
HAVE_CMSE:=$(findstring __ARM_FEATURE_CMSE,$(shell $(gcc_compile_bare) -dM -E - </dev/null))
HAVE_V81M:=$(findstring armv8.1-m.main,$(gcc_compile_bare))
-ifeq ($(shell $(gcc_compile_bare) -E -mcmse - </dev/null >/dev/null 2>/dev/null; echo $?),0)
+ifeq ($(shell $(gcc_compile_bare) -E -mcmse - </dev/null >/dev/null 2>/dev/null; echo $$?),0)
CMSE_OPTS:=-mcmse
endif
I have reported the bug:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99157

Writing out dependencies into a file using Make

I'm writing a Makefile for Verilog compilation (isn't important if you aren't familiar with it). The compiler command can either take compile units or a flat file that has the compile units 'in order'. For the latter case, I'd like to write a rule that will spit out a file that has the dependencies in the right order.
Let's assume a simple makefile below:
a.output:
<a.files>
b.output: a.output
<b.files>
c.output: d.output
<c.files>
d.output: d.input
<d.files>
What I'd like is a file that contains:
a.files
b.files
d.files
c.files
An idea I had was to have a variable in the recipe that can be appended to, like
a.output:
MY_FILES += <a.files>
but I don't think that will work in a recipe context. Does anyone have a decent solution to this problem?
Also, I'd like the Makefile to be parallel but obviously it won't work for this target. How can I specify disabling parallel execution for this specific target or set of targets?
EDIT Oct 8 2019
To make it simpler for a person not familiar with Make syntax to write dependencies, I've basically let them write out their intent using variables:
MODULES += module_a
module_a.prerequisites = module_b module c
module_a.other_var = some_string_a
MODULES += module_b
module_b.prerequisites =
module_b.other_var = some_string_b
I then use a define directive to generate the rules necessary for compilation (I was inspired by this example). This means I do have flexibility on what I can create. So, in the previous example, <a.output> is actually the target for module_a. This can be a PHONY target. <a.files> actually represents the variables (prerequisites and other_var in the example).
I'm sorry for the miscommunication but what I'm trying to do is write out all the target and dependent module_x.other_var in the right order for a given module. I hope that makes it clear.
I'm currently concatenating a file in the right order which is one of the solutions mentioned below. I was wondering if there's some other Make magic that I could apply.
In its simplest form, you can just echo the names to the file
OUTPUT_FILE = output.file
a.output:
echo "<a.files>" > $(OUTPUT_FILE)
b.output: a.output
echo "<b.files>" >> $(OUTPUT_FILE)
c.output: d.output
echo "<c.files>" >> $(OUTPUT_FILE)
d.output: d.input
echo "<d.files>" >> $(OUTPUT_FILE)
If these files are prerequisites then you can print each dep or target using the auto vars:
Print the target/goal
d.output: d.input
echo "$#" >> $(OUTPUT_FILE)
print the first prerequisite
d.output: d.input
echo "$<" >> $(OUTPUT_FILE)
print all prerequisites
d.output: d.input
echo "$^" >> $(OUTPUT_FILE)
update for parallel build
Not pretty, can certainly improve this, but this will be safe for parallel builds. However as I say I think the echo method alone seems to work ok.
Also note this is not tested, so treat as pseudo code
OUTPUT_FILE = output.file
OUTPUT_FILE_A = output.file.a
OUTPUT_FILE_B = output.file.b
OUTPUT_FILE_C = output.file.c
OUTPUT_FILE_D = output.file.d
OUTPUT_FILES = $(OUTPUT_FILE_A)
OUTPUT_FILES += $(OUTPUT_FILE_B)
OUTPUT_FILES += $(OUTPUT_FILE_C)
OUTPUT_FILES += $(OUTPUT_FILE_D)
final: a.output b.output c.output d.output
echo "" > $(OUTPUT_FILE)
for file in "$(OUTPUT_FILES)" ; do \
cat $$file >> $(OUTPUT_FILE) ; \
done
a.output:
echo "<a.files>" > $(OUTPUT_FILE_A)
b.output: a.output
echo "<b.files>" > $(OUTPUT_FILE_B)
c.output: d.output
echo "<c.files>" > $(OUTPUT_FILE_C)
d.output: d.input
echo "<d.files>" > $(OUTPUT_FILE_D)

can't get correct arguments when use awk command in a defined function

There is a version.h file in project, like this:
#ifndef _VERSION_H_
#define _VERSION_H_
#define PROJNAME "Uranium"
#define VERSION "1.0.1"
#endif
And I want to print the project name and version when use make to compile the project.
So I added following makefile:
PROJNAME_KEYWORD = "PROJNAME"
VERSION_KEYWORD = "VERSION"
define GetPropValue
$(shell \
awk '{ \
split($$0, words, " "); \
for (i in words) { \
if (index(words[i], $$(1)) != 0) { \
word = words[i + 1]; \
gsub("\"", "", word); \
print word; \
break; \
} \
} \
}' version.h \
)
endef
ifndef PROJNAME
PROJNAME = $(call GetPropValue, $(PROJNAME_KEYWORD))
endif
ifndef VERSION
VERSION = $(call GetPropValue, $(VERSION_KEYWORD))
endif
it's expected to have this:
PROJNAME = Uranium
VERSION = 1.0.1
But actually I got this,
PROJNAME=_VERSION_H_ _VERSION_H_ PROJNAME VERSION
VERSION=_VERSION_H_ _VERSION_H_ PROJNAME VERSION
After some debugging process, I found $$(1) in
if (index(words[i], $$(1)) != 0) {
line is incorrect,
when I replaced $$(1) with "PROJNAME",
I can get right result,
PROJNAME = Uranium
$$(1) should be arguments, like $(PROJNAME_KEYWORD) from
$(call GetPropValue, $(PROJNAME_KEYWORD))
So in this case, how to write this?
Summary
Since you want to obtain data about macro definitions recorded in a C header file, the most natural tool to apply to the job would be the C preprocessor. So how about skipping the user-defined function altogether, and going with
PROJNAME = $(shell echo PROJNAME | cat version.h - | cpp -P | tr -d '"')
Explanation
You are already assuming GNU's version of make., and its $(shell) function in particular. $(shell) executes a shell command and evaluates to the contents of the command's standard output. In this case, the command executed determines the definition of a preprocessor macro defined in version.h by
concatenating the contents of version.h with a line containing the bare macro name, and
piping the result into the preprocessor. The -P option to the preprocessor suppresses generation of extra output, such as line-number indicators.
The macro definition contains quotation marks that are not part of the value you say you want to assign to your make variable, so the preprocessor output is furthermore piped into tr to strip those.
Demonstration
Given this complete makefile ...
PROJNAME = $(shell echo PROJNAME | cat version.h - | cpp -P | tr -d '"')
demo:
#echo '$(PROJNAME)'
... , and the version.h file presented in the question residing in the same directory, running make or make demo produces this output:
Uranium
I tried another day,
if (index(words[i], $$(1)) != 0) { \
$$(1) is incorrect, should be replaced with $(1),
if (index(words[i], $(1)) != 0) { \
but this cause another problem,
there are lots of error happens when makefile have static check before running,
awk: line 1: syntax error at or near )
awk: line 1: syntax error at or near }
This means static check don't know $(1) it is, might replace with empty but I'm not sure,
to resolve this, add "" before $(1),
so it should be like this,
if (index(words[i], ""$(1)) != 0) { \
it's all right in static check, and $(1) will be replaced with argv[1] properly.

Eiffel compilation through Makefile and `dpkg-buildpackage -us -uc` generating an error

Am trying to create a debian package of my Eiffel application.
Either make or make -j4 (which is the called one from dpkg-buildpackage) within the root structure does the job without error
but when called from dpkg-buildpackage -us -uc which calls the Makefile it exits with an error
In file included from big_file_C7_c.c:40:0:
lo322.c: In function ‘inline_F425_4447’:
lo322.c:97:5: error: format not a string literal and no format arguments [-Werror=format-security]
syslog(arg1, arg2);
^~~~~~
cc1: some warnings being treated as errors
My makefile for info is as following:
#Build variables
MY_EC = $(shell which ec)
BUILT_TARGET = EIFGENs/$(TARGET_NAME)/F_code/$(APP_NAME)
# This target will compile all files
all: build
build:
# Checks eiffel compiler
# #echo "MY EC IS: ${MY_EC}"
#if [ -z "${MY_EC}" ]; then
echo "Compiler not found";
else
echo "Eiffel compiler found";
fi
# Compilation
echo '---------->finalizing'
ec -finalize -config $(APP_NAME).ecf -target $(TARGET_NAME) || (echo "last command failed $$="; exit 1)
cd $(FINAL_EXE_DIR); \
echo '---------->Finish freezing';\
finish_freezing || (echo "A problem occured during finish_freezing!!!"; exit 1)
The issue is caused by the feature c_logging_write_log of the class LOG_WRITER_SYSTEM in EiffelStudio 18.11 and earlier that makes the following call:
syslog($priority, $msg);
Replacing it with
syslog($priority, "%s", (char *) $msg);
(in $ISE_EIFFEL/library/runtime/logging/writers/log_writer_system.e) and recompiling the system (from scratch, if the logging library is marked as read-only) should fix the problem.

Makefile does not find target

I have the following Makefile, but it does not work. When I call
make html
I get a
make: *** No rule to make target `docs/index.html', needed by `html'. Stop.
error, even though I think I have defined it.
SRCDIR = source
OUTDIR = docs
RMD = $(wildcard $(SRCDIR)/*.Rmd)
TMP = $(RMD:.Rmd=.html)
HTML = ${subst $(SRCDIR),$(OUTDIR),$(TMP)}
test:
echo $(RMD)
echo $(TMP)
echo $(HTML)
all: clean update html
html: $(HTML)
%.html: %.Rmd
echo $(HTML)
#Rscript -e "rmarkdown::render('$<', output_format = 'prettydoc::html_pretty', output_dir = './$(OUTDIR)/')"
update:
#Rscript -e "devtools::load_all(here::here()); microcosmScheme:::updateFromGoogleSheet(token = './source/googlesheets_token.rds')"
## from https://stackoverflow.com/a/26339924/632423
list:
#$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$#$$' | xargs
.PHONY: update clean cleanhtml all list
The variables seem to be correct:
15:21 $ make test
echo source/index.Rmd
source/index.Rmd
echo source/index.html
source/index.html
echo docs/index.html
docs/index.html
If I change it as follow it works, but the target points to the SRCDIR, but I want it to point to the OUTDIR:
RMD = $(wildcard $(SRCDIR)/*.Rmd)
HTML = $(RMD:.Rmd=.html)
# HTML = ${subst $(SRCDIR),$(OUTDIR),$(TMP)}
I am sure it is one small thing...
This rule:
%.html : %.Rmd
....
tells make how to build a file foo.html from a file foo.Rmd, or a file source/foo.html from a file source/foo.Rmd, or a file docs/foo.html from a file docs/foo.Rmd.
It doesn't tell make how to build a file docs/foo.html from a file source/foo.Rmd, because the stem that matches the pattern % is not the same.
If you want to write a pattern for docs/foo.html to be built from source/foo.Rmd, you have to write it like this:
$(OUTDIR)/%.html : $(SRCDIR)/%.Rmd
....
so that the part that matches the pattern % is identical.
ETA Some other notes: you should be using := with the wildcard function as it's much better performing. Also you shouldn't use subst here because it replaces all occurrences of the string which could break things if any of your .Rmd files contain the string source for example (e.g., source/my_source_file.Rmd. This is much better written with patsubst, as in:
RMD := $(wildcard $(SRCDIR)/*.Rmd)
HTML := $(patsubst $(SRCDIR)/%.Rmd,$(OBJDIR)/%.html,$(RMD))
Finally, you don't show what the clean target does but it's unusual to have the clean target depended on by all. Usually it's a separate target that is invoked only when you want it, like make clean.

Resources