57946
## 背景

ポータブルなライブラリ環境を構築するために、必要なライブラリをまとめたNuGetパッケージの作成を行っています。

[C++プロジェクトでNuGetを使ってみようよ！（Vol. 2：パッケージ作成編） -
Qiita](https://qiita.com/nia_tn1012/items/0815e1f493ac49d20d41)

参考にした上記サイトの通り、プログラムの実行まで行えましたが、もう少し機能の充実を図りたいと考えています。

## 質問

追加したい機能を優先度順で列挙すると以下のようになります。

  1. exeがあるフォルダに必要なdllが自動でコピーされる 
  2. DebugとReleaseのモードによってリンクするライブラリがあるパスを変える
  3. pragma comment をしなくても.libファイルがリンクできている

これらの機能を追加するには、どのようにパッケージを作成すればよいでしょうか?

## 取り組んだ内容

2と3については、VisualStudioが生成した.vcxprojファイルを参考にして以下の.targetsファイルを作成しました。

```

    <?xml version="1.0" encoding="utf-8"?>
    <Project DefaultTargets="Build" ToolsVersion="4.0" 
        xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
        <ImportGroup Label="PropertySheets"/>
        <PropertyGroup>
        </PropertyGroup>
        <ItemDefinitionGroup>
            <!-- プロジェクトファイルの「構成プロパティ」→「C++」に該当します。 -->
            <ClCompile>
                <!-- マクロを「HAS_NUGETOPENCV」を定義します。 -->
                <PreprocessorDefinitions>HAS_NUGETOPENCV;%(PreprocessorDefinitions)</PreprocessorDefinitions>
                <!-- 追加のインクルードディレクトリに追加するフォルダーを指定します。 -->
                <AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)../../build/native/include/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
            </ClCompile>
            <!-- プロジェクトファイルの「構成プロパティ」→「リンカー」に該当します。 -->
            <Link>
                <!-- 追加のライブラリディレクトリに追加するフォルダーを指定します。 -->
                <AdditionalLibraryDirectories>$(MSBuildThisFileDirectory)../../build/native/lib/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
            </Link>
    
            <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
                <Link>
                    <AdditionalDependencies>opencv_world400.lib;%(AdditionalDependencies)</AdditionalDependencies>
                </Link>
            </ItemDefinitionGroup>
            <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
                <Link>
                    <AdditionalDependencies>opencv_world400d.lib;%(AdditionalDependencies)</AdditionalDependencies>
                </Link>
            </ItemDefinitionGroup>
        </ItemDefinitionGroup>
    </Project>
    
```

しかし、コンパイル時にリンクエラーが発生してしまい、.libファイルのリンクが適切にできませんでした。

## 現状

### パッケージフォルダ構成

.nuspec .props .targets ファイルは参考サイトのパスに保存しています。

```

    OpencvNuget
    └─build
        └─native
            ├─include
            │  └─opencv2
            └─lib
               ├─opencv_world400.lib
               └─opencv_world400d.lib
    
```

### パッケージの構成ファイル

OpencvNuget.nuspec

```

    <?xml version="1.0"?>
    <package >
      <metadata>
        <id>OpencvNuget</id>
        <version>1.0.1</version>
        <authors>name</authors>
        <owners>name</owners>
        <requireLicenseAcceptance>false</requireLicenseAcceptance>
        <description>Opencv Sample</description>
        <releaseNotes>first commit</releaseNotes>
        <copyright>Copyright 2019</copyright>
        <tags>c++ NuGetTest</tags>
      </metadata>
    </package>
    
```

propsファイルは参考サイトと同一であるため割愛します。
CC BY-SA 4.0
2019-09-04T15:02:56.047
57846
2019-09-10T07:17:27.333
2019-09-09T07:36:08.127
3060
19500
question
c++ visual-studio dll
NuGetでC++パッケージを作成したい
自己解決しました。

targetsファイルを次のように編集することで要求1と3に対応しています。

```

        <?xml version="1.0" encoding="utf-8"?>
    <Project DefaultTargets="Build" ToolsVersion="4.0" 
        xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
        <ImportGroup Label="PropertySheets"/>
        <PropertyGroup>
        </PropertyGroup>
        <ItemDefinitionGroup>
            <!-- プロジェクトファイルの「構成プロパティ」→「C++」に該当します。 -->
            <ClCompile>
                <!-- マクロを「HAS_NUGETOPENCV」を定義します。 -->
                <PreprocessorDefinitions>HAS_NUGETOPENCV;%(PreprocessorDefinitions)</PreprocessorDefinitions>
                <!-- 追加のインクルードディレクトリに追加するフォルダーを指定します。 -->
                <AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)../../build/native/include/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
            </ClCompile>
            <!-- プロジェクトファイルの「構成プロパティ」→「リンカー」に該当します。 -->
            <Link>
                <!-- 追加のライブラリディレクトリに追加するフォルダーを指定します。 -->
                <AdditionalLibraryDirectories>$(MSBuildThisFileDirectory)../../build/native/lib/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
            </Link>
    
            <!-- 要求2と3 libの自動リンク -->
        </ItemDefinitionGroup>
        <!-- ConfigureとPlatformで場合わけ -->
        <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
            <Link>
                <!-- 追加の依存ライブラリに追加して自動リンク -->
                <AdditionalDependencies>opencv_world343.lib;%(AdditionalDependencies)</AdditionalDependencies>
            </Link>
        </ItemDefinitionGroup>
        <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
            <Link>
                <AdditionalDependencies>opencv_world343d.lib;%(AdditionalDependencies)</AdditionalDependencies>
            </Link>
        </ItemDefinitionGroup>
        <!-- 要求1 dllの自動コピー -->
        <ItemGroup>
            <!-- dllのあるフォルダパスを指定 -->
            <NativeLibs Include="$(MSBuildThisFileDirectory)../../build/native/lib/*.dll" />
            <None Include="@(NativeLibs)">
                <Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
                <!-- 出力フォルダにdllを自動で上書き -->
                <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
            </None>
        </ItemGroup>
    
    </Project>
    
```

自動リンクがうまく作用しなかったのは、`</ItemDefinitionGroup>`を入れ子に記述していたからでした。  
Configureでリンク先フォルダの分岐はこのファイルではできていませんが、の部分も条件分岐の中に含めることで可能であると考えております。

dllの自動コピーは、質問文の「パッケージフォルダ構成」中のlibフォルダに、必要なdllファイルをすべて保存していることを前提としています。

参考にしたサイト

[stackoverflow: Add native files from NuGet package to project output
directory](https://stackoverflow.com/questions/19478775/add-native-files-from-
nuget-package-to-project-output-directory)
CC BY-SA 4.0
2019-09-09T07:06:06.453
57946
2019-09-10T07:17:27.333
2019-09-10T07:17:27.333
3060
19500
57846
answer