I use this project hierarchy:
- root:
- Module1
- Module2
- Module3
- main.cpp
main.cpp
uses the class instance from module which contains members from Module2
& Module3
. In the last module, there is a function for reading files. So, if I use relative paths, I face an issue about the wrong end path because relative paths work relatively by the folder where I launched my executable file instead of relative paths by the folder where the executable file is.
Then I created a small function for getting the root path:
static std::string rootFolder{""};
int main(int argc, char *argv[])
{
char buffer[MAX_PATH];
GetModuleFileNameA(NULL, buffer, MAX_PATH);
std::string::size_type pos = std::string(buffer).find_last_of("\\/");
rootFolder = std::string(buffer).substr(0, pos) + "/../";
return EXIT_SUCCESS;
}
P.S.: So far I have added implementation for Windows only.
In the main function, it works. But I need to transfer rootFolder to a class in Module3
and then I added a file with globals - globals.hpp (I didn't add a cpp implementation because I think a code less than 20 lines I can store in a header).
#ifndef APP_GLOBALS
#define APP_GLOBALS
#include <string>
#include <Windows.h>
#include <string>
static std::string rootFolder{""};
inline void initGlobals()
{
char buffer[MAX_PATH];
GetModuleFileNameA(NULL, buffer, MAX_PATH);
std::string::size_type pos = std::string(buffer).find_last_of("\\/");
rootFolder = std::string(buffer).substr(0, pos) + "/../";
}
#endif
And in the main function and Module3
source file, I added the following lines:
#include "globals.hpp"
main func:
/// Other code here
int main(int argc, char *argv[])
{
initGlobals();
/// Other code here
}
But when I tried to compile the app, I got an error:
cmd.exe /C "cd . && C:\PROGRA~1\mingw64\bin\G__~1.EXE -g CMakeFiles/VulkanTriangle.dir/src/app.cpp.obj CMakeFiles/VulkanTriangle.dir/src/main.cpp.obj CMakeFiles/VulkanTriangle.dir/src/pipeline.cpp.obj CMakeFiles/VulkanTriangle.dir/src/core/window.cpp.obj -o ..\bin\VulkanTriangle.exe -Wl,--out-implib,libVulkanTriangle.dll.a -Wl,--major-image-version,0,--minor-image-version,0 -LD:/Documents/programming/vulkanTriangle/lib -lglfw3 -lvulkan-1 -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
CMakeFiles/VulkanTriangle.dir/src/pipeline.cpp.obj:D:/Documents/programming/vulkanTriangle/src/globals.hpp:10: multiple definition of `initGlobals()'
CMakeFiles/VulkanTriangle.dir/src/main.cpp.obj:D:/Documents/programming/vulkanTriangle/src/globals.hpp:10: first defined here
collect2.exe: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
So, then I started to google about the multiple definition
error and I found another question from stackoverflow.
Question 1:
As it was written in one of the answers, I added the inline
keyword before initGlobals
function. And yes! It worked. But can't understand why. Can you explain?
As I understand HEADER GUARD logic, it works like this:
#ifndef MY_SUPER_UNIQUE_HEADER // Ok, it was defined. Then pass the code below.
#define THAT_HEADER
#endif
Question 2:
So, if get the multiple definition
error, it seems I don't understand a header loading logic. Can you explain it?
And perhaps I have a main question:
Is there any better solution to init and transfer rootFolder
variable to Module3
.
Sorry for the TLDR :)