__FILE__
gives either an absolute path (built with make) or a relative one (built with ninja). Here's a simple tester:
#include <iostream>
int main(int argc, char *argv[]) {
std::string thisFile = __FILE__;
std::cout << "thisFile = " << thisFile << "\n";
return 0;
}
And here's the equally simple CMakeLists.txt
:
cmake_minimum_required(VERSION 3.10)
project(file_test)
add_executable(app main.cpp)
If I'm in the build
directory, I'll type either cmake ..
or cmake -GNinja ..
(I've also experimented with explicitly saying which c++ compiler to use with a -D
argument on the command line - with unchanged results).
If I build with ninja, app
's output is:
thisFile = ../main.cpp
If I build with make, app
's output is:
thisFile = /home/myname/sandbox/cmake/main.cpp
I've tried this on Ubuntu and Pop!OS - same results.
Does anyone know of a way to get the ninja build to behave in the same way that the make build does?
Does anyone know of a way to get the ninja build to behave in the same way that the make build does?
Use CMake 3.21, from 3.21 release notes:
The Ninja Generators now pass source files and include directories to the compiler using absolute paths. This makes diagnostic messages and debug symbols more consistent, and matches the Makefile Generators.
Alternatively, write a wrapper script around your compiler. Such a script would parse compiler options and extract source file path and change relative path to absolute and then invoke the compiler with absolute path. Pass that wrapper to CMake with CMAKE_CXX_COMPILER_LAUNCHER
to launch your script.
Alternatively, in CMake iterate over every file you are going to compile, extract in CMake a full path to that file with get_filename_component
and then use set_source_file_properties
on that file to add COMPILE_DEFINITION
like ABSFILE=${the_absolute_path_to_that_file}
and use that compile definition in your source file for a full path. I think, probably depending on compiler, you could also overwrite __FILE__
that way.