使用 Visual Studio/MSBuild 创建你的第一个 Conan 包

创建你的第一个 Conan 包教程 中,使用了 CMake 作为构建系统。如果你还没有阅读那一部分,请先阅读它以熟悉 conanfile.pytest_package 的概念,然后回来阅读关于 Visual Studio 包创建的具体细节。

使用 conan new 命令创建一个“Hello World”C++ 库示例项目

$ conan new msbuild_lib -d name=hello -d version=1.0

这将创建一个具有以下结构的 Conan 包项目。

.
├── conanfile.py
├── hello.sln
├── hello.vcxproj
├── include
│   └── hello.h
├── src
│   └── hello.cpp
└── test_package
    ├── conanfile.py
    ├── test_hello.sln
    ├── test_hello.vcxproj
    └── src
        └── test_hello.cpp

结构和文件与之前的 CMake 示例非常相似

  • conanfile.py:在根文件夹中,有一个 conanfile.py,它是主要的配方文件,负责定义如何构建和使用包。

  • hello.sln:一个 Visual Studio 解决方案文件,可以用 IDE 打开。

  • hello.vcxproj:一个 Visual Studio C/C++ 项目,是上面解决方案的一部分。

  • srcinclude 文件夹:包含简单的 C++ “hello” 库的文件夹。

  • test_package 文件夹:包含一个 示例 应用程序,它将需要并链接到创建的包。在本例中,test_package 也包含一个 Visual Studio 解决方案和项目,但如果需要,也可以让 test_package 使用其他构建系统,例如 CMake。test_package 使用与包相同的构建系统并不是强制性的。

让我们看一下包配方 conanfile.py(仅包含相关的部分)

# Sources are located in the same place as this recipe, copy them to the recipe
exports_sources = "hello.sln", "hello.vcxproj", "src/*", "include/*"

def layout(self):
    vs_layout(self)

def generate(self):
    tc = MSBuildToolchain(self)
    tc.generate()

def build(self):
    msbuild = MSBuild(self)
    msbuild.build("hello.sln")

def package(self):
    copy(self, "*.h", os.path.join(self.source_folder, "include"),
         dst=os.path.join(self.package_folder, "include"))
    copy(self, "*.lib", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"),
         keep_path=False)

让我们简要解释一下配方的不同部分

  • 请注意,此配方中没有像 shared 选项这样的 options。当前项目始终构建静态库,因此它不是可选的。

  • layout() 定义了一个典型的 VS 布局,这比 CMake 布局不太灵活,因此它不允许任何参数化。

  • generate() 方法调用 MSBuildToolchain 生成一个 conantoolchain.props 文件,项目必须将其添加到其属性中。如果项目具有 Conan requires 依赖项,则它也应该添加 MSBuildDeps 并添加相关的生成文件属性表。

  • build() 方法使用 MSBuild() 辅助函数来驱动解决方案的构建

  • 由于项目在构建脚本中没有任何“安装”功能,因此 package() 方法可以手动定义必须复制哪些文件。

hello.vcxproj 项目文件将生成的属性表(如 conantoolchain.props)添加到项目中,以便构建可以接收 Conan 输入 settings 并相应地采取行动。

hello.vcxproj
 <ImportGroup Label="PropertySheets">
   <Import Project="conan\conantoolchain.props" />
 </ImportGroup>

如果项目有依赖项,则也应该添加依赖项生成的 .props 文件。

test_package 文件夹还包含一个 test_hello.vcxproj 文件,它包含工具链和依赖项属性表。

test_package/test_hello.vcxproj
<ImportGroup Label="PropertySheets">
    <Import Project="conan\conantoolchain.props" />
    <Import Project="conan\conandeps.props" />
</ImportGroup>

请注意,test_package/conanfile.py 也包含一个 generators="MSBuildDeps"

让我们使用当前默认配置从源代码构建包,然后让 test_package 文件夹测试包

$ conan create .

...
======== Testing the package: Executing test ========
hello/1.0 (test package): Running test()
hello/1.0 (test package): RUN: x64\Release\test_hello
hello/1.0: Hello World Release!
  hello/1.0: _M_X64 defined
  hello/1.0: MSVC runtime: MultiThreadedDLL
  hello/1.0: _MSC_VER1939
  hello/1.0: _MSVC_LANG201402
  hello/1.0: __cplusplus199711
hello/1.0 test_package

现在我们可以验证配方和包二进制文件是否在缓存中

$ conan list hello/1.0:*
Local Cache:
  hello
    hello/1.0
      revisions
        856c535669f78da11502a119b7d8a6c9 (2024-03-04 17:52:39 UTC)
          packages
            c13a22a41ecd72caf9e556f68b406569547e0861
              info
                settings
                  arch: x86_64
                  build_type: Release
                  compiler: msvc
                  compiler.cppstd: 14
                  compiler.runtime: dynamic
                  compiler.runtime_type: Release
                  compiler.version: 193
                  os: Windows