Let CMake set the "Exclude From Build" option for a single source file in Visual Studio - c++

In Visual Studio there is an "Exclude From Build" option in the properties page of each source file, that can be set to exclude the file from build, but keep it visible in the source tree:
Is there a way to set that specific property with CMake?
I found a VS_DEPLOYMENT_CONTENT property and tried that but without success (it doesn't seem to do anything).
The reason for using that property is mainly to keep the file in the project to be able to open and edit it from within Visual Studio.
Thanks in advance!

Unfortunately, I also can't find the answer how to set "Exclude From Build" for some files with cmake in the same project. For now, I have added all such files to the target created by add_custom_target.
if(MSVC)
add_custom_target(myproj.additional SOURCES ${otherHeaders} ${otherSources})
endif()
This will create an extra project in the solution. The files in this project will not compile and I can still edit and search in them.
Another option is to set the HEADER_FILE_ONLY property for sources that should not be compile:
if(MSVC)
set_source_files_properties(${otherSources} PROPERTIES
HEADER_FILE_ONLY TRUE
)
endif()
In this case, the files stay in the project but without any marks - such files will not differ in appearance from those that are compiled

Since CMake 3.18 you can use VS_SETTINGS. That allows you to set any VS Project setting you like.
set_property(SOURCE ${SourceFiles} PROPERTY VS_SETTINGS "ExcludedFromBuild=true")
Note that you have to set the settings values with the name as it is written in the vcxproj file. To know what the setting is called you can set the setting to the correct value via the VS IDE, save the project and then open the vcxproj file in a text editor and search for the correct setting-value pair.
For example, in case of Excluded from Build:
<FXCompile Include="C:\path\to\source\file\file.hlsl">
<ExcludedFromBuild>true</ExcludedFromBuild>
</FXCompile>

Related

How to use Visual Studio with CMake AND preserve file structure

I use CMake to create C++ projects. Then I would like to use Visual Studio as my IDE. But the issue I face is that I can't get files to be structured properly.
Here is the problem:
Let's assume I have the following file structure on the disk.
And here is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.20)
set(sourceDirectory src)
set(includeDirectory include)
set(targetName vulkan-tutorial)
set(targetVersion 1.0.0)
project(${targetName} VERSION ${targetVersion})
file(GLOB src
${sourceDirectory}/*.cpp
${sourceDirectory}/**/*.cpp
${sourceDirectory}/**/**/*.cpp
)
add_executable(${targetName} ${src})
target_include_directories(${targetName} PRIVATE ${includeDirectory})
Here is what this project looks like in Visual Studio with filters.
Or without using VS-filters.
I can create new files, but they're not going to land, where I want them to. The behavior I want to achieve is extremely simple: I want to see the root directory of my project and its "src" and "include" folders. I want to be able to right-click them and create new folders and files. Then I want Visual Studio to create them inside the selected folder. Like it would be in every normal file-explorer.
One solution I could imagine is to generate project files not inside a "build folder", but in the root directory of the project itself, which is obviously a terrible solution and leads to a pollution of the project structure.
Summarized - here is the result I want to end up with (now I can achieve it only by generating the project in the root). But all the build files should be located in the corresponding "build" folder in the root of the project.
I also would like to add that I tried to use different functions for CMake that kind of group my files together, but I just ended up with lots of filters that reflect my project structure on the disk. Of course, I still wasn't able to add new folders and files dynamically.
I appreciate any help. Thanks in advance.
Simply use the Open Folder option in visual studio.
This will open the directory and automatically configure the project using CMake. It will display the tree independently from the CMake configuration structure.
Microsoft has a page CMake projects in Visual Studio, that explains how to properly import CMake projects in visual studio

How to specify source directory location in CMakeLists.txt?

In my c++ cmake project I want my CMakeLists.txt and source files in different locations. How can you specify this to cmake? I want to know this because I believe it makes sense to separate build files from source files.
In my case, this is for a cross platform project. I know one usually uses a single top-level CMakeLists.txt + conditional constructs to handle different targets/platforms, but what I plan is to have different CMakeLists.txt files for each platform and have them AWAY from the sources. Like so:
-my_project
-sources
-module1
-common.hpp
-common.cpp
-windows
-win_functions.cpp
-win_functions.hpp
-linux
-linux_functions.cpp
-linux_functions.hpp
-module2 (...)
-module3 (...)
-build_projects
-windows
-CMakeLists.txt
-linux
-CMakeLists.txt
It seems to me it would be a matter of specifying a new cmake's working/source directory but so far the closet I get is to prepend the correct location when adding source files as in:
target_sources(my_target_windows PRIVATE ${win_source_dir}/win_functions.cpp)
But the problem is visual studio won't let me preview the source files when adding them in this way, and it seems I cannot solve this in visual studio's CMakeSettings.json either. So I am looking for a more built-in feature for this.
Ok, found a fix for my problem within Visual Studio:
In solution explorer set "solutions and folders" to "CMake Targets View" and it will now correctly display sources and headers added to the cmake project.
So, using relative paths to sources in cmake + this VS feature solves my problem.

How to hide targets in Visual Studio from CMake

I am generating a .sln with CMake.
I want to use Google Test and use that kind of code for adding a new tests:
add_executable(my_test test/my_test.cpp)
target_link_libraries(my_test gtest gmock_main)
add_test(NAME my_test COMMAND my_test)
It works fine, but when I open my .sln, I have all the targets appearing in the solution explorer: the libraries, the unit tests, etc.
Is there a way to hide these target?
You can't do it explicitly only in cmake (ATM), but here is one way on how can hide multiple targets more efficiently: Simply put them on in the same "folder" (in cmake) and then hide the folder (in visual studio).
Suppose you have cmake targets called Mm,Nn and Pp that you want to hide in Visual Studio. You need to say to cmake to allow "folders" and Simply set the property called FOLDER like so
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set_target_properties(Mm Nn Pp PROPERTIES FOLDER nameOfTheFolder)
and then right click on the folder nameOfTheFolderin solution and on hide folder.
If you want to see the hidden folders again, right click on the solution and then Unhide folders (this is at least how it is in visual studio 2010)

Is it possible to add files to a CMake generated solution folder in Visual Studio?

This question is more or less a warmup of this question:
how to get cmake to add files to msvcs solution tree
It never got a valid answer so I want to repose it slightly different:
Is it possible to use the cmake solution folders that where introduced with cmake 2.8.3 to add files directly to the vs solution? I want to do the cmake equivalent of VS->Solution->Add->Existing Item. So my file will appear in a folder that belongs to the solution and not to a project.
I found examples how the solution folders can be used to group targets into folders with code like this:
set_property( GLOBAL PROPERTY USE_FOLDERS ON)
set_property(TARGET ${TARGET_NAME} PROPERTY FOLDER "Test")
So can I add a file instead of a target to the folder?
This is probably not possible.
CMake organizes its assets into projects and targets. The project is what corresponds to Visual Studio's solution file while each target will generate a Visual Studio project inside the respective solution.
The problem is now that CMake does not allow to add files to CMake projects. In fact, a CMake project is little more than a collection of targets and offers almost no customization options. Hence the USE_FOLDERS option you mentioned can only be used to group VS projects inside a solution, but not single files.
The closest to what you ask would probably be to add a custom target that holds your files. However, this will still generate a VS project (which also contains a bunch of other stuff besides your files) inside the solution and not a plain folder.
If I understand the question correctly, I think I know how to do it:
set(FILES_TO_ADD
file1
file2
file3)
source_group("Group Name" FILES ${FILES_TO_ADD})
The source_group command creates the folder inside the Visual Studio project.
This answer just adds an example for the "custom target" solution that was proposed by ComicSansMS in the accepted answer. This is what I currently use to add my global files.
set( SOLUTION_FILES
${CMAKE_SOURCE_DIR}/CMakeLists.txt # root CMakeLists file
${CMAKE_SOURCE_DIR}/cmake/macros.cmake # cmake functions
${CMAKE_SOURCE_DIR}/CMakeInCodeDefinitions.h.in # imported cmake variables
# etc...
)
add_custom_target( GlobalFiles SOURCES ${SOLUTION_FILES})

generate vs2010 project file with my own source directories

In most of my c++ projects, i want to use a different directory structure from visual studio default directory structure. i.e:
/project
/build # put visual studio soluation and project files
/src # only put the c++ header files and source files
/bin # put the target executable files
/debug
/release
/tmp
/debug
/release
Everytime i create a solutaion in vs2010 i will config these directories (e.g OutputDirectory), but now i'm really boring about this.
So is there a tool to generate vs2010 solution and project files automatically according my config file? And my only requirement is to set these directories.
You can achieve the structure with the following CMakeList. The following assumes the file is located at .../project/CMakeLists.txt:
cmake_minimum_required(VERSION 2.8) #every top-level project should start with this command; replace the version with the minimum you want to target
project(MyProjectName)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) # put .exe and .dll files here
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) # put .so files here (if you ever build on Linux)
set(CMAKE_MODULE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) # put .dll and .so files for MODULE targets here
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib) # put .lib files here
# Note that for multi-configuration generators (like VS), the configuration name will be appended to the above directories automatically
# Now that the directories are set up, we can start defining targets
add_executable(MyExe src/myExe.cpp)
add_library(MyLib SHARED src/myDLL.cpp)
target_link_libraries(MyExe MyLib)
When invoking CMake, set the output directory to .../project/build (e.g. in the CMake GUI). If running from the command line, do it like this:
> cd .../project/build
> cmake .. -G "Visual Studio 10"
Please note that some generators (Eclipse) don't like it when the output directory a subdirectory of the source directory. For such case, a slight directory re-structuring would be recommended.
You could write such a tool yourself in C# for instance, look at the classes in the Microsoft.Build.Construction namespace, they're made for creating projects programmatically.
However a simpler yet more versatile option is using the same property sheet in all your projects, and set all directory paths you need. This also has the huge advantage that it's reusable so should you ever decide to change your output directories, all projects referencing your property sheet are automatically affected.
For example:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MyMainDir>$(ProjectPath)\..\</MyMainDir>
<OutDir>$(MyMainDir)\bin\$(ConfigurationName)</OutDir>
<IntDir>$(MyMainDir)\tmp\$(ConfigurationName)</IntDir>
</PropertyGroup>
</Project>
This will first figure out your 'main dir' i.e. the one named 'project' in your question and then set the output and intermediate directories based on that and the name of the current ConfigurationName, which by default is Debug or Release.
Now it's just a matter of importing this property sheet in your project: go to View->Other Windows->Property Manager, right-click the project(s), select Add Existing property Sheet. Or you could manually add an <Import Project=....> in the project file.
While you're at it, you might as well also add compiler/linker options to the property sheet so all your projects use the same options. This takes some time now, but will save you tons of time in the future as you don't have to change the same options in the project settings over and over and over again.