9

I am (was) using the __FILE__ and __LINE__ macros for printing diagnostic messages out of my code. This works quite well when you use GCC with make, the file is as short as you specified it on the command line. I recently switched to using CodeLite which uses fully qualified file names (at least under windows) when building. Suddenly my diagnostic output is almost not readable.

It there a way to get only the file component of the filename in the preprocessor? I can live with a non portable GCC specific solution. (I will fallback to plain __FILE__ other cases.)

Sure I can pass the contents of __FILE__ through a function and extract only the file component, but string operations was not what I had in mind for diagnostic messages that should not change runtime behavior...

NOTE: I use the filename the way GNU uses it. A Path is collection of filenames and a filename is either a relative or absolute identifier of a file. A filename can be made up of a directory component and file component.

5
  • Diagnostics does change runtime behavior (otherwise there would be no diagnostics), and whether you call one extra function makes little difference, since the output itself is calling library functions to do the output anyway. Commented Sep 13, 2011 at 8:21
  • Printing a diagnostic message usually involves, in addition to dozens of string operations, some not-so-benign file I/O actions. For some reason nobody seems to be worried about this. Why worry about adding a call to another side-effect-free function that only affects diagnostic messages? Commented Sep 13, 2011 at 8:44
  • You both are right, adding diagnostics is not effect free. I implemented it that way, I let it pass through a function. I was more wondering it something like it exists. It sure is not standard, but finding documentation about this is not perfect. (Even the gcc manual does not outline every predefined macro.) Commented Sep 19, 2011 at 11:52
  • About I/O; not every diagnostic is bound to print to STDOUT/STDERR or a file. Ever heard of a ring buffer that is output when the application crashes? For example GNU Nana implements that. In contrast to file I/O that has "almost" no impact on performance. Commented Sep 19, 2011 at 11:55
  • FYI there's also c++ constexpr solution: stackoverflow.com/a/38237385/52074 Commented May 14, 2019 at 12:43

4 Answers 4

9

If you are using GNU Make then you can simply pass -D BASE_FILE_NAME=\"$*.c\" in on the preprocessing stage of compilation (if you're doing them separately, or at compilation if in a single stage, which is the norm).

This depends upon the way you have your file names determined. Mine come from a list of plain file names and are prefixed with directories using functions in the makefile at a later stage.

IE, this works well for me, but your mileage may vary! :-)

A simplified version of my make "code" :

CLASSES = main.c init.c

PREPROCESSED = $(patsubst %.c,$(PPCDIR)/%.pp.c,$(CLASSES))

$(PREPROCESSED): $(PPCDIR)/%.pp.c: %.c $(ALLH) 
    $(GCC) $(GCCOPTS) -D BASE_FILE_NAME=\"$*\" -E $< > $@

The simply use BASE_FILE_NAME in your code as you like :-)

Sign up to request clarification or add additional context in comments.

2 Comments

Unfortunately I am working with CodeLite, that generates the makefiles for me. Using CodeLite is great, until you want to do something that falls out of the norm. Still nice ideea, +1
The same idea can be used in Visual Studio. In Visual Studio 2008: right click on project file(.vcproj) -> Properties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions. Add BASE_FILE__=\"$(InputFileName)\". You can use __BASE_FILE instead of FILE in your source files.
4

There is no known preprocessor macro that provides the functionality. Passing __FILE__ through a function seams like the only sensible option.

4 Comments

For gcc there is __BASE_FILE__.
@fret : for me, __BASE_FILE__ outputs the same as __FILE__. If you read the documentation to which you linked, it provides the name (not necessarily basename) of the file with the main function (not the current file, even).
if you can use c++ then there is a constexpr solution: stackoverflow.com/a/38237385/52074
@TrevorBoydSmith good point. But, to be honest, if you look at the date, this question was asked one month after the C++11 was released and not widely adopted yet.
4

In reply to FredCooke above, you can exchange this line:

-D BASE_FILE_NAME=\"$*.c\"

With:

-D BASE_FILE_NAME=\"$(<F)\"

This will give you proper file name expansion, for .cpp as well.

Comments

3

As has already been mentioned in other answers, the only portable way to do this is by passing in a define from the compiler, there are however compiler spesific extensions:

  • Clang: __FILE_NAME__
  • GCC: __BASE_FILE__

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.