Can GNU make execute a rule whenever an error occurs? - error-handling

This is slightly different from Can a Makefile execute code ONLY when an error has occurred?.
I'd like a rule or special target that is made whenever an error occurs (independent of the given target; without changing the rule for every target as the other answer seems to imply with the || operator).
In dmake there is special target .ERROR that is executed whenever an error condition is detected. Is there a similar thing with GNU make?
(I'm still using GNU make 3.81, but I didn't find anything in the documentation of the new GNU make 4.0 either)

Gnu doesn't support it explicitly, but there's ways to hack almost anything. Make returns 1 if any of the makes fail. This means that you could, on the command line, rerun make with your error rule if the first make failed:
make || make error_targ
Of course, I'll assume you just want to put the added complexity within the makefile itself. If this is the case, you can create a recursive make file:
all:
$(MAKE) normal_targ || $(MAKE) error_targ
normal_targ:
... normal make rules ...
error_targ:
... other make rules ...
This will cause the makefile to try to build normal_targ, and iff it fails, it will run error_targ. It makes it a bit harder to read the makefile for the inexperienced, but it puts all the logic in one place.

Related

Makefile and variable target from command line

Newbie question for Makefiles... why doesn't this work?
TARGET=$#
$(TARGET): * **/*
#echo "TARGET=$(TARGET)"
Where this does?
TARGET=my_target
$(TARGET): * **/*
#echo "TARGET=$(TARGET)"
When started with make my_target?
Result of the former is, "no rule to make target `my_target'."
In addition to the question "why this doesn't work," is there a workaround? I'd like to be able to specify an arbitrary target from the command line. I suppose I could react to an env var, but that makes the CLI clunky, e.g., make target=my_target build or similar.
I've searched, but I'm not getting the right hits to solve this. GNU make 3.81. Thanks!
The automatic variable $# is defined in the context of a pattern rule; outside of any rule it has no value.
If you want Make to do the same thing to whatever target you name, you can use a match-anything rule:
%:
#echo TARGET=$#

How can a CMake variable be hidden?

I have a CMake project which lets a globally set variable (set with -DARDUINO_SDK_PATH=/a/b/c on command line) disappear i.e. suddenly the given value is gone which leads to a fatal error.
I know there are different ways to "hide" a variable (e.g. inside functions or external projects)
In my case:
the variable is not being set explicitly anywhere in the code (e.g. via set() or find_path())
the access which leads to the error is on top level (i.e. not inside a function)
there are instructions (i.e. same file/line) where in one case the variable has the value it's been given and the next time it's gone
Tracing the variable with variable_watch(ARDUINO_SDK_PATH) I can see that everything works fine before the compiler is being checked:
cmake -DARDUINO_SDK_PATH=/a/b/c <path>
...
... everything fine, ${DARDUINO_SDK_PATH} == '/a/b/c' everywhere
...
-- Check for working C compiler: /usr/bin/avr-gcc
...
... here the variable is empty and not being traced any more
...
Here is my suggestion:
Does the compiler check (indicated by check for working C compiler .. on the terminal) have it's own variable space and does not know variables provided on command line?
Note: This question is a generalization of this question, which has become way too specialized but might offer some useful background information.
That any modification to variable is not traced after the variable_watch() command seems like a bug somewhere in CMake to me.
Generally speaking a "cached CMake variable" can be hidden by a "normal CMake variable" with the same name. But e.g. find_path() won't run again or modify a variable if already set.
Here is an example:
cmake_minimum_required(VERSION 2.4)
project(VariableWatchTest NONE)
variable_watch(MY_TEST_VAR)
set(MY_TEST_VAR "something" CACHE INTERNAL "")
message("${MY_TEST_VAR}")
set(MY_TEST_VAR "hiding something")
message("${MY_TEST_VAR}")
unset(MY_TEST_VAR)
message("${MY_TEST_VAR}")
find_path(MY_TEST_VAR NAMES "CMakeLists.txt" HINTS "${CMAKE_CURRENT_LIST_DIR}")
message("${MY_TEST_VAR}")
Would give (without the variable_watch() messages:
-- something
-- hiding something
-- something
-- something
References
What's the CMake syntax to set and use variables?
I'm not sure whether this is a bug or a feature but (at least some) CMake variables are not available in certain steps of the CMake configuration procedure.
You can check this by adding something like this to your toolchain file:
MESSAGE("FOO: ${FOO}")
and run CMake like this
cd build-dir
cmake -DFOO=TEST ..
You will likely see FOO printed with value TEST once in the beginning of the configuration process and later printed again but being empty.
Just don't access variables from the global space inside a toolchain file (doesn't belong there anyway).

check_library_exists not works as it should

In CMakeLists.txt I write:
INCLUDE(CheckLibraryExists)
check_library_exists("libcurl" "" "" HAVE_CURL)
HAVE_CURL is always false, even if libcurl installed, and this function not causes fatal errors.
To check why a a try-compile fails, you can run CMake with the --debug-trycompile option, which will leave behind the buildsystem for the last try_compile command (these are used internally by all the Check... modules).
I didn't run the check, but I looked at the code of CheckLibraryExists, and it is apparently mandatory to specify a function to look for in that library (the second argument to check_library_exists).

In CMake, have the Makefile not print anything if no actions were actually taken

I use CMake in my project. Often I run a make before firing a test script, so that if the code has changed I don't test an outdated binary. If I see lines about compiling or linking etc I know something has changed. But if nothing has changed, I still see:
[100%] Built target foo
And I would really rather not see that at all. I mean, I don't want a silent build altogether - just in case no actions are necessary. How can I do that?
PS - Here's the result of make -rRd | grep 'Must remake':
Must remake target 'cmake_check_build_system'.
Must remake target 'all'.
Must remake target 'CMakeFiles/tester.dir/all'.
Must remake target 'CMakeFiles/tester.dir/depend'.
Must remake target 'CMakeFiles/tester.dir/build'.
Must remake target 'all'.
Must remake target 'default_target'.
but nothing is actually done.
I use the following
make2() {
# Exclude any output that contains 'Built target'
make $# | grep -v 'Built target';
echo '-'
}
Then
make2 my_target_generated_by_cmake

How to make Emacs byte-compilation warnings errors

In my continuous integration testing for my emacs package fsharp-mode, I am adding byte-compilation to the tests, in order to have immediate feedback. I am roughly using:
emasc -batch batch-byte-compile *.el
This returns non-zero if there is an error, but not if it is just a warning. I would like to be alerted also if there are any warnings, as this may include calls to undefined functions (which has happened before thanks to a typo).
So: how can I obtain a non-zero return code in case of compilation warnings?
You can set byte-compile-error-on-warn to a non-nil value, as in:
$ emacs -Q --batch \
--eval '(setq byte-compile-error-on-warn t)' \
-f batch-byte-compile *.el
The byte compiler now stops at the first warning, though, so you should make this setting optional in your Makefile, and only use it in your CI setup.
If you need more sophisticated control than that, you have to write your own post-processor, e.g. a Python script that parses the output of the byte compiler and adjusts the exit code and/or output accordingly, or write your own batch-byte-compile variant that does more sophisticated processing.