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 pul开发者_StackOverflow中文版l 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.
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.
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)
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...
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.
精彩评论