generate vs2010 project file with my own source directories - c++

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.

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

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

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>

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)

Display include-directory as separate part of project in Visual Studio using CMake

I am in the process of porting a big library project from Linux to Windows. Fortunately we were using CMake even before porting was even remotely on the table so not many adjustments were needed.
I figured it might be a good idea to develop the Windows parts natively on Windows for easier testing so i created a VS Studio using the CMake-gui
My project is organized like this:
lib/ # Library source code
include/
mylib/ # Public installable header files
In the top CMakeLists.txt i added
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
so my internal source files include the headers just like an external application would.
The problem is now the following: Visual Studio 2015 displays the public header files in the "External References"-directory among a lot of system headers. It is not obvious which header files belong to the project.
How can i make VS display the public headers separately from the system includes?
Turning my comment into an answer
All header files you want to be explicitly listed by CMake in Visual Studio projects have to be listed as a source file in your CMake target's list of sources.
Then you can group those sources/headers via the source_group(... FILES/REGULAR_EXPRESSION ...) command.
If you have more then one target and you don't want to add those steps manually every time, you could think about grouping them into a function():
function(my_add_library _target)
file(
GLOB_RECURSE _header_list
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_SOURCE_DIR}/include/*.h*"
)
add_library(${_target} ${ARGN} ${_header_list})
target_include_directories(${_target} PRIVATE "${CMAKE_SOURCE_DIR}/include")
source_group("Public Headers" FILES ${_header_list})
endfunction(my_add_library)
Note:
I'm using file(GLOB ...) only to collect the headers, not the sources (see Why is cmake file GLOB evil?)
You could keep the include_directories() command in the main CMakeLists.txt, I just prefer the target specific target_include_directories() variant
For more details on grouping source/header files in CMake see:
Keeping file hierarchy across subdirectories in CMake
How to keep source folders hierarchy on solution explorer?
And as a general reference:
What is the difference between "${CMAKE_CURRENT_SOURCE_DIR}" and "." in INCLUDE_DIRECTORIES?

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