Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieve output target name as a string at compilation time in C++

I have a project which compiles in multiple platforms... Windows, Unix, Linux, SCO, name your flavor.

I would like to stuff the output target's name into a variable in the project source code (the name of the output program, DLL, SO library or whatever) so I can use it in messages as a generic way to reference the component name be it an EXE on Windows, a DLL, an SO library on Unix, etc.

What I'm thinking of is a preprocessor key like FUNCTION_ but something to pull the name of the EXE/DLL on Windows in Visual C++, and then secondarily the SO output library in GCC. Those are probably going to be two different mechanisms of course, but I figure to coalesce the two into one option that I can use generically in my multiplatform code.

So a macro'ish thing or something I can call which at least picks up the Windows output file name during compilation (Visual C++) so I can push it into a const string in the code, and maybe a way to do the same thing in GCC so the two platforms can be wrapped into an single abstraction. Preferably not picked up at runtime but caught and persisted during compilation.

If the output is a library, then its the lib file name. If it's a component, then the output component file name.

I expect Boost or Poco must have something like this already possibly with some unsupported endpoints which is fine.

like image 586
Allbite Avatar asked Mar 04 '11 18:03

Allbite


4 Answers

If everything is together under one project, you can use a preprocessor macro. To do this in Visual Studio, open up your project properties and go to Configuration Properties > C/C++ > Preprocessor, and add something like PROGRAM_NAME="\"$(ProjectName)\"" to the Preprocessor Defines field (which corresponds to the /Dfoo=bar compiler option).

For GCC, use the similar -Dfoo=bar command line option. For example, your Makefile might look something like this:

PROGRAM_NAME = myapplication
CFLAGS += '-DEXECUTABLE_NAME="$(PROGRAM_NAME)"'

# Rule to make the executable from the object files
$(PROGRAM_NAME): $(OBJS)
    $(LD) $(OBJS) -o $@ $(LDFLAGS)

# Rule to make object files from C source files
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

This allows your source files to use the macro PROGRAM_NAME, which will expand to the constant string "myapplication" in this case.

However, if you have object files that are being linked into multiple programs (e.g. you have lots of shared library code which can be run either by the main program driver or by various test suites), then the object files can't know which executable they're being linked into ahead of time, so they have to determine that at runtime.

In that case, use a constant global variable to store the program name, and define and initialize that in each executable's main source file using the technique above.

like image 54
Adam Rosenfield Avatar answered Nov 15 '22 18:11

Adam Rosenfield


The compiler cannot know this. It's the linker that assigns a name. I'd say your best bet is a define, or runtime determining the module name (which won't work for static libs)

like image 24
Erik Avatar answered Nov 15 '22 16:11

Erik


Another solution, a bit hacky, would be to set your const string in the code to a unique, easy to locate and big enough value and after the linking is done locate & overwrite the unique value with the actual name of file you're operating on...

like image 1
Eugen Constantin Dinca Avatar answered Nov 15 '22 16:11

Eugen Constantin Dinca


Based my solution on @Adam Rosenfield's answer.

In my CMakeLists.txt created a variable:

set(DLL_NAME myModuleDllName)

Then added the macro to the project like this:

add_compile_definitions(DLL_NAME="${DLL_NAME}")

Now I can use this macro everywhere in the generated Visual Studio project.

like image 1
KulaGGin Avatar answered Nov 15 '22 16:11

KulaGGin