1

I'm trying to learn CMake and am struggling to achieve the project layout that I'm used to making with visual studio.

I want to achieve something like the following directory structure, where the .vcxproj and .sln are generated by CMake

Root
    CMakeLists.txt
    MySolution.sln

    ProjectOne
        CMakeLists.txt
        ProjectOne.vcxproj
        someSourceFile1.h
        someSourceFile1.cpp

    ProjectTwo
        CMakeLists.txt
        ProjectTwo.vcxproj
        someSourceFile2.h
        someSourceFile2.cpp

    Binaries
       Platform
          Debug
              ProjectOne.exe
              ProjectTwo.dll

          Release
             ProjectOne.exe
             ProjectTwo.dll

All the tutorials I seem to find seem to give an Examples where the structure turns out something like this:

Root
   Source
      CMakeLists.txt

      ProjectOne
        CMakeLists.txt
        someSourceFile1.h
        someSourceFile1.cpp

      ProjectTwo
        CMakeLists.txt
        someSourceFile2.h
        someSourceFile2.cpp

    Build
       MySolution.sln
       ProjectTwo.vcxproj
       ProjectOne.vcxproj
      
       Platform
          Debug
              ProjectOne.exe
              ProjectTwo.dll

          Release
              ProjectOne.exe
              ProjectTwo.dll
              

Using commands like

mkdir Build
cd build
CMake ..\Source
CMake --Build .

Notable I have not added ALL_BUILD.vcxproj and ZERO_CHECK.vcxproj that get generated, which I am yet to understand my need for.

  • Is there just a command I'm missing in the CMakeList.txt to do this?
  • Is there a reason I shouldn't lay my project out the way I want to?
Natio2
  • 235
  • 1
  • 9
  • 1
    Why would you need generated files to be mixed with persistent files? It is a nightmare to manage such organization if you find a way to make it happen. – ixSci Aug 12 '22 at 04:54
  • @ixSci One reason is that in visual studio if you go project->Add new It will dump it into Root/Build/ so adding files becomes super manual. Go to directory Root/Source/Project/, make file, add to CMakeList, rebuild to generate... – Natio2 Aug 12 '22 at 04:58
  • 2
    You still have to manually edit cmake files, MSVS won't do it for you if you are using the solution mode so your organization won't fix everything. Or you can try the CMake mode of Visual Studio but it is lacking comparing to the solution one in other parts. – ixSci Aug 12 '22 at 05:01
  • @ixSci Being new to CMake there's lots I don't know. I figured you'd be able to auto include all the *.h and *.cpp in a directory like you can in other build systems like premake – Natio2 Aug 12 '22 at 05:02
  • 1
    `ZERO_CHECK` is a internal cmake target for regenerating the solution, if the cmake project is detected to be out of date and it will be inserted as a dependency of all of your own targets and `ALL_BUILD` a target that when build does the equivalent of `make all` (or `cmake --build build_dir`) If you activate the [`USE_FOLDERS` global property](https://cmake.org/cmake/help/latest/prop_gbl/USE_FOLDERS.html) cmake will put those files in an extra folder `CMakePredefinedTargets` in your solution explorer. – fabian Aug 12 '22 at 16:23

1 Answers1

0

Doing some more research I have stumbled across this post Visual Studio puts new files into wrong directory which made me think I could not mix my dev and dist builds with CMake.

Thanks to the helpful comments of fabian that you can actually build the structure I want and am used to doing something like this.

You can make it only use folders for specific builds if you want it for some and not others.

project(MySolution)

cmake_minimum_required(VERSION 3.2)

# Use solution folders if I'm using VS change to whatever your dev platform is
IF(MSVC)
  SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
ENDIF()

add_subdirectory(MyFolderName)

Having a play with it, your dev build does need to call CMake from the \source folder where a distribution build would need to be called from the \Build directory to separate out the files.

I'm guessing there's ways to use more If() ... Else() ... Endif() to generate this in a specific folder based on build type as well.

Having a look around, I think the easiest way might just be to place another scripting language over the top that just calls the cmake commands from different directories based on build type.

Windows.scriptType Linux.scriptType etc...

Unless some kind soul can point me how to do this one in CMake

Natio2
  • 235
  • 1
  • 9
  • 1
    "CMake is meant for distribution builds, not development builds" -- that is absolutely untrue – Alex Reinking Aug 12 '22 at 14:08
  • *"CMake is meant for distribution builds, not development builds."* Oh, I did not know. I need to tell my colleagues about this; We've been doing it wrong for years... Seriously: CMake discourages you to set up the project with source and build directory matching, the reason being that there are extra files that will be generated in the build directory and those could conflict with your sources in the worst case. Just set everything up as a single solution file and you're probably fine simply working with this solution. – fabian Aug 12 '22 at 16:26
  • 1
    You can use `USE_FOLDERS` and `CMAKE_FOLDER` to generate a suitable structure in the solution explorer. – fabian Aug 12 '22 at 16:30
  • @fabian Thank you! I wish you had made it as an answer so I could tick it. Do you know of any repo's that already have this setup, so I can use it as an example to read through? Also isn't it annoying working in the IDE when you split them out, as the built in functions wont Know to but the source in the other folder? – Natio2 Aug 12 '22 at 21:26
  • Would you do something like if(WIN32) set_property( GLOBAL PROPERTY USE_FOLDERS ON) else() set_property( GLOBAL PROPERTY USE_FOLDERS OFF) endif() then you get the benefit of a nice dev build and your dist builds will still be split out? – Natio2 Aug 12 '22 at 21:32
  • 1
    You don't need to do this at all: `USE_FOLDERS`/`CMAKE_FOLDERS` only influence the solution explorer structure (and possibly similar info for different generators targeting another IDE) and this information should be is entirely different to any other properties of the projects created.Assuming you've got mingw installed, you could e.g.run `grep -rn CMakePredefinedTargets` in the build dir to verify it's only the solution file where the info is stored and the info used for building your targets is stored in the .vcxproj files.There's no effect on the results of `cmake --build ... --config ...` – fabian Aug 13 '22 at 06:33