2024-04-26 12:12 AM
Hi,
I want to automatically add the following line of code at the top of each source file within my project:
static char const thisFile[] = __FILE__;
For this, I'm creating the following Define symbol (-D) in STM32CubeIDE, by going to project Properties -> C/C++ Build -> Settings -> Tool Settings -> MCU GCC Assembler -> Preprocessor:
However, when I click on OK -> Apply and Close, it shows this warning, which I don't completely understand.
Anyway, I click Rebuild Index, and it changes my symbol by removing the semicolon at the end and adding some new double quote symbol "
and, when I build the project after this (the code already uses thisFile string in its functions), it throws this error:
error: 'thisFile' undeclared (first use in this function)
I suspect, that it happens because the preprocessor can't properly transform the semicolon from my symbol, so the whole static char const thisFile[] = __FILE__ line becomes invalid.
Is there a way how to make this Define symbol (-D) feature to work with semicolons or maybe some other way how to add my desired line of code at the top of each source file?
Solved! Go to Solution.
2024-04-26 03:19 AM - edited 2024-04-26 03:23 AM
__FILE_NAME__
Takes less space then __FILE__. It doesn't have the full path only filename and extension. It is not standard, but it works in GCC.
The compiler is smart enough not to create duplicates of strings in FLASH so even if you use string literals in different places in one file it won't be duplicated. Unless you concatenate the strings, because those are seen as new ones. Strings are passed by address, not by copy.
You can use the -E parameter to get the intermediate files (main.o becomes a readable text file, for instance). It will result in compiler errors, but you can see what the preprocessor outputs. You can see that __FILE_NAME__ gets expanded to "main.c" and the compiler will store that in 1 place in FLASH.
2024-04-26 03:21 AM
@unsigned_char_array wrote:global.h:
#ifndef GLOBAL_H_
#define GLOBAL_H_
#define thisFile __FILE__
#endif // GLOBAL_H_
And in my main.c:
SerialDebug("%s\r\n", thisFile);
But that would be equivalent to writing
SerialDebug( "%s\r\n", __FILE__ );
which would, indeed, cause the __FILE__ macro to be expanded each time it is used.
Surely, what you really want is:
#ifndef GLOBAL_H_
#define GLOBAL_H_
static char thisFile[] = __FILE__;
#endif // GLOBAL_H_
so that you create one variable per file, where the macro is expanded.
and then .c files can do
SerialDebug( "%s\r\n", thisFile );
to just reference the file-local variable without re-expanding the __FILE__ macro
2024-04-26 03:25 AM - edited 2024-04-26 03:32 AM
@unsigned_char_array wrote:The compiler is smart enough not to create duplicates of strings in FLASH so even if you use string literals in different places in one file it won't be duplicated.
This is controlled by the -fmerge-constants option:
EDIT:
The link highlighting doesn't seem to have worked there. :frowning_face:
Try this :https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fmerge-constants
and note that there's also a -fmerge-all-constants - with some caveats ...
2024-04-26 03:30 AM
@Andrew Neil wrote:Surely, what you really want is:
#ifndef GLOBAL_H_
#define GLOBAL_H_
static char thisFile[] = __FILE__;
#endif // GLOBAL_H_
Yes, but in that case it expands to "path/global.h" and not to "path/main.c".
2024-04-26 03:50 AM
Of course!
<facepalm>
2024-04-26 07:02 AM - edited 2024-04-29 01:25 AM
I've solved it.
Modify build command in STM32CubeIDE:
from:
${COMMAND} ${INPUTS} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT}
to:
${COMMAND} ${INPUTS} -D__CFILE__='${INPUTS}' ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT}
for the equivalent of __FILE__
or even better:
${COMMAND} ${INPUTS} -D__CFILE__='"${InputFileName}"' ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT}
for the equivalent of __FILE_NAME__
or
${COMMAND} ${INPUTS} -D__CFILE__='"${InputFileBaseName}"' ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT}
for the equivalent of __BASE_FILE__
Inside a header file the macro __CFILE__ will have not expand to the path of the header file being processed, but to the path to the C file that includes the header file.
Combine this with with -include global.h in misc and with global.h containing:
static char thisFile[] = __CFILE__;
Now it works. This does not work with __FILE__ or __FILE_NAME__ as those will expand to the path or name of the header file.
Like I wrote before it is not going to save memory in any way (please measure memory use by checking build analysis and map file and check where all string literals are stored to verify).
(I also found a way to define the project name, can also be useful: -DPROJECT_NAME='"${ProjName}"')
2024-04-26 01:15 PM
Just use the __BASE_FILE__ macro instead of __FILE__ ?
https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html#Common-Predefined-Macros