title: Visual Studio C++ Multiple Project Solution Setup
body: <h1>0. Disclaimer</h1>
  
  <p>This question is only about <strong>Visual Studio C++ project/solution configuration</strong> and may involve subjectivity.</p>
  
  <p>However, the idea behind this post is to share our approaches to configure a large Visual Studio solution.</p>
  
  <p>I'm not considering any tool like <code>CMake</code>/<code>Premake</code> here.</p>
  
  <h1>1. Problem</h1>
  
  <ul>
  <li>How do you handle a large scaled C++ application architecture and configuration using Visual Studio?</li>
  <li>What is, for you, the best way to setup a new Visual Studio solution composed of multiple projects?</li>
  <li>What Visual Studio project/solution configuration feature are you trying to avoid? (<em>Ex: Filters instead of folders</em>)</li>
  </ul>
  
  <h1>2. Personnal approach</h1>
  
  <h2>2.1. Context</h2>
  
  <p>I'm a software developer for a video game company, so I will take a very simplified game engine architecture to illustrate my words:</p>
  
  <p><a href="https://i.stack.imgur.com/AJsZd.png" rel="noreferrer"><img src="https://i.stack.imgur.com/AJsZd.png" alt="enter image description here"></a></p>
  
  <h2>2.2. File Structure</h2>
  
  <p>My Visual Studio solution would probably look something like this:</p>
  
  <p><a href="https://i.stack.imgur.com/bEk2g.png" rel="noreferrer"><img src="https://i.stack.imgur.com/bEk2g.png" alt="enter image description here"></a></p>
  
  <p>Where <code>Application</code> is an <em>executable</em> and every other projects are <em>libraries</em> (Dynamically linked).</p>
  
  <p>My approach would be to separate each project into two folders: <code>include</code>, <code>src</code></p>
  
  <p><a href="https://i.stack.imgur.com/kSrn9.png" rel="noreferrer"><img src="https://i.stack.imgur.com/kSrn9.png" alt="enter image description here"></a></p>
  
  <p>And the inner structure would be separated into folders following my namespaces:</p>
  
  <p><a href="https://i.stack.imgur.com/cmUD6.png" rel="noreferrer"><img src="https://i.stack.imgur.com/cmUD6.png" alt="enter image description here"></a></p>
  
  <h2>2.3. Project Configuration</h2>
  
  <p><em>The following lines will assume there is only one <code>$(Configuration)</code> and <code>$(Platform)</code> available (Ex: <code>Release-x64</code>) and that referencing .lib files into <code>Linker/Input/Additional Dependencies</code> is done for each project.</em></p>
  
  <p>I would here define a <code>Bin</code> (Output), <code>Bin-Int</code> (Intermediate output) and <code>Build</code> (Organized output) folder, let's say they are located in <code>$(SolutionDir)</code>:</p>
  
  <ul>
  <li><code>$(SolutionDir)Bin\</code></li>
  <li><code>$(SolutionDir)Bin-Int\</code></li>
  <li><code>$(SolutionDir)Build\</code></li>
  </ul>
  
  <p>The <code>Bin</code> and <code>Bin-Int</code> folders are playgrounds for the compiler, while the <code>Build</code> folder is populated by each project post-build event:</p>
  
  <ul>
  <li><code>$(SolutionDir)Build\$(ProjectName)\include\</code> (Project includes)</li>
  <li><code>$(SolutionDir)Build\$(ProjectName)\lib\</code> (.lib files)</li>
  <li><code>$(SolutionDir)Build\$(ProjectName)\bin\</code> (.dll files)</li>
  </ul>
  
  <p>This way, each <code>$(SolutionDir)Build\$(ProjectName)\</code> can be shared as an independent library.</p>
  
  <p><em>Note: Following explainations may skip <code>$(SolutionDir)</code> from the <code>Build</code> folder path to simplify reading.</em></p>
  
  <p>If <code>B</code> is dependent of <code>A</code>, <code>Build\B\include\</code> will contain <code>B</code> and <code>A</code> includes. The same way, <code>Build\B\bin\</code> will contain <code>B</code> and <code>A</code> binaries and <code>Build\B\lib\</code> will contain <code>B</code> and <code>A</code> .lib files (If and only if <code>B</code> is ok to expose <code>A</code> to its user, otherwise, only <code>B</code> .lib files will be added to <code>Build\B\lib\</code>).</p>
  
  <p>Projects reference themselves relatively to <code>Build\</code> folders. Thus, if <code>B</code> is dependent of <code>A</code>, <code>B</code> include path will reference <code>$(SolutionDir)Build\A\include\</code> (And not <code>$(SolutionDir)A\include\</code>), so any include used by <code>A</code> will be available for <code>B</code> without specifying it explicitly. (But result to sections <code>2.6.2.</code>, <code>2.6.3.</code> and <code>2.6.4.</code> technical limitations).</p>
  
  <p>After that, I make sure that my solution has a proper <code>Project Dependencies</code> configuration so the <code>Build Order</code>, when building the whole solution, will consider and respect my project dependencies.</p>
  
  <h2>2.4. User Project Configuration</h2>
  
  <p>Our <code>EngineSDK</code> user (Working onto <code>Application</code>) will only have to setup <code>Application</code> such as:</p>
  
  <ul>
  <li><strong>Include Directories</strong>: <code>$(SolutionDir)Build\Engine\include\</code></li>
  <li><strong>Library Directory</strong>: <code>$(SolutionDir)Build\Engine\lib\</code></li>
  <li><strong>Post-build</strong>: Copy <code>$(SolutionDir)Build\Engine\bin\*</code> to <code>$(OutDir)</code></li>
  <li><strong>Additional Dependencies</strong>: Any .lib file upstream in the dependency hierarchy is listed here</li>
  </ul>
  
  <p>This is the typical  Visual Studio configuration flow of a lot of C++ library.</p>
  
  <p><em>Common library folder architecture that I try to preserve:</em></p>
  
  <pre><code>lib\
  include\
  bin\
  </code></pre>
  
  <p>Here are some example of libraries using this folder architecture model (Do note that <code>bin</code> is exclusively for dynamically linked libraries as statically linked libraries don't bother with DLLs):</p>
  
  <ul>
  <li>SFML: <a href="https://www.sfml-dev.org/" rel="noreferrer">https://www.sfml-dev.org/</a></li>
  <li>SDL: <a href="https://www.libsdl.org/" rel="noreferrer">https://www.libsdl.org/</a></li>
  </ul>
  
  <h2>2.5. Advantages</h2>
  
  <ul>
  <li>Clear folder architecture</li>
  <li>Ability to export a library directly by copy-pasting or zipping a sub-folder of <code>$(SolutionDir)Build\</code></li>
  </ul>
  
  <h2>2.6. Technical limitations</h2>
  
  <p>The approach I wrote here has some drawbacks. These limitations are the reason of this post as I want to improve myself:</p>
  
  <h3>2.6.1. Tedious configuration</h3>
  
  <p>Dealing with 10 or less projects is fine, however, with bigger solutions (15+ projects), it can quickly become a mess. Project configurations are very rigid, and a small change in project architecture can result into hours of project configuration and debugging.</p>
  
  <h3>2.6.2. Post-build limitation</h3>
  
  <p>Let's consider a simple dependency case:</p>
  
  <ul>
  <li><code>C</code> is dependent of <code>B</code> and <code>B</code> is dependent of <code>A</code>.</li>
  <li><code>C</code> is an executable, and <code>B</code> and <code>A</code> are libraries</li>
  <li><code>B</code> and <code>A</code> post-build events update their <code>Build\$(ProjectName)\</code> directory</li>
  </ul>
  
  <p>When changing the source code of <code>A</code>, then compiling it, <code>Build\A\</code> will get updated. However, as <code>B</code> has been previously compiled (Before <code>A</code> changes), its <code>Build\B\</code> folder contains a copy of previous <code>A</code> binaries and includes. Thus, executing <code>C</code> (Which is only aware of <code>B</code> as a dependency), will use old <code>A</code> binaries/includes. A workaround I found for this problem is to manually trigger <code>B</code> post-build event before executing <code>C</code>. However, forgetting to trigger an intermediate project post-build can result into headaches during debugging (Not loaded symbols, wrong behaviour...).</p>
  
  <h2>2.6.3. Multiple times single header reference</h2>
  
  <p>Another limitation for this approach is "Multiple times single header reference".</p>
  
  <p>This problem can be explained by considering the project dependency image at section <strong>2.1.</strong>.
  Considering that <code>Graphics</code> and <code>Physics</code> are both including <code>Maths</code> headers, and that <code>Engine</code> is including <code>Build\Graphics\include\</code> and <code>Build\Physics\include\</code>, typing a header name will show multiple identical results:</p>
  
  <p><a href="https://i.stack.imgur.com/GzH3x.png" rel="noreferrer"><img src="https://i.stack.imgur.com/GzH3x.png" alt="enter image description here"></a></p>
  
  <h2>2.6.4. De-synchronized symbol referencing</h2>
  
  <p>If <code>B</code> is dependent of <code>A</code> and any header changes in <code>A</code> (for instance, we add a new function), <code>Rescan File</code>/<code>Rescan Solution</code> will be needed to access the new symbol from <code>B</code>.</p>
  
  <p>Also, navigating to files or symbol can make us move to the wrong header (Copied header instead of the original one).</p>
  
  <h1>3. Interrogations and learning perspectives</h1>
  
  <h2>3.1. Project Reference</h2>
  
  <p>During my Visual Studio software developer journey, I came through the project <code>Reference</code> concept, but I can't find how it can solve the technical limitations of my current approach, nor how it can helps me to re-think it.</p>
  
  <h2>3.2. Property sheets</h2>
  
  <p>As every project configuration of my solution is following the same principle but the content (Include dirs, library dirs...) for each one is different, I'm not sure how to make a great usage of property sheets.</p>
  
  <h2>3.3. Exploring GitHub</h2>
  
  <p>Currently I'm struggling finding some good project architecture references. I would be pleased finding some Visual Studio configured solution on GitHub or any code sharing platform. (I know that <code>CMake</code> and <code>Premake</code> are prefered in most case when sharing code, however, learning more about Visual Studio project configuration is my actual goal).</p>
  
  <p>Thanks for reading my words, I hope that you are also interested into discussing about this subject and maybe we can share our approaches.</p>