Best way to get ${workspaceFolder} for relative paths in c++

Viewed 26

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

0 Answers
Related