Reading file in a c++ file in VS project [duplicate] - c++

I have a project with the following structure:
project_name/CMakeLists.txt
project_name/src
project_name/resources
...
project_name-build/configuration_name/project_name.exe
I want my application to be run in the root project directory project_name so it can directly access resources.
Does CMake provide a method to specify this property, or will I have to manually set it in each build environment I use?
I've looked around in the documentation and haven't found anything other than the possibility of setting up a post-build event to run my project from the desired directory which is less than desirable. I also found that the working directory setting for Visual Studio is saved in a per-user file (.vcxproj.user) which I don't believe CMake generates (which points to the answer being probably no).

Since CMake 3.8, there is the VS_DEBUGGER_WORKING_DIRECTORY target property, which allows you to set the debugger working directory for a target in Visual Studio.
Usage example:
set_property(TARGET MyTarget PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")

As drescherjm pointed out (in his comment on the question) CMake doesn't provide a method to directly set a working directory. However, CMake does provide indirect methods of doing so.
The path I think I'll take is to use the configure_file command to fill in a template .user file.

Here is an easier solution.
Paste this at the end of your cmake:
file( WRITE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.vcxproj.user"
"<?xml version=\"1.0\" encoding=\"utf-8\"?> \
<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>")
It overwrites the default vcxproj.user file for the current project and specifies $(OutDir) for the Working Directory as desired for debugging. Make sure that $PROJECT_NAME is your project name.

Related

Debugging CMake Visual Studio project with PATH environment set by VS_DEBUGGER_ENVIRONMENT

I've created a CMake project using visual studio 2019. It has one executable target, which links to some shared libraries (DLL). I cannot directly set the system environment variable PATH because the DLL path is determined by find_package. Therefore, set VS_DEBUGGER_ENVIRONMENT target property is my choice to debug that executable target.
However, the VS_DEBUGGER_ENVIRONMENT property is not working when I directly open the CMake project and debug that target. I've checked the .vsproj it has the correct LocalDebuggerEnvironment tag generated.
But if I run cmake -G "Visual Studio 16 2019" ../ and open the generated visual studio solution and then debug the subproject from there, everything turns out to be ok.
I think maybe the visual studio doesn't support LocalDebuggerEnvironment when opening project as a CMake project. Or perhaps I didn't debug it the right way. Is there anything else I can do to change the visual studio debug runtime PATH environment using CMake?
Any suggestion would be greatly appreciated!
This is just to share what I finally ended up with after some painful hours of digging through the web.
First, a variable to store the required debugging paths is needed (example):
list(APPEND VS_DEBUGGING_PATH "%PATH%")
list(APPEND VS_DEBUGGING_PATH "${PostgreSQL_ROOT}/bin")
The next step is to create a ${CMAKE_PROJECT_NAME}.vcxproj.user template file for C/C++ and in my case also a ${CMAKE_PROJECT_NAME}.vfproj.user template for FORTRAN (just for the record):
file(
WRITE "${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.vcxproj.user"
"<?xml version=\"1.0\" encoding=\"utf-8\"?>
<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">
<PropertyGroup Condition=\"'\$(Configuration)'=='Release'\">
<LocalDebuggerEnvironment>PATH=#VS_DEBUGGING_PATH#</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition=\"'\$(Configuration)'=='MinSizeRel'\">
<LocalDebuggerEnvironment>PATH=#VS_DEBUGGING_PATH#</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition=\"'\$(Configuration)'=='RelWithDebInfo'\">
<LocalDebuggerEnvironment>PATH=#VS_DEBUGGING_PATH#</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition=\"'\$(Configuration)'=='Debug'\">
<LocalDebuggerEnvironment>PATH=#VS_DEBUGGING_PATH#</LocalDebuggerEnvironment>
</PropertyGroup>
</Project>"
)
file(
WRITE "${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.vfproj.user"
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<VisualStudioUserFile>
<Configurations>
<Configuration Name=\"Release|x64\" Environment=\"PATH=#VS_DEBUGGING_PATH#\"/>
<Configuration Name=\"MinSizeRel|x64\" Environment=\"PATH=#VS_DEBUGGING_PATH#\"/>
<Configuration Name=\"RelWithDebInfo|x64\" Environment=\"PATH=#VS_DEBUGGING_PATH#\"/>
<Configuration Name=\"Debug|x64\" Environment=\"PATH=#VS_DEBUGGING_PATH#\"/>
</Configurations>
</VisualStudioUserFile>"
)
As you might see, both template files are just dumped into the root of ${CMAKE_BINARY_DIR} in this case. The base name ${CMAKE_PROJECT_NAME} is also arbitrary.
Those templates can then finally be "configured" (copied) into each target folder of your setup. Either for C/C++
configure_file(
"${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.vcxproj.user"
"${CMAKE_CURRENT_BINARY_DIR}/${target_name}.vcxproj.user"
#ONLY
)
or FORTRAN
configure_file(
"${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.vfproj.user"
"${CMAKE_CURRENT_BINARY_DIR}/${target_name}.vfproj.$ENV{USERNAME}.user"
#ONLY
)
or even both if necessary. The variable ${target_name} needs to replaced with your target name of course. :-)
This should suffice. It is however important to close VS 2019 before (re-)configuring/(re-)generating with CMake. Otherwise VS 2019 might simply overwrite those files for each target.
I strongly hope this is helpful.
Please let me know if you need more details.
Here is the result for C/C++ targets and here for FORTRAN targets

How to ensure that the relative paths are the same in Linux and Windows using CMake [duplicate]

I have a project with the following structure:
project_name/CMakeLists.txt
project_name/src
project_name/resources
...
project_name-build/configuration_name/project_name.exe
I want my application to be run in the root project directory project_name so it can directly access resources.
Does CMake provide a method to specify this property, or will I have to manually set it in each build environment I use?
I've looked around in the documentation and haven't found anything other than the possibility of setting up a post-build event to run my project from the desired directory which is less than desirable. I also found that the working directory setting for Visual Studio is saved in a per-user file (.vcxproj.user) which I don't believe CMake generates (which points to the answer being probably no).
Since CMake 3.8, there is the VS_DEBUGGER_WORKING_DIRECTORY target property, which allows you to set the debugger working directory for a target in Visual Studio.
Usage example:
set_property(TARGET MyTarget PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
As drescherjm pointed out (in his comment on the question) CMake doesn't provide a method to directly set a working directory. However, CMake does provide indirect methods of doing so.
The path I think I'll take is to use the configure_file command to fill in a template .user file.
Here is an easier solution.
Paste this at the end of your cmake:
file( WRITE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.vcxproj.user"
"<?xml version=\"1.0\" encoding=\"utf-8\"?> \
<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>")
It overwrites the default vcxproj.user file for the current project and specifies $(OutDir) for the Working Directory as desired for debugging. Make sure that $PROJECT_NAME is your project name.

Custom CMake target that uses only CMake functions [duplicate]

I have a project under CMake with some files generated with python generator from XML files. I cannot specify all files generated by this generator in CMakeLists.txt so I use file globbing for this.
The problem is that when I update my XML files or generator sources (which are in the same repository) I would like to have my build system reconfigured so changed files are taken into account when rebuilding the code (via make for example).
Is it possible to make CMake treat some files like it treats CMakeLists.txt files and to make it regenerate build system when those file are changed?
It doesn't require any kind of workarounds. The standard way is to use CMAKE_CONFIGURE_DEPENDS property:
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS <filename>)
Yes, you should be able to do that by (ab)using configure_file(). Configuring a file makes the source a dependency of the CMake run, so that any changes in it cause a reconfiguration. Simply like this:
configure_file(MyInputFile.xml DummyOutput.xml)
Since it has been a while I will add to #roolebo's answer.
There's actually a better command to add a dependency on a file:
set_directory_properties(PROPERTIES CMAKE_CONFIGURE_DEPENDS <relative_or_full_path_to_file>)
What might be confusing is that this command adds a property to the current directory. Well, it does not matter since you can set a full path to a file that resides outside of the current directory's scope, for instance: ../../config.json

CMake Error: "add_subdirectory not given a binary directory"

I am trying to integrate Google Test into the subproject of bigger project and I cannot find the solution that would be satisfying for me.
I have two constraints:
the source code of Google Test is already somewhere in the project structure (thus using URL to download it from git repository is not an option)
the source code of Google Test is not a subdirectory of my subproject (and never will)
So when I tried to do something like this:
add_subdirectory( ${GOOGLETEST_PROJECT_LOCATION})
I received:
CMake Error at unit_tests/CMakeLists.txt:10 (add_subdirectory):
add_subdirectory not given a binary directory but the given source
directory "${GOOGLETEST_PROJECT_LOCATION}" is not a subdirectory of
"${UNIT_TEST_DIRECTORY}". When
specifying an out-of-tree source a binary directory must be explicitly
specified.
On the other hand maybe ExternalProject_Add could be a solution but I do not know how shall I use it when I do not want to download sources at all and use sources from specific location in the project.
Project structure looks more or like like this:
3rdparty
|--googletest
...
subproject
|--module1
|--file1.cpp
|--CMakeLists.txt
|--module2
|--file2.cpp
|--CMakeLists.txt
|--include
|--module1
|--file1.h
|--module2
|--file2.h
|--unit_test
|--module1
|--file1test.cpp
|--module2
|--file2test.cpp
|--CMakeLists.txt
|--CMakeLists.txt
CMakeLists.txt
The error message is clear - you should also specify build directory for googletest.
# This will build googletest under build/ subdirectory in the project's build tree
add_subdirectory( ${GOOGLETEST_PROJECT_LOCATION} build)
When you give relative path (as a source directory) to add_subdirectory call, CMake automatically uses the same relative path for the build directory.
But in case of absolute source path (and when this path isn't in your source tree), CMake cannot guess build directory, and you need to provide it explicitly:
See also documentation for add_subdirectory command.
I feel obligated to comment on this because this was the top search result when I was googling this error.
For me, I'm apparently an idiot: I had modified the CMakeLists.txt file in the src directory of my project, but I didn't realize the file was locked and VS Code wasn't actually saving even when I hit Ctrl+S. Check the file tab in VS Code and see if there's a white dot there, indicating the file isn't saved. Hit Ctrl+S and see if you get a pop-up in the lower-right corner prompting you to try again as superuser.
I've still got errors, but they're new errors that make sense for my project.

CMake command line for C++ #define

I need to compile different versions of a certain project by adding compiler switches. Usually I would do this by using add_definitions or something like
set_property( TARGET mylib PROPERTY COMPILE_DEFINITIONS _MYDEFINE=1 )
in the CMakeLists.txt file.
In this specific project however, I am not allowed to modify any sources, including the CMakeLists.txt file.
I was hoping that something like
cmake -D_MYDEFINE=1 <path to sources>
would generate a project file (Visual Studio 2008 in my case, but shouldn't matter) which includes _MYDEFINE=1 in its preprocessor definitions but in fact it won't.
What are my options here? Is there a different cmake command line option to achieve this? Feel free to suggest solutions not including the command line, as long as changing the project's CMakeLists.txt is not necessary.
I managed to do it this way now:
I was able to convince everybody to add the following lines to the common CMakeLists.txt:
IF (NOT DEFINED _MYDEFINE)
SET(_MYDEFINE <default value>)
ENDIF()
ADD_DEFINITIONS(-D_MYDEFINE=${_MYDEFINE})
(No it is not really called "MYDEFINE", and <default value> is just a placeholder, I just replaced all that for this example)
This does not change the current behaviour of compiling with no additional compiler flags and is thus a valid change.
And it allows you to do
cmake -D_MYDEFINE=<my value> <path to sources>
where this cmake definition will be mapped to a C++ precompiler definition when cmake creates the project file.
Container CMakeLists.txt solution
Tricky solution:
Your read only CMakeList.txt path: ${path}/ReadOnlyProject/CMakeLists.txt
Create a new CMakeList.txt to upper to the read only library (${path}/CMakeLists.txt):
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0)
PROJECT (FAKE_PROJECT)
ADD_DEFINITIONS(-D_MYDEFINE=1)
ADD_SUBDIRECTORY(ReadOnlyProject)
Now use your new project (FAKE_PROJECT) to compile. If the ReadOnlyProject does not set compilers definitions directly, it could work.
On Visual Studio 2010:
Try to modify c:\Users\${username}\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.Win32.user.props to add custom compiler settings.
You should add the followings:
<Project>
...
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>__MYDEFINE=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
</Project>
To pass a C++ or C pre-processor define without modifying any CMake source files, use the environment variables CFLAGS for C or CXXFLAGS for C++ respectively, e.g.:
$ export CXXFLAGS="-D_MY_DEFINE=1 -D_MY_OTHER_DEFINE=1"
$ mkdir build
$ cd build
$ cmake ..