第三方库应该放在哪里?

Where Should One Place Third Party Libraries?

这个问题似乎有点荒谬,但我正在努力为此寻找一个好的系统。是否有存储和组织第三方开发库的标准化系统?我深受强迫症困扰,认为自己是一个 "neat-freak," 所以我倾向于使用大量 directories/subdirectories 来组织项目,但由于我是一个新的开发人员,我最近才开始涉足第 3 方库,我不确定如何组织它们。我会使用大量文件夹并制作一个巨大的层次结构,但这样做可能会导致我的源代码 #includes 中出现一些非常长的绝对路径。有什么建议吗?

您有 2 个选择:

  1. 使用 system-installed 库(和 headers),告诉编译器在哪里可以找到它们。
  2. 在你的项目中使用一个文件夹(使用文件夹./external来存储外部源,例如./external/boost-asio用于Boost ASIO库),在初始化项目时下载源(我更喜欢使用git submodules 下载外部资源),并使用您的项目构建它们。

CMAKE 是一个可以帮助您实现这两个目标的构建工具。

无论哪种方式,正如 jtbandes 所写,不要使用绝对路径。

第三方库可以随心所欲,只要你确保编译器和编译后的程序都能找到它们需要的文件。因此,您可以随心所欲地组织文件,只要您确保将此告知编译器和已编译程序即可。

具体如何执行此操作取决于您使用的 IDE(集成开发环境)。我使用 visual studio,因此如果您使用其他术语,确切的术语可能会有所不同。在 visual studio 中,您必须转到项目的属性才能执行此操作。

对于外部库的头文件,转到配置属性 > C/C++ > 常规,然后单击 "Additional Include Directories"。如果编辑此字段的值,则可以将路径添加到外部库的包含目录,该目录应包含外部库的所有头文件。通过使用 Visual Studio 提供的宏,您可以使这些路径成为相对路径,这样您就不必在每次移动项目时都重新执行此操作。确保您没有删除“%(AdditionalIncludeDirectories)”。还要确保 window 顶部的所选配置和平台与您尝试编译的配置和平台相匹配。使用宏,您可以同时为所有配置和平台设置它,这有点困难,但它会在长 运行 中节省您的时间。来自我的一个项目的示例:

$(SolutionDir)dependencies\SDL2_image-2.0.1\include;$(SolutionDir)dependencies\SDL2-2.0.5\include;%(AdditionalIncludeDirectories)

对于库文件,您需要转到“配置属性”>“链接器”>“常规”,然后单击 "Additional Library Directories"。编辑此值以将路径添加到外部库的 lib 文件夹。您可以在这里再次使用宏。

$(SolutionDir)dependencies\SDL2-2.0.5\lib\x64;$(SolutionDir)dependencies\SDL2_image-2.0.1\lib\x64;%(AdditionalLibraryDirectories)

接下来,转到配置属性 > 链接器 > 输入并编辑 "Additional Dependencies" 以添加所需的 .lib 文件的名称。这次只是文件名,你不需要这里的路径。来自我的一个项目的示例:

SDL2main.lib;SDL2.lib;SDL2_image.lib;%(AdditionalDependencies)

最后,您需要确保您编译的程序可以找到外部库的.dll 文件。为此,您可以随意使用 PATH 等系统变量,但我不建议这样做。我更喜欢使用 Post-Build Event。像这样的事件基本上是在编译程序后执行的一系列命令行命令。您可以通过转至配置属性 > 构建事件 > Post-构建事件并编辑 "Command Line" 来添加此事件。您可以在此处放置的示例来自我的一个项目,如下所示:

copy /Y "$(SolutionDir)dependencies\SDL2_image-2.0.1\lib$(PlatformTarget)\*.dll" "$(TargetDir)*.dll"
copy /Y "$(SolutionDir)dependencies\SDL2-2.0.5\lib$(PlatformTarget)\SDL2.dll" "$(TargetDir)SDL2.dll"
xcopy /Y /S /E /I "$(SolutionDir)assets" "$(TargetDir)assets"

请注意,我再次使用宏:$(SolutionDir)、$(PlatformTarget)、$(TargetDir)分别被配置和平台的每个组合替换为解决方案目录、平台目标和目标目录。