web-dev-qa-db-ja.com

Visual Studio 2015ランタイムの依存関係、またはユニバーサルCRTを取り除く方法

Visual Studio 2015を使用していくつかの.dllをコンパイルし、一部の古いWindows 7/64ビットに展開しようとしました。また、アプリケーションの起動に必要なDLLを推測してMSVCP140.DLLとVCRUNTIME140.DLLをコピーしようとしましたが、アプリケーションはvs2015 dllをロードできませんでした。何が間違っているかを分析し始めました-そして、依存関係ウォーカーは、以下のdllからの依存関係を示しました。

API-MS-WIN-CRT-MATH-L1-1-0.DLL
API-MS-WIN-CRT-HEAP-L1-1-0.DLL
API-MS-WIN-CRT-CONVERT-L1-1-0.DLL
API-MS-WIN-CRT-STRING-L1-1-0.DLL
API-MS-WIN-CRT-STDIO-L1-1-0.DLL
API-MS-WIN-CRT-RUNTIME-L1-1-0.DLL
API-MS-WIN-CRT-FILESYSTEM-L1-1-0.DLL
API-MS-WIN-CRT-TIME-L1-1-0.DLL

これは、CRTがdll/exeの起動を担当していることを最もよく理解しているため、高レベルのサービスを提供しないため、特に驚くべきことでした。

さて、それらを取り除く方法、または少なくとも最小限にする方法を見つけようとしました。

1つの記事が見つかりました: https://blogs.msdn.Microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/

それはリリース静的ライブラリについて言及している-だから私はそれらにリンクして* L1-1-0.DLL *依存性地獄を取り除くことができると思ったが、私が試したものに関係なく-私は成功しなかった。 libvcruntime.lib、libucrt.lib、libcmt.libに対してリンクしようとしましたが、リンカーオプション「/nodefaultlib:vcruntime.lib」を使用して無効にしようとし、さらにincludeディレクトリ$(UniversalCRT_IncludePath)を追加しようとしました。私はそれらがうまくいくと推測しようとしたので定義します-私の試みはどれも助けませんでした。

中間ソリューションとして、CRT dllが2つだけであるVisual Studio 2013の使用にフォールバックしました:msvcp120.dll、msvcr120.dll。

もちろん、おそらくVisual Studio 2015ランタイムをインストールすることをお勧めしますが、私たちの要件の1つは、スタンドアロンの実行可能ファイルをサポートすることです。これはインストールなしで機能します。

Visual Studio 2017が到着するのを待つ以外に私に何かお勧めはありますか?

23
TarmoPikaro

(2016年11月10日に更新)。

静的にリンクすることでユニバーサルCRTを取り除くことができます。後で説明しますが、ユニバーサルCRTをそのまま使用し続ける場合を見てみましょう。

記事によると https://blogs.msdn.Microsoft.com/vcblog/2015/03/03/introducing-the-universal-crt/ -ユニバーサルcrt dll配布可能ファイルを使用してアプリケーションを起動することが可能次のフォルダーから:C:\Program Files (x86)\Windows Kits\10\Redist\ucrt

合計1.8 Mbサイズの合計41個のファイルがリストにあります。 (64ビットプラットフォームの例)

もちろん、それだけでは十分ではありません。次のフォルダーからvcruntime140.dllとmsvcp140.dllが追加で必要になります:C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x64\Microsoft.VC140.CRT

そのため、アプリケーション以外に合計43個の追加のDLLを出荷します。

アプリケーション内でucrtライブラリを静的にコンパイルすることもできます。その後、43個のdllが不要になりますが、リンク後に静的リンクが必要かどうかは、アプリケーションによって異なります-使用されているdllとapiの数。一般的に、ucrtが2つの異なるdllにリンクされた後、必ずしも同じグローバルを互いに共有する必要はありません-エラーが発生する可能性があります。

Vcruntime.lib/msvcrt.libに対してリンクする必要がありますが、十分ではありません-余分な_VCRTIMP=および_ACRTIMP=は、ucrtから関数をプルするときに無効にする必要があるものを定義します。

Premake5を使用している場合、次のようにプロジェクトを構成できます。

defines { "_VCRTIMP="}
linkoptions { "/nodefaultlib:vcruntime.lib" }
links { "libvcruntime.lib" }

に続く:

defines { "_ACRTIMP="}
linkoptions { "/nodefaultlib:msvcrt.lib" }
links { "libcmt.lib" }

定義はMicrosoftによって文書化されていないため、将来変更される可能性があります。

独自のプロジェクトに加えて、プロジェクトで使用されているすべての静的ライブラリを再コンパイルする必要があります。

ブーストライブラリについて-b2.exe boostrapperを使用して、ブーストもコンパイルできました。

boost>call b2 threading=multi toolset=msvc-14.0 address-model=64 --stagedir=release_64bit --build-dir=intermediate_64but release link=static,shared --with-atomic --with-thread --with-date_time --with-filesystem define=_VCRTIMP= define=_ACRTIMP=

リンクの問題のトラブルシューティングを行う場合-未解決の__imp*関数名はdllimportキーワードを使用しているため-libvcruntime.libにリンクする場合は、__imp*参照。

4
TarmoPikaro

C/C++ > Code Generation > Runtime Libraryコンパイラオプションを設定することでこれを解決できました

  • デバッグ用:/MDdから/MTdまで
  • リリースの場合:/MDから/MTまで

これにより、すべてのAPI-MS-WIN-CRT-*およびランタイムdll参照が削除され、すべてのCRTコードが静的にリンクされました。

新しいVS2015ユニバーサルCRT(動的および静的)の詳細はこちら: https://msdn.Microsoft.com/en-us/library/abx4dbyh.aspx

27
Ton Plooij

私も、MSVCRT、UCRT、およびカーネルのさまざまな部分から関数をインポートする複数のコンポーネント/プロジェクトライブラリの依存関係とソリューションを静的にリンクすることで戦いました。結果のEXEを必要な場所にコピーするだけでよいと期待されていました(MSIの完全インストールを正当化する製品はありませんでした)。

ほとんどあきらめた後、私は最良の解決策が niversal C Runtimeアナウンスメント に隠されたガイドラインに従うことであることに気付きました。具体的には:

パフォーマンスと保守性の両方の理由から、Visual C++ライブラリの静的リンクを強くお勧めします

試したすべての「特別な」リンカオプションを削除し、/ MT |/MD(マルチスレッドCRT DLLリリース|デバッグ)ランタイムライブラリの選択にドロップバックします。 Windows 10ワークステーション、2012 R2サーバー、Windows 7)。単にインストール/再配布 MSVCRT(VC_Redist * .exe) および KB2999226(Windows Update経由のUCRT)

ユニバーサルCRTは、Windowsオペレーティングシステムのコンポーネントです。 1月のテクニカルプレビュー以降、Windows 10の一部として含まれており、Windows Updateを介して古いバージョンのオペレーティングシステムで使用できます。

したがって、論理的には、C++ソリューションが顧客に追加する唯一の追加の展開依存関係はMSVCRTです。これは、UCRTが既に最新の/適切にメンテナンスされたマシン上に存在する必要があるためです。もちろん、それは少し不確実性を追加します。 EXEをコピーして、良いマシンでも悪いマシンでも実行することはできません。

MSIのような適切な展開パッケージを作成する場合、WIXのようなツールがある場合は簡単に含めることができます。また、最近のSDKには40奇数のDLLをローカルに含めることができますが、セキュリティ更新の原則を満たしていないため、私はそうしません。

これが実際にサポートされている唯一の方法です 別の例を参照 。また、この記事では、「mincore_downlevel.lib」にリンクすることをお勧めします。これは、これらの「api-ms-win *」の欠落DLLエラー。

  1. Project SDKバージョン10に設定、mincore.libとリンク= Windows 10でのみ実行されますが、8.1/2012 R2またはWindows 7/2008 R2サーバーでは実行されません。
  2. Project SDKバージョン8.1に設定、mincore.libとのリンク= Windows 10と8.1/2012 R2サーバーの両方で実行されますが、Windows 7/2008 R2サーバーでは実行されません。
  3. 10に設定されたプロジェクトSDKバージョンmincore_downlevel.libとのリンク=すべてで実行!

要約すれば:

  1. 静的にリンクしないで、デフォルトのDLL Cランタイムをプロジェクト設定で選択したままにします。
  2. 古いSDKは不要で、最新のWindows 10 SDKで開発できますが、古いWindowsバージョンをサポートする場合は、「mincore.lib」ではなく「mincore_downlevel.lib」とリンクする必要があります。
  3. 使いやすくするために、これをtargetver.hまたはstdafx.hに追加します。これも選択を文書化しています(他の行を削​​除します)。
// Libraries
#pragma comment(lib, "mincore.lib")             // Lowest OS support is same as SDK
#pragma comment(lib, "mincore_downlevel.lib")   // Support OS older than SDK
8
Tony Wall

Visual Studio 2015でビルドされたアプリケーションの実行に必要なランタイムDLLを見つけるのに苦労しました。

ここで、VS-2015ビルドアプリケーションの実行を許可する次のことがわかりました。

注:システムプロセッサのアーキテクチャ(x86、x64 ..)に従ってDLLバージョンを配置します。

1
Nilesh Sironja