Highlight warning message in makefile - makefile

I have some code looks like below in Makefile.
ifeq ($(COMPARISON_NODE_VERSION),-1)
$(warning Please update your nodejs version to $(ENV_NODE_VERSION), or it may cause unexpected error later.)
endif
is there any chance to change the color of msg, like yellow?

Make cannot do that, but you can do it yourself if you want, by embedding color code sequences into the message text. It might be kind of gross to look at in the makefile though (you have to use the actual codes: make doesn't do any translation of character codes).

Related

gcc: warn if macro was redefined (regardless of previous definition)

gcc's manual says the following:
If a macro is redefined with a definition that is not effectively the same as the old one, the preprocessor issues a warning and changes the macro to use the new definition. If the new definition is effectively the same, the redefinition is silently ignored. This allows, for instance, two different headers to define a common macro. The preprocessor will only complain if the definitions do not match.
(emphasis mine)
Is there a way to make gcc more strict and issue a warning when a macro is redefined, regardless of definition?
Example:
#define TEST 1
#define TEST 1
int main(void) {
return 0;
}
Compiling with gcc -Wall -Wextra -Wpedantic does not generate any warning whatsoever.
Techincally speaking, if a header defines an apple as being red, then another wants to make sure everybody knows the apple is red, this should not be an issue. This is the reason behind it. And also to not compromise linking between multiple libraries if they have the same macro definition and the same value.
some h/hxx/hpp header
#define apples red
It's the usual attitude when you see some people wanting to make sure everyone knows they know (we all have these friends or co-workers, don't we? :) ) that apples are red so they state the obvious.
Preprocessor definitions are "compiled" (so-to-speak, rather said, interpreted and replaced or evaluated accordingly) at, well, compile-time. So having the same token defined multiple times is no real overhead on the app, it might just add a bit of compilation time.
The problem is when some wise-guy wants to let you know apples can also be green.
some other h/hxx/hpp header
#define apples green
Then, when you need to use some apples, you end up with:
some c/cxx/cpp file
#include "some_header.h/hxx/hpp"
#include "some_other_header.h/hxx/hpp"
And you end up with "apples " redefined.
Putting aside the daunting task of seeing where the conflict comes from (usually when combining multiple third-party libs/framerworks that might use similar names in macros or have the same acronyms prefixing a macro), this should be enough for you to know there is a conflict.
Keep in mind, this is a warning, so it will not stop the compilation. To treat warnings as errors, use -Werror.
I wouldn't worry about duplicate definitions, to be honest. They won't harm the code. If you really wanna go overkill-mode, you can always do some testing:
#if defined(apples) ...
... or ...
#ifdef apples ...

How to force VSCode to ignore linting the next line of golang code?

I like my code to look clean. I try to follow recommendations, etc. It helps keep everything tidy, conforming, and decent.
But sometimes, you need to defeat the linter because it has a bug, or it just doesn't understand what you intend.
In this case, I have the following code:
fmt.Println("Enter values between %00 and %0f.")
VSCode complains with:
fmt.Println call has possible formatting directive %0f (printf)
That's a reasonable thing for it to think, and I thank it very much for warning me of a possible mistake I might have made... but in this specific case, I really do want it to print %0f as-is. I really, really know what I'm doing here.
Normally, I might do something like this:
//lint:ignore printf No, really, this is what I want
fmt.Println("Enter values between %00 and %0f.")
But VSCode still gives the yellow wavy line and completely ignores the lint:ignore directive.
I must work around this annoyance with:
fmt.Printf("Enter values between %%00 and %%0f.\n")
But I'd prefer to use the original syntax, as the intent is clearer, and the line matches what I've written everywhere else in this part of the overall code.
So, how do I put my foot down and freaking tell the cursed program to stop placing its errant yellow wavy line because, dammit, I really do know what the I'm doing? It is not only distracting, but it wastes my time as I keep looking over the 'linting error' only to see it's not an issue.
Edit
Some additional information might be useful.
In my desire to keep things as uncomplicated as reasonably possible, I use the 'Go' extension, with no changes to the linter it defaults to using.
Examining these settings, it looks like it's using staticcheck. And, indeed, I see that in the local bin folder.
But staticcheck doesn't care. It doesn't complain at all about the fmt.Println() I wrote, even if I don't have a //lint:ignore line above it, when I run it explicitly.

Is it legal to override target in Makefile by order in a file?

I have a Makefile:
.PHONY: all
all: target1
target1:
$(info "target1")
target1:
$(info "target1 override")
If to execute "make" from a bash it will respond:
$ make
Makefile:8: warning: overriding recipe for target 'target1'
Makefile:5: warning: ignoring old recipe for target 'target1'
"target1 override"
make: Nothing to be done for 'all'.
This behavior is expected by me, because I expect that the latest definition of the target will be taken by Makefile's parser.
Is it legal to expect that the latest rule from the Makefile will be taken if the rule is overridden?
Is it possible to get rid of warnings?
P.S. Also I have tried answers from another StackOverflow's questions like the use of "override" keyword and "::" symbols. It doesn't help (errors and the same warnings from Makefile appears).
Is it legal to expect that the latest rule from the Makefile will be
taken if the rule is overridden?
A makefile that contains multiple target rules that provide recipes for the same target violates the POSIX specifications for make:
Only one target rule for any given target can contain commands.
Violating that will not bring the police down on you, but it may, rightfully, bring down the wrath of other developers and managers who have to work with your code, now or later. Implementations of make are not bound by the spec to any particular behavior when a makefile containing such multiple recipes is presented.
The diagnostic messages you present and the behavior you describe appear characteristic of GNU make. To the extent that you are willing to be dependent on that particular make implementation, it would be reasonable to rely on section 4.11 of its manual, which says:
There can only be one recipe to be executed for a file. If more than
one rule gives a recipe for the same file, make uses the last one
given and prints an error message.*
(Footnote mine.) But reliance on that renders your makefile non-portable. Other make implementations might instead reject the makefile, choose the first recipe, choose a random recipe, choose all matching recipes in some order, or exhibit any manner of obvious or non-obvious breakage. Alerting you to that is the purpose of the message.
Is it possible to get rid of warnings?
Continuing to assume GNU make, the manual says definitively that a diagnostic will be emitted, and its summary of command-line options does not describe any that I would expect to suppress the output in question without also suppressing the actual build.
Bottom line
The question conveys the impression that you think the usage described ought to be acceptable, so that the diagnostic is merely a nuisance. This is not the case. Such usage is poor style, at least, and it can present genuine problems for yourself and others. Whatever you're trying to accomplish that way, there are better alternatives.
*It's referring to target rules. Suffix and pattern rules that match the target are a different matter.

Are there any practical reasons to use `-include` in a Makefile?

I was recently debugging a vague problem which turned out to be caused by a misplaced sub-Makefile which was conditionally included into a main Makefile by the -include directive. Mind the starting minus sign. According to GNU Make manual:
If you want make to simply ignore a makefile which does not exist or
cannot be remade, with no error message, use the -include directive
instead of include, like this:
-include filenames…
This acts like include in every way except that there is no error (not
even a warning) if any of the filenames (or any prerequisites of any
of the filenames) do not exist or cannot be remade.
For compatibility with some other make implementations, sinclude is
another name for -include.
The nastiest problem with this directive is that no diagnostics whatsoever are given when the sub-Makefile cannot be found. Needless to say, this complicates debugging a lot.
In fact, there was no real need to use it there, a regular include worked just fine and is much more robust. I understand the original author's intention for using -include. That sub-Makefile contained some "secret" stuff that was not meant to be shared with 3rd party engineers. But this functionality was never used in the end, and it could have been implemented in a more transparent way.
I wonder if there are other practical cases when -include is useful. Maybe some cases when one or several makefiles are dynamically generated during the build process?
Surely, the most useful application of -include is when the include file is auto-generated by make itself.
Remember that all include files also become make's targets automatically. So -include generated_file does not make make to fail prematurely, but implies that generated_file will be (re-)built using other rules in the current Makefile. This can be exploited in auto-dependencies generation, for example.
BTW. Another trick with 'include' is that include $(empty_var) also works without errors (i.e. is no-op).

Deal with MAKEFILE_LIST spaces on windows

I would like to get the makefiles list in a cross-platform way.
However on Windows, MAKEFILE_LIST doesn't support well spaces (not protected):
$(warning MAKEFILE_LIST=$(MAKEFILE_LIST))
Give the following result (because the Makefile is included in another):
MAKEFILE_LIST= Makefile C:/Program Files/MyApp/Makefile.include
The make string operations are not powerful enough to deal with that, and the regular way to get the top Makefile don't work:
THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST))
returns obviously this corrupted result (because lastword is based on spaces):
THIS_MAKEFILE=Files/MyApp/Makefile.include
Any solution to fix that cleanly (meaning using make functions or system commands calls)?
The basic answer is that make does not support filenames with whitespace in them. Some very limited use can be successful in some very limited situations, if you're willing to do a lot of extra work. MAKEFILE_LIST is not one of those limited situations.
It's simplest to just treat pathnames containing whitespace as not supported. Just don't do it.

Resources