Skip to main content
Associate II
April 26, 2024
Solved

Use of Define symbols (-D) with the semicolon ";" sign in STM32CubeIDE

  • April 26, 2024
  • 8 replies
  • 7149 views

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:

pav_ivanovs_1-1714115156456.png

However, when I click on OK -> Apply and Close, it shows this warning, which I don't completely understand.

pav_ivanovs_1-1714114411877.png

Anyway, I click Rebuild Index, and it changes my symbol by removing the semicolon at the end and adding some new double quote symbol "

pav_ivanovs_2-1714115197413.png

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?

This topic has been closed for replies.
Best answer by unsigned_char_array

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}"')

8 replies

Guillaume K
ST Employee
April 26, 2024

@pav_ivanovs wrote:

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:

you are creating a #define for the "MCU GCC Assembler". do it in the "MCU GCC compiler" section instead.

Associate II
April 26, 2024

Ok, I've added the same symbol there, but the result is the same

pav_ivanovs_0-1714117206407.png

Guillaume K
ST Employee
April 26, 2024

Is there an error reported by compiler ?

I suggest to remove the double quotes. Especially the double quote that is on the second line.

In your C code, how do you use THIS_FILE__ ? I suggest to add a semi colon after THIS_FILE__ on a single line:

 

 

THIS_FILE__;

 

 

Try to find in the CDT build console what command line is really used ( "arm-none-eabi-gcc c:/path/to/file.c -DTHIS_FILE=...")

Associate II
April 26, 2024

ok, thanks, adding

THIS_FILE__;

at the top of source files helped, but my initial intention was to automatically add the

static char const thisFile[] = __FILE__;

line at the top of each source file. If I need to manually place THIS_FILE__; at the top of each source file, then it sort of defeats the purpose here. Is there a way to use the Define symbol (-D) feature or smth else to achieve what I want?

unsigned_char_array
Lead III
April 26, 2024

That's not how define works. A define creates a symbol that can be used for text substitution or conditional compilation. It's not designed to add code to a file. That's what include is for.

You can define the symbol like this:

unsigned_char_array_1-1714120663850.png

 

The index keeps track of all the symbols in the code, so you can navigate to declarations and definitions of variables and functions. If you change global symbols all files have to be recompiled and this potentially affects the index.

I have a better solution. Use the -include command to force include a file in all source files without modifying the files. You will need to create one header file.

 

unsigned_char_array_0-1714119848430.png

global.h:

 

 

 

 

 

 

#ifndef GLOBAL_H_
#define GLOBAL_H_

#define thisFile __FILE__

#endif // GLOBAL_H_

 

 

 

 

And in my main.c:

 

 

SerialDebug("%s\r\n", thisFile);

 

 

 

"Kudo posts if you have the same problem and kudo replies if the solution works.Click ""Accept as Solution"" if a reply solved your problem. If no solution was posted please answer with your own."
Andrew Neil
Super User
April 26, 2024

@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

 

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
unsigned_char_array
Lead III
April 26, 2024

@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".

"Kudo posts if you have the same problem and kudo replies if the solution works.Click ""Accept as Solution"" if a reply solved your problem. If no solution was posted please answer with your own."
Associate II
April 26, 2024

Thanks for advice, but unfortunately, it doesn't do exactly what I want. My initial purpose of adding the

 

static char const thisFile[] = __FILE__;

 

line at the top of each source file was to create a string that contains the file path only once per source file. The typical issue with debugging using the __FILE__ macro is that it expands to a long path string each time I write

SerialDebug("%s\r\n", thisFile);

and I might have a lot of such calls within a source file. So it basically, clogs up memory pretty quickly. The solution that I'm trying to implement is described here:
https://barrgroup.com/blog/design-contract-embedded-c#endnote2
but it relies on adding

DEFINE_THIS_FILE

macro at the top of each source file, which I would like to automate somehow.

unsigned_char_array
Lead III
April 26, 2024

@pav_ivanovs wrote:

I might have a lot of such calls within a source file. So it basically, clogs up memory pretty quickly.


No it doesn't. The string gets stored in FLASH only once and referenced multiple times. I just tested it. In memory viewer I see all the constant strings in FLASH and see my file name only once and the address of the string is the same for all function calls in the file. How did you measure your "memory clogging"?

"Kudo posts if you have the same problem and kudo replies if the solution works.Click ""Accept as Solution"" if a reply solved your problem. If no solution was posted please answer with your own."
Andrew Neil
Super User
April 26, 2024

@pav_ivanovs wrote:

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__;

file?


I don't see how a preprocessor definition helps this at all?

Surely, if you can automatically insert a preprocessor definition, then you could just as easily directly insert that line of text?

 


@pav_ivanovs wrote:

it shows this warning, which I don't completely understand.

pav_ivanovs_1-1714114411877.png


This Index is what allows the editor to automatically do cross-referencing, find things referenced via macros, highlight "inactive" condition code, etc, etc.

Obviously, when you change a command-line define, that's going to affect this.

 

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
unsigned_char_array
Lead III
April 26, 2024

 

__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.

"Kudo posts if you have the same problem and kudo replies if the solution works.Click ""Accept as Solution"" if a reply solved your problem. If no solution was posted please answer with your own."
Andrew Neil
Super User
April 26, 2024

@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:

https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#:~:text=%2Dfmerge%2Dconstants%20%C2%B6,%2DOs.

 

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 ...

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
unsigned_char_array
Lead III
April 26, 2024

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}"')

"Kudo posts if you have the same problem and kudo replies if the solution works.Click ""Accept as Solution"" if a reply solved your problem. If no solution was posted please answer with your own."
Pavel A.
April 26, 2024