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が到着するのを待つ以外に私に何かお勧めはありますか?
(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*
参照。
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
私も、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エラー。
要約すれば:
// Libraries
#pragma comment(lib, "mincore.lib") // Lowest OS support is same as SDK
#pragma comment(lib, "mincore_downlevel.lib") // Support OS older than SDK
Visual Studio 2015でビルドされたアプリケーションの実行に必要なランタイムDLLを見つけるのに苦労しました。
ここで、VS-2015ビルドアプリケーションの実行を許可する次のことがわかりました。
注:システムプロセッサのアーキテクチャ(x86、x64 ..)に従ってDLLバージョンを配置します。