I am developing a program in C that needs to include the date and the time of the last push performed in a given branch in the git repository in order to version it.
I know how I can get the data from git and use it to generate a version number in the format I want.
(https://stackoverflow.com/a/51403241/7114946)
The problem is I don't know how to include this within the code of the program because it ultimately needs to "printf" this info during the starting of the app.
I have found the preprocessor macros __TIME__ and __DATE__. I wonder if there are other similar macros to include some given string/data.
Thanks
edit: I need to include this info in compilation time, not when the code is uploaded into git.
You can define macros on the command line:
gcc -DFOO=BAR -c prog.c
acts like #define FOO BAR in prog.c.
You can combine this with shell command interpolation to get the output of an external program in there:
gcc -DGIT_TIMESTAMP="\"$(git whateveryourcommandis)\"" prog.c
(The escaped quotes are there to make the macro expand to a string literal.)
And then prog.c can do e.g.:
printf("my git timestamp is %s\n", GIT_TIMESTAMP);
Related
I have an AVR8 GCC application that can be built with a standard makefile. Because some folks who want to build the application don't want to set up make and such (or have trouble doing so), I also have figured out how to set the project up so it can be compiled from the Arduino IDE as well.
All is working.
But, I normally set some items in the makefile, like the version number and such, but creating the VERSION string in the makefile and passing it as a define into each source file compilation. But, when run from the Arduino IDE, that step is obviously not occurring. So, I have to create a second #define in the Arduino sketch stub to recreate the define.
This means when I update the version, I need to do so in 2 places, in the makefile and in the source file.
The easy option is to simply move the VERSION creation to the source file, where both can use it. And, I'm OK doing that, but
The makefile actually needs the version information, both to create the right filename (think app_v1.2.3.4.bin) and embed the version number into the bin file since it is used by the boot-loader (if requested) to ensure the version the boot-loader flashes is newer than the one already in FLASH. So, if I move the VERSION, RELEASE, MODIFICATION, etc. defines into the C code, I need to find a way to pull them back into the makefile.
I tried using the file read operations in the makefile, but they seem to ignore:
#define VERSION 0
with the prefaced '#' char.
I see there's some options to run sed/awk/etc, in bash, but I don't want to make too many assumptions on the environment, and the makefile currently runs on Windows as well as Unix/Linux without any differences.
I tried a few stack overflow examples, but nothing seems to yield those 4 numbers from any file, .h or otherwise.
I'm OK with creating version.h with just:
#define VERSION 0
#define RELEASE 1
#define MODIFICATION 2
#define FIX 4
If I can read it into the makefile and create the variables I need.
Jim
You may take a look at gmtt which was designed exactly with you use case in mind. In gmtt the following should read and analyze your header file:
include gmtt.mk
# create a 3-column table from the header file. The first column is just the "#define"
VNR_TABLE := 3 $(file < version.h)
# Extract the values from the table: select column 3 from VNR_TABLE where column 2 equals a string constant.
# Be careful not to introduce spaces in the compare!
VER := $(call select,3,$(VNR_TABLE),$$(call str-eq,$$2,VERSION))
REL := $(call select,3,$(VNR_TABLE),$$(call str-eq,$$2,RELEASE))
MODF := $(call select,3,$(VNR_TABLE),$$(call str-eq,$$2,MODIFICATION))
FIX := $(call select,3,$(VNR_TABLE),$$(call str-eq,$$2,FIX))
I couldn't test it but I think you get the idea.
PS: using a GNUmake library just means placing the included file alongside the makefile.
I think in this case you can use the ‘file’ function of makefiles.
It allows you to write (with > specifier) or read (with < specifier) to/from files. Then you can trim (with filter-out) your variables inside your makefile.
Source: https://www.gnu.org/software/make/manual/html_node/File-Function.html#File-Function
You can use GNU make's $(shell ...) function to extract the macro expansions. Assuming VERSION is defined in src.c and tokens are delimited by spaces (not tabs):
VERSION := $(shell sed -n -e "s/^\#define VERSION *\(.*\)/\1/p" src.c)
.PHONY: all
all:
#echo VERSION=$(VERSION)
I am attempting to build a project that comes with an automake/autoconf build system. This is a well-used project, so I'm skeptical about a problem with the configure scripts, makefiles, or code as I received them. It is likely some kind of environment, path, flag, etc problem - something on my end with simply running the right commands with the right parameters.
The configuration step seems to complete in a satisfactory way. When I run make, I'm shown a set of errors primarily of these types:
error: ‘TRUE’ undeclared here (not in a function)
error: ‘struct work’ has no member named ‘version’
error: expected ‘)’ before ‘PRIu64’
Let's focus on the last one, which I have spent time researching - and I suspect all the errors are related to missing definitions. Apparently the print-friendly extended definitions from the C standard library header file inttypes.h is not being found. However, in the configure step everything is claimed to be in order:
configure:4930: checking for inttypes.h
configure:4930: /usr/bin/x86_64-linux-gnu-gcc -c -g -O2 conftest.c >&5
configure:4930: $? = 0
configure:4930: result: yes
All the INTTYPES flags are set correctly if I look in confdefs.h, config.h, config.log Output Variables, etc:
HAVE_INTTYPES_H='1'
#define HAVE_INTTYPES_H 1
The problem is the same whether doing a native build, or cross-compiling (for arm-linux-gnueabihf, aka armhf).
The source .c file in question does have config.h included as you'd expect, which by my understanding via the m4 macros mechanic should be adding an
#include <inttypes.h>
line. Yes, as you may be inclined to ask, if I enter this line myself into the .c file it appears to work and the PRIu64 errors go away.
I'm left with wondering how to debug this type of problem - essentially, everything I am aware of tells me I've done the configure properly, but I'm left with a bogus make process. Aside from trying every ./configure tweak and trick I can find, I've started looking at the auto-generated Makefile.in itself, but nothing so far. Also looking into how I can get the C pre-processor to tell me which header files it's actually inserting.
EDIT: I've confirmed that the -DHAVE_CONFIG_H mechanic looks good through configure, config.log, Makefile, etc.
autoconf does not automatically produce #include directives. You need to do that on your own based on the HAVE_* macros. So you'll have to add something like this:
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
If these lines show up in confdefs.h, a temporary header file used by configure scripts, this does excuse your application from performing these #includes. If configure writes them to confdefs.h, this is solely for the benefit of other configure tests, and not for application use.
First, run make -n for the target that failed. This is probably some .o file; you may need some tweaking to get its path correctly.
Now you have the command used to compile your file. If you don't find the problem by meditating on this command, try to run it, adding the -E to force preprocessor output text instead of invoking the compiler.
Note that now the .o file will be text, and you must rebuild it without -E later.
You may find some preprocessor flags useful to get more details: -dM or -dD, or others.
I'm trying to debug some additions I made to a fairly large c program using gdb. The program I'm trying to debug makes extensive use of #define statements to set different values that are used throughout the code. I need to be able to see what these values are in order to help my debugging (as they include some very important information.
After some digging around I found that the info macro FOO and macro expand FOO commands should be able to print these values if the -g3 option (also tried the -gdwarf-2 and -ggdb3 flags as well) is passed to the compiler (as discussed here). However, whenever I try using this I get
The symbol `FOO' has no definition as a C/C++ preprocessor macro
at <user-defined>:-1
Now, I'm sure that the macro is defined otherwise the previous line of code would not have been able to run. In addition, I'm certain that I have passed the -g3 flag to the compiler. I have one idea as to where the issue might be and that is the location that the macro is defined at. Currently the macro is defined in a header file that is not in the same directory as the rest of the files (i.e. if the source files are in /foo/bar/blam/.. then the macro is defined in /def/mac/here/. Given this I thought maybe the problem was that gdb didn't know to look in this directory so I tried issuing the directory command in gdb and gave it the path to the directory containing the header file (base on this). This still did not solve the problem.
Does anyone know how I can get the values of these macros? If it is pertinent I'm running gdb version 7.11 and compiling the program using
cc and gcc both with Apple LLVM version 7.0.2 (clang-700.1.81). Also, gdb was installed/built using homebrew.
I'm trying to use YCM for the first time so in order to make it work I decided to give a chance for the YCM-Generator, which generates the .ycm_extra_conf.py file automatically based on the makefile.
So far my program is just a simple hello world.
#include <stdio.h>
int main()
{
printf("Hello World!");
return 0;
}
I'm using the CMakeLists.txt trick to generate the makefile.
file(GLOB sources *.h *.c)
add_executable(Foo ${sources})
then after executing the YCM-Generator script, I get this output
Running cmake in '/tmp/tmp_YknVy'... $ cmake
/home/pedro/Desktop/Projetos/teste
Running make... $ make -i -j4
Cleaning up...
Build completed in 1.5 sec
Collected 2 relevant entries for C compilation (0 discarded).
Collected 0 relevant entries for C++ compilation (0 discarded).
Created YCM config file with 0 C flags
YCM plugin does find the .ycm_extra_conf.py file, but the auto-completion doesn't work right, for example, if I type "floa", it doesn't suggests "float", but It only suggests things that I used before like "int" or "printf".
Am I missing something or this is working as intended?
So I fixed it.
For c it does require a .ycm_extra_conf.py , while a friend of mine could make it work without one in c++.
The auto complete only suggest automatically functions that were previously used, if you don't remember a function name you have to press <Ctrl-Space>
YCM-Generator didn't do the job, so I modified the example file myself following the comments.
If you are used to Visual Assist, the auto complete works but it's really weak if compared to VA, which is a shame... I really hope someone port that plugin to Linux.
I'm writing an implementation of the C preprocessor that, when running on Linux, needs to know the path on which to find header files. This can be obtained by running gcc -v. I want to compile the results into the binary of my preprocessor rather than having to invoke gcc -v on every run, so I'm currently thinking of writing a Python script to be run at compile time, that would obtain the path and write it into a small C source file to be included in the build.
On the other hand, I get the impression GNU Autotools is basically the specialist in obtaining system-specific information to be used at build time. Does Autotools have the ability to obtain the #include path in such a way that it can be incorporated as a string into the program being built (as opposed to being used for the build process)? If so, how?
If you want to get the internal include/ directory used by GCC, run the gcc -print-file-name=include command, e.g. in shell syntax
the_gcc_include_dir=$(gcc -print-file-name=include)
This $the_gcc_include_dirdirectory contains files like <stdarg.h> and <stddef.h> and many others.
You also want the include-fixed/ directory, so
the_gcc_include_fixed_dir=$(gcc -print-file-name=include-fixed)
This $the_gcc_include_fixed_dir contains files like <limits.h> and also a useful README
You probably don't need autotools in your case.
I ended up parsing gcc's include path with a Python script:
print 'string gcc_include_path[] = {'
for s in sys.stdin:
if s[0] == ' ':
s = s.strip()
print '\t"'+s+'",'
print '};'
and calling it from Makefile:
echo | cpp -Wp,-v 2>&1 >/dev/null | python include_path.py >include_path