I am building a build system and have .c file which contains version string. const char version[] = "V01.00.00";
I need to get that line by regex into make variable to use for further binary making.
Can you suggest the best way to do that? Would appreciate native make solution.
It's a bad idea to try to parse .c files by yourself to extract information from them. Only the C compiler, for example gcc should be used to parse .c files. You should not be doing it, leave it to the compiler.
The reason is, that if someone changes the .c file you extracted information from, your extraction code is likely to break. Basically, your extraction code would have to be compatible with any .c syntax, which means, you would end up to be a "compiler".
Otherwise, you would have to publish some documentation for other programmers, to tell them to keep the .c code the way you want it, for your code not to break. So you would end up restricting the C language for them.
If you want to get such information:
define a function in the .c file to return that information
compile that file to a library
make an executable that links with the library and calls that function
call that executable from the Makefile
Related
I want to use Sconstruct instead of Makefile. But I found that many situations in the Makefile are difficult to implement in Sconstruct.
For example,
I have three .c files, a.c, b.c, and c.c. I want to decide which file to compile into the final file based on the input. In Makefile I can use make a, make b, make c to achieve. But in sconstruct, scons e decides which statement to execute based on the final target file. Is there a way to decide which statement to execute based on the source file or a lable?
Sometimes in the Makefile, I want to compile multiple files at once, but not all files. In the Makefile, I can write the compilation of multiple files under one label. Is there such a method in Sconstruct?
I found a lot of documents about sconstruct on the Internet, but basically every document introduces the most basic commands.
Possibly not understanding all of the question, but SCons, builds the targets you ask it to on the command line, like Make does. If you don't give it any, it builds the default targets, which you yourself can define through Default() calls. If neither, then it builds ".", which means all of the targets discovered underneath the directory of the SConstruct.
Targets don't have to be the name of a file to build, you can use the Alias() function to assign a name that will work as a build target. An alias can refer to several targets if you wish, which seems to be your second question.
Feel free to hop onto the SCons Discord channel if you want to chat more interactively (see https://scons.org/contact.html for links)
I have been trying to debug a makefile.am that occasionally causes a build failure in make. In this file, the sources are auto generated .c files and the headers are auto generated .h files.
..._SOURCES = #buildDirectory#/x.c
#buildDirectory#/y.c
#buildDirectory#/z.c
..._HEADERS = #buildDirectory#/x.h
#buildDirectory#/y.h
#buildDirectory#/z.h
The failure looks like this
<failedproto>.proto: "symbol1" is not defined.
<failedproto>.proto: "symbol2" is not defined.
<failedproto>.proto: "symbol3" is not defined.
...
<failedproto>.proto: warning: Import <failedproto>.proto but not used.
make: *** [<failedproto>.c] Error 1
make: *** Waiting for unfinished jobs....
All of these symbols appear in the a corresponding .h. This leads me to think that the .c is being generated before the .h, and its just a straight race. I have added both ..._SOURCES and _HEADERS to BUILT_SOURCES, but I still see the failure. So my next instinct is to create a dependency for the .c on the .h. How do I do this, since they are both auto generated? Also, any alternative solutions would be welcome too.
Hopefully my formatting is not confusing.
Edit with some more detail:
These files are being auto generated by the protoc-c compiler: https://github.com/protobuf-c/protobuf-c
The protoc-c takes these .proto files and generates .pb-c.c and .pb-c.h files, making me think that these two are not dependent after all. Some in house code is also run, which generates other .proto files, I will call them nameX.proto and nameY.proto, which in turn generate nameX.pb-c.c/nameX.pb-c.h and nameY.pb-c.c/nameY.pb-c.h. A more accurate example of the Makefile.am is like this:
..._SOURCES = #buildDirectory#/name.pb-c.c
#buildDirectory#/nameX.pb-c.c
#buildDirectory#/nameY.pb-c.c
..._HEADERS = #buildDirectory#/name.pb-c.h
#buildDirectory#/nameX.pb-c.h
#buildDirectory#/nameY.pb-c.h
I have been trying to track these dependencies, and I will try and describe what conclusions I have come to. nameX.pb-c.c includes its corresponding header nameX.pb-c.h. That header includes nameY.pb-c.h, making me think that nameX.proto is being compiled into nameX.pb-c.c/nameX.pb-c.h before nameY.proto can be compiled. Since there is an include relationship between nameX.pb-c.h and nameY.pb-c.h, the build fails because nameX.pb-c.h needs nameY.pb-c.h. This leads me to two rules I've been suspicious about from the start. These rules are generalized like this:
$(OUT_DIRECTORY)/%nameX.proto:$(SRC_DIRECTORY)/name.proto $(SRC_DIRECTORY)/nameY.proto
command $(OUT_DIRECTORY) $(FLAGS) $<
$(OUT_DIRECTORY)/%nameX.proto:$(SRC_DIRECTORY)/name.proto
command $(OUT_DIRECTORY) $(FLAGS) $<
Could this be an issue? What is stopping the second rule from being run if it truly needs the first rule?
To make matters worse, many of the .proto files are intermediate files (they are generated then discarded throughout the build) so I cannot look at them to see what they look like.
It's very unusual to use #...# replacements throughout your makefile like this. Normally you would assign the replacement once, to a make variable, then use the variable instead (in addition to being "nicer to read", this allows someone to override this value on the make command line if they want to):
BUILDDIR = #buildDirectory#
..._SOURCES = $(BUILDDIR)/x.c
$(BUILDDIR)/y.c
$(BUILDDIR)/z.c
..._HEADERS = $(BUILDDIR)/x.h
$(BUILDDIR)/y.h
$(BUILDDIR)/z.h
Also, it seems likely to me that there are standard automake variables that might already cover this value; if so it's better to use the standard ones than invent new ones... but obviously there's no way to know that without knowing more about your environment.
Anyway, for your question we need to know more about this autogeneration operation. What do your rules for autogenerating look like now? Is it really the case that the generation of the .c file can't be done until the .h file is generated? That's unusual.
If you list the output file, the input files, and the command needed then it's pretty simple to write a correct rule.
I've recently discovered clang++'s static analyzer feature, and it's fantastic for going over my code with a fine-toothed comb to find latent bugs. I just uncomment this line in my Makefile:
CXXFLAGS += --analyze -Xanalyzer -analyzer-output=text
et voila, I'm in deep-bug-checking mode.
One minor problem with this, however, is that whenever the analyzer does not find any problems in a particular .cpp file, doesn't produce any .o file.
Normally that wouldn't be a big deal (I can always re-comment the above line to build an actual executable), but usually when I see an analyzer-warning, the first thing I want to do is try to fix the underlying problem and then re-run make.
... which works, but since no .o files are being generated, make will start re-analyzing all the .cpp files again from the beginning, rather than just the .cpp files I actually modified since the previous run. This means I end up spending rather a lot of time re-checking .cpp files that haven't changed.
My question is, is there any way to get the static analyzer to output a .o file (it doesn't have to be a valid object file, just any file with an updated timestamp) so that Make will know that a "clean" .cpp file does not need to be re-processed? (i.e. make Make work the same way it does when doing a normal compile)
Check out the clang static analyzer page, and get the package there for download. You can use the included scan-build tool to do what you're trying.
The normal way to use is to get rid of the flags you have above and just run:
$ scan-build make whatever
And it should 'just work'. You might need to pass some more flags or set some environment variables if you don't use standard make variable names.
Strange thing happening:
The idea of the makefile is to be able to compile several files at the same time. If you edit one of those files, when you type make, the only file that should compile is the one that was edited.
Now, for some reason, my makefile has decided to stop recognizing when the file has changed. So I have to: make clean and the make again to be able to compile, which is ridiculous since each time I have to compile takes about 1 minute.
Any ideas why this is happening?
I didn't add anything to my makefile; it just started doing that out of nowhere.
Something changed; programs don't stop working unless something changed. The difficulty is going to be working out what changed. You can always just type:
rm file-that-changed.o
make
to rebuild just the one file that changed, but that's a nuisance.
Is there a multi-step compilation and you have an intermediate file lying around that is confusing make?
I just had a mix up in a multi-step compilation.
If you have a non-standard file suffix that you compile into C code, and then from C into object code (or any other similar multi-step compilation), then the key to getting reliable recompilation with make is to organize the suffix list so that your extensions come at the start. Unfortunately, there isn't a standard easy way to know what the built-in suffix list is, so you end up having to do something like this:
SUFFIXES = .y .l .c .o # Yacc, Lex, C, Object files
EXTRA_SUFFIX = .xc # Extreme C, or Extended C, or ...
.SUFFIXES: # Eliminate all built-in suffixes
.SUFFIXES: ${EXTRA_SUFFIX} ${SUFFIXES}
The second .SUFFIXES line puts your extension at the front of the list. Now you can write your rules to compile your .xc file into a .c or .o file, and then when you modify the .xc file, even if there's an intermediate .c file left around, the fact that the .xc is newer than the .c or .o file will ensure that the recompilation is done.
Once upon a long time ago, the Sun version of make provided a macro called SUFFIXES which contained the default suffixes in the correct order. Sadly, that was not adopted and standardized, so you have to build the suffix list yourself. But the choice of macro name wasn't entirely accidental.
I need to be override certain macro definition by my header file. And I am not allowed to change source code. And I have to use gcc, but if anyone is aware of something similar on any other compiler then also it will help.
Here is what I exactly need:
Lets say I have code base with lot of .c files. These .c files include .h files. After all the .h files have been included for each file I want the compiler to behave as if I have another extra.h file which I want to specify when invoking the compiler. What I do in that .h file is #undef some macro and re-define the macro the way I want them to be.
Note: I am aware of --preinclude option in gcc, but using --preinclude over-rides my extra.h by the .h of the original source code. What I need is some kind of post include option.
Unless you uniformly have one specific header that is always included last in the source files, this is going to be tricky.
I think the way I'd approach it, if I had to, would be:
Create a new directory, call it headers.
Put in there suitable dummy headers with the same name as the regular headers, which would contain #include "extra.h" at the end (or possibly #include <extra.h>, but I would try to avoid that).
The dummy headers would also include the original files by some mechanism, possibly even using #include "/usr/include/header.h" but preferably some other technique - such as #include "include/header.".
The extra.h header would always redefine all its macros - it would not have the normal #ifndef EXTRA_H_INCLUDED / #define EXTRA_H_INCLUDED / #endif multiple inclusion guards, so that each time it is included, it would redefine the relevant macros.
Consequently, extra.h cannot define any types. (Or, more precisely, if it does, those must be protected against multiple definition by multiple include guards; the key point is that the macros must be defined each time the file is included - a bit like <assert.h>.)
Each redefined macro would be explicitly protected by #undef REDEFINED_MACRO and then #define REDEFINED_MACRO ....
There is no point in testing whether the macro is defined before undefining it.
The build process would be modified to look in the headers directory before looking anywhere else. The compiler option would be -I./headers or something similar, depending on exactly where you locate the headers directory.
Depending on how you have decided to locate the normal versions of the headers, you might need another -I option (such as -I/usr if you've used #include "include/header.h" notation) to locate the standard headers again.
The upshot is that your private headers get used directly by the compiler, but they include the standard headers and then your extra.h header - thus achieving what you wanted without modifying the C source or the normal headers.
But there is something misguided about the whole attempt...you would be better off not trying this.
Makefile could be used to redefine the macros through the -U and -D compiler(gcc) options. But why redefine them after the originals are evaluated? I cannot think of a need for such a thing. Can you tell what are you hoping to achieve through this?
The requirement is to insert extra.h after all the other .h files in a .c file. So adding it at the end of each .h file will insert it between two .h files included in sequence inside a .c file, which is not the intention.
You can use sed/awk inside makefile(s) to:
- first create duplicate .c files inserting '#include "extra.h"' after other #include lines inside each of the .c files (it will be tedious/ticky to resole #ifdef blocks inside the .c files)
- then achieve your target compiling those duplicate .c files
- finally delete the duplicate .c files
You can use
-include file option of GCC, because of this feature:
If multiple -include options are given, the files are included in the order they appear on the command line.
So as I understand you must include ALL *.h files from the command line,- just keep your "extra.h" the last header in -include option list and you should get what you want.
There are two ways I can think of doing this according to your requirements, and both should be relatively simple, I hope.
The first way does not touch the source code at all, however it requires that each header file you are #undef'ing things from has a header guard. You can copy and concatenate every header file that you need to "change" things in into one monolithic file, your "extra.h" file. Then at the end of that file, go ahead and redefine all the macros you need. Then include this file when you compile. The header guards will prevent the original headers from being included. Obviously, there are a number of potential problems with this approach, and it certainly wouldn't work in general.
The second way is a lot cleaner and more reliable, but it requires you to edit the code directly, albeit non-intrusively. For each header you need to redefine things in, make a copy of that header with an ".orig" suffix or something, then edit the actual header file directly. After you are all done doing whatever you are doing, then just copy all the ".orig" files back into the actual headers before your customers obtain the code. I assume your requirements aren't so draconian that you can't change the code even temporarily.
If none of that works, then I doubt you are going to find an effective answer from anybody short of hacking GCC directly and adding a "-postinclude" option yourself.