Adr*_*vry 10 c++ architecture project solution visual-studio
这个问题仅涉及Visual Studio C++ 项目/解决方案配置,可能涉及主观性。
然而,这篇文章背后的想法是分享我们配置大型 Visual Studio 解决方案的方法。
我不考虑任何像CMake/Premake这里 的工具。
我是一家视频游戏公司的软件开发人员,所以我将用一个非常简化的游戏引擎架构来说明我的话:
我的 Visual Studio 解决方案可能如下所示:
其中Application是可执行文件,其他所有项目都是库(动态链接)。
我的方法是将每个项目分成两个文件夹:include,src
内部结构将分为我的命名空间后面的文件夹:
以下行将假设只有一个$(Configuration)可用$(Platform)(例如:Release-x64),并且为每个项目完成了对 .lib 文件的引用Linker/Input/Additional Dependencies。
我将在这里定义一个Bin(输出)、Bin-Int(中间输出)和Build(组织输出)文件夹,假设它们位于$(SolutionDir):
$(SolutionDir)Bin\$(SolutionDir)Bin-Int\$(SolutionDir)Build\和文件夹是编译器的游乐场,而该文件夹由每个项目构建后事件填充Bin:Bin-IntBuild
$(SolutionDir)Build\$(ProjectName)\include\(项目包括)$(SolutionDir)Build\$(ProjectName)\lib\(.lib 文件)$(SolutionDir)Build\$(ProjectName)\bin\(.dll 文件)这样,每个都$(SolutionDir)Build\$(ProjectName)\可以作为独立的库进行共享。
注意:以下说明可能会跳过$(SolutionDir)文件Build夹路径以简化阅读。
如果B依赖于A,Build\B\include\则将包含B并A包括。同样的方式,Build\B\bin\将包含B和A二进制文件,Build\B\lib\并将包含B和A.lib 文件(当且仅当B可以A向用户公开时,否则,仅B将 .lib 文件添加到Build\B\lib\)。
项目相对于Build\文件夹引用自身。因此,如果B依赖于A,B则 include 路径将引用$(SolutionDir)Build\A\include\(而不是$(SolutionDir)A\include\),因此 所使用的任何包含都A将可用B,而无需明确指定。(但结果取决于章节2.6.2.和技术2.6.3.限制2.6.4.)。
之后,我确保我的解决方案具有正确的Project Dependencies配置,以便Build Order在构建整个解决方案时,将考虑并尊重我的项目依赖项。
我们的EngineSDK用户(正在处理Application)只需进行Application如下设置:
$(SolutionDir)Build\Engine\include\$(SolutionDir)Build\Engine\lib\$(SolutionDir)Build\Engine\bin\*到$(OutDir)这是很多C++库的典型Visual Studio配置流程。
我尝试保留的通用库文件夹架构:
lib\
include\
bin\
Run Code Online (Sandbox Code Playgroud)
以下是使用此文件夹架构模型的库的一些示例(请注意,这bin专门用于动态链接库,因为静态链接库不关心 DLL):
$(SolutionDir)Build\我在这里写的方法有一些缺点。这些限制是这篇文章的原因,因为我想提高自己:
处理 10 个或更少的项目没问题,但是,处理更大的解决方案(15 个以上项目)时,它很快就会变得一团糟。项目配置非常严格,项目架构的微小变化可能会导致项目配置和调试花费数小时。
让我们考虑一个简单的依赖情况:
C依赖于B且B依赖于A。C是可执行文件, 和B是A库B和A构建后事件更新其Build\$(ProjectName)\目录当更改 的源代码A,然后编译它时,Build\A\就会更新。但是,正如B之前编译的那样(A更改之前),其Build\B\文件夹包含以前的二进制文件的副本A并包含。因此,执行C(仅作为依赖B项)将使用旧的A二进制文件/包含文件。我发现这个问题的解决方法是在执行之前手动触发B构建后事件C。然而,忘记在构建后触发中间项目可能会导致调试过程中的麻烦(未加载符号、错误行为......)。
这种方法的另一个限制是“多次单个标头引用”。
这个问题可以通过考虑 2.1 节中的项目依赖关系图像来解释。。考虑到Graphics和Physics都包含Maths标头,即Engine包含Build\Graphics\include\和Build\Physics\include\,输入标头名称将显示多个相同的结果:
如果B依赖A并且任何标头发生更改A(例如,我们添加一个新函数),则需要Rescan File/才能从 访问新符号。Rescan SolutionB
此外,导航到文件或符号可能会使我们移动到错误的标题(复制的标题而不是原始的标题)。
在我的 Visual Studio 软件开发之旅中,我经历了项目Reference概念,但我找不到它如何解决我当前方法的技术限制,也找不到它如何帮助我重新思考它。
由于我的解决方案的每个项目配置都遵循相同的原则,但每个项目的内容(包括目录、库目录...)都不同,我不确定如何充分利用属性表。
目前我正在努力寻找一些好的项目架构参考。我很高兴在 GitHub 或任何代码共享平台上找到一些 Visual Studio 配置的解决方案。(我知道这一点CMake,并且Premake在大多数情况下共享代码时更喜欢,但是,了解有关 Visual Studio 项目配置的更多信息是我的实际目标)。
感谢您阅读我的文字,我希望您也有兴趣讨论这个主题,也许我们可以分享我们的方法。