0

Directory structure of my program

my_project
├── CMakeLists.txt
├── external
│   └── folder
│       └── schema.json
├── src
│   ├── CMakeLists.txt
│   └── main.cpp
└── unit-test
    ├── CMakeLists.txt
    └── test.cpp

I want to define a variable in my_project/CMakeLists.txt which points to schema.json

my_project/CMakeLists.txt
add_definitions(-DSCHEMA_PATH="${CMAKE_CURRENT_LIST_DIR}/external/folder/schema.json")

To use it in a code as below

my_project/unit-test/test.cpp
std::filesystem::path rootSchema{SCHEMA_PATH};

my_project/src/main.cpp
std::filesystem::path rootSchema{SCHEMA_PATH};

So after build I can directly run the executable and it works, since the json file is available at the path.

cmake -Bbuild -S.
cmake --build build --target all
./build/bin/runTests

How can use the same variable after make install? Since the schema json file is not present in install directories.

Friedrich
  • 2,011
  • 2
  • 17
  • 19
Daemon
  • 1,575
  • 1
  • 17
  • 37

1 Answers1

0

Let's take a look at what's happening here. You define a preprocessor variable SCHEMA_PATH which you set to an absolute path. This is compiled into the test and production binaries.

To make something like this work, you need to use a relative path and install schema.json along with your application.

Your root CMakeLists.txt should look something like this:

# Use a relative path from bin
add_definitions(-DSCHEMA_PATH="../external/folder/schema.json"

# Copy the file into the build directory
file(
    COPY ${PROJECT_SOURCE_DIR}/external/folder/schema.json
    DESTINATION ${CMAKE_BINARY_DIR}/external/folder
)

And in src/CMakelists.txt where you install your target

install(
    FILES ${PROJECT_SOURCE_DIR}/external/folder/schema.json
    DESTINATION my/installation/dir/external/folder
)

As pointed out by @fabian, the relative path needs to be evaluated relative to the executable's location as pointed out in the answers to Get path of executable

You should check that both the build and the installation folders have the following, identical structure:

install/build root
+ bin
| + my_executable
| + runTests (only in build)
+ external
  + folder
    + schema.json
Friedrich
  • 2,011
  • 2
  • 17
  • 19
  • 3
    A relative path alone won't do the trick, since the program need not be run with the installed `bin` directory as working directory. You'll need to use one of the approaches defined here to avoid this: https://stackoverflow.com/questions/1528298/get-path-of-executable . Alternatively info stored e.g. in the registry during installation (assuming windows) could be used for locating the install dir... – fabian May 09 '23 at 17:13
  • @fabian thank you for your constructive criticism on yet another of my answers. I took the liberty of pasting your link verbatim. I also agree there are several alternatives to relative paths by using a global config (Windows registry or *NIX dotfiles) or using absolute paths in the first place. It depends. I tried to write something that's not too different from the OP's original implementation. – Friedrich May 09 '23 at 17:50