web-dev-qa-db-ja.com

ソースコードとプリコンパイルされたバイナリを切り替える

アプリケーションには膨大な量のライブラリがあります。ライブラリは、c ++またはc#で記述されます。 (プラットフォーム:.netフレームワーク、Windows、64ビット)ソースコードとしてすべてをコンパイルするには、多くの時間がかかります。ビルド済みのバイナリに切り替えることを考えていましたが、ソースコードに戻る可能性を残したいと考えています。 gitを使用するバージョン管理システムとして、Azureの開発者がビルドを実行できます。必要に応じてカスタムサーバーを設定できます。

パッケージ管理用に用意されている既成のツールにはどのようなものがありますか?ソースコードとビルド済みのバイナリを簡単に切り替える可能性はありますか? (ツールが両方のプログラミング言語と互換性がない場合-1つの言語のみのツールセットを指定してもかまいません。)そのようなツールが存在しない場合、自分で推奨するもの-使用するパッケージの種類、書き込むスクリプトの種類その上?

API/Abiブレークを特定することは可能ですか?

4
TarmoPikaro

この問題には複数の軸があります。ソースコードのビルド、パッケージのインストール、外部リポジトリ、api/abiの中断、システム自体のビルドです。

まず最初にあなたの要件-あなたはパッケージングやインストールにも興味がありますか?.

それ自体をパッケージ化するために、たとえば次のパッケージングシステムを使用することが可能です:_nuget, conan, vcpkg, choco_。

ほとんどの場合、パッケージ自体を公開するだけでなく、それらのシンボルをデバッグすることにも関心があります。

Azure devopsの場合、デバッグシンボルの公開に関するドキュメントは、たとえば次のリンクから入手できます。

https://Azure.Microsoft.com/en-us/blog/deep-dive-into-Azure-artifacts/https://docs.Microsoft.com/en-us/nuget/create-packages/symbol-packages-snupkg

現在のところ、Conan(c ++パッケージ)はシンボルの発行をサポートしていません: https://github.com/conan-io/conan/issues/4047

ソースコードの配布を取得するには、git自体を使用できます。 Gitサブモジュールでは外部gitリポジトリ参照を作成できますが、外部サブモジュールを追加したら、ダブルコミットを使用してすべてを変更する必要があります-1つのgitコミットをサブリポジトリに、1つのgitコミットを使用してマスターリポジトリから参照されたgitハッシュを更新します。

確かに、このような問題のいくつかのウォークアラウンドが存在します:サブモジュールのないネストされたgit:

サブモジュールのないネストされたgitリポジトリ?

=>

http://debuggable.com/posts/git-fake-submodules:4b563ee4-f3cc-4061-967e-0e48cbdd56cb

ただし、ソースコードの代わりにビルド済みのバイナリを使用してメインリポジトリを構築する場合-理想的なソリューションでは、その外部gitリポジトリは不要です。つまり、外部リポジトリのgit clone /チェックアウトは必要ありません。

次に、_all-in-one solution_または複数のソリューションをそれぞれ個別にコンパイルすることもできます。

依存するソリューションのコンパイルの手間が少ないため、_all-in-one solution_を使用する方が確かに簡単です。

完全に動的なソリューションの生成を実現するために、たとえばcmakeを使用することができます-cmakeから使用される事前構成されたオプションに応じてソリューションを生成できます。 (cmakeの_"option"_を参照)。

cmakeは確かにC++(プリコンパイル済みヘッダーをサポートし、Unityビルドのスピードアップ)に代わる優れた代替手段ですが、C#の場合はそれほど簡単ではありません(必要なパラメーターを見つけて正しく構成する方法は難しい)。

現時点(2020年5月)ではcmakeに代わるものはまだ見つかっていませんが、cmakeと並行して進化する複数のツールとエコシステムがあるため、将来の可能性を観察する必要があります。

それから包装について。 chocoはnugetのサブセットのようです-ソフトウェアの更新をサポートする独自のxmlタグでnuspecを拡張します。 (参照されたWebページ: https://chocolatey.org/https://docs.Microsoft.com/en-us/nuget/reference/nuspec

Nugetパッケージまたはインストーラーパッケージを公開する場合は、nugetリポジトリを使用できます(追加費用なし)。

ニーズに不十分な場合は、nugetサーバーをchocoサーバーにアップグレードすることも可能ですが、コストがかかる可能性があります-チョコレートのWebページを参照してください。

実際のコンパイル/リンクエラーが発生するか、実行時にアプリケーションがクラッシュするまで、API/Abiブレークはどのレベルでも観察できません-可能な唯一の代替策は、パッケージ自体のバージョン管理を制御することです-したがって、マスターパッケージnuget(またはchoco)のバージョン依存するnuget(またはchoco)バージョンのより高いバージョンが必要になります。

メインリポジトリが子リポジトリと同じ人によって開発されている場合-開発者自身がapi/abiブレークを実行できますが、2つのgitが互いに独立していて、異なるチームが開発している場合-api/abiブレークは、時間。

リポジトリの一貫性を保証する最良の方法-マスターリポジトリのユニットテストを行うことです。これにより、api/abiブレークが発生しないことを確認します。

理論的には、api/abiが壊れた場合-ビルドシステム自体が2つのビルド代替案で続行できる-

  1. メインリポジトリを最後に機能する子リポジトリで追跡する
  2. メインリポジトリを構築せずに子リポジトリをフォローする

同じメカニズムをブランチを使用して適用できます。

  1. 「メインgit:マスターブランチ」+「子git:リリース/1.0ブランチ」
  2. 「子git:マスターブランチ」

これは、2つのリポジトリだけでなく、長期にわたる障害が発生した場合のブランチの切り替えも監視するために必要なメカニズムです。 (たとえば、子gitの開発チームはメインgitで発生するビルドブレークを気にしません)

この目的のための既製のツールは存在しないと思われます(表示される場合はコメントを残してください)。これには、潜在的に異なるgitリポジトリからの、潜在的に異なるgitリポジトリからの2つの潜在的に異なるビルドチェーンからの再接続ツールが必要になる場合があるためです。

そして最後に重要なことですが、アプリケーションをソフトウェア更新に対応させたい場合は、nuget/chocoディストリビューションダウンロードを追加のnuget/chocoサーバーで使用できます。

Nugetパッケージのダウンロードパーツの良い例を次に示します。 https://github.com/mwrock/NugetDownloadFeed

インストールパッケージのビルドはもう少し複雑な問題です-たとえば次のリンクを参照してください:

(私の意見に基づいて最も悪いものから)

1
TarmoPikaro

私はあなたの質問を読んで、依存関係は.NetまたはC++にあると言っています。最終的な出力ビルドは.Netです。 NuGetは、依存関係に関連するすべてのものの「標準」の.Netツールであることを知っています。

今。それは、ソースとバイナリを簡単に「切り替える」ことを考えて、何が正確に欲しいかに依存しますか?

ビルドサーバー上開発者マシン上を区別しません。あなたは確かに両方をできるだけ速くするためにバイナリからビルドしたいのですが、私はビルドサーバーにソースコードを望んでいることを理解できません:ソースコードは人間ではなくマシン用です。

オプション1.「バイナリのビルド速度を取得するが、ソースのデバッグエクスペリエンスを取得する」

これはNuGetで実現できます。 Azureを使用しているため、ライブラリビルドにタスクを追加して、プライベートAzure NuGetフィードに直接公開できます。その出発点は

あなたを語る

  1. フィードを設定する
  2. フィードに公開する
  3. フィードを消費する

Nuget publishはソースシンボルを含めることができるであるため、Nugetは完全な「デバッグ時のソースコード」体験を提供します。これはアンカーの同じページでカバーされています、

開発者のマシンで、ソリューション内のプロジェクトの依存関係をNuGetパッケージの依存関係に置き換えます。次に、次の通常のnugetエクスペリエンスを取得します。

  • NuGetは、マシンのフィードからコンパイルされた.dllをキャッシュします
  • NuGetは更新が利用可能になると通知します
  • いつ最新にするかを選択します。 OR always-update-on-buildを強制できます; ORあなたはalways-update-on-checkoutを強制できます。

Force update-on-checkoutを使用すると、(ほぼ)最新のコードを常に見るというソースコードスタイルのエクスペリエンスが得られますが、バイナリからのビルドはおそらく最速です。 git post-checkoutフックを追加してnuget updateを実行し、すべてのgit get latestが同時にnugetから最新になるように、強制的にupdate-on-git-checkoutを実行できます。 https://ddg.gg/example%20git%20oncheckout%20hook%20windows

(.Netシンボルファイルには最後のビルドに使用されたパスが含まれるため、開発者のマシンのライブラリに標準のチェックアウトパスを適用するのに役立つ場合があります。ただし、これには、ビルドサーバー。)

オプション2.つまり、「ソースからのビルドとバイナリからのビルドを簡単に切り替えることができる」

これは通常とは異なる要件であるため、すぐに使用できるソリューションはありません。 「シンプルな」アプローチは、個別のプロジェクトとソリューションを用意することです。代わりに、もう一度質問してくださいexactly何を達成しようとしているのですか?

最新のソースから確実にビルドしたい場合、Azureのnugetフィードには常に最新のビルドが含まれているため、ビルドサーバーと開発マシンの両方で、オプション1によってこれが既に解決されています(数秒かかります)。 。

(実際、自動テストを使用する場合、オプション1はソースからビルドするよりもbetterです。なぜなら、誰かが誤ってチェックインした最新のものではなく、「テストをビルドしてパスする最新のソース」を使用したからです。 '。)

「プロジェクトに完全なソースがあるが、高速ビルド」が必要な場合、これは自動的に行われる可能性があります。msbuildは、cmakeのように、プロジェクトがすでに最新の場合、プロジェクトを再ビルドしません。ただし、ビジュアルスタジオの開発者は、ビルドの代わりに再ビルド(=クリーン+ビルド)のキーストロークを常に覚えています。依存関係が大量にある場合、この1回のキーストロークを変更することを学ぶことで、すべての待機時間を節約できます。問題は、他の開発者が多くの変更を行っている場合、最新のソースと再構築の時間を回避できないことです。

開発マシンとビルドサーバーを構築するための異なるプロジェクトファイルを使用できます。これを維持するとエラーが発生しやすくなるため、script標準のものからビルドサーバーのcsprojファイルを自動生成する必要があります。その後、ビルドサーバーはnugetから依存関係を取得できますが、開発マシンはソースandを使用し、正常にビルドされたライブラリの更新をnugetフィードにプッシュします。

コメント:両方の世界の中でどれほど近づくことができますか?

多くの依存関係を持つ大きなプロジェクトがあると、小さなプロジェクトにはないコストが発生するという事実を避けられません。あなたは代償を払うどちらか開くのが遅く、ビルドが遅い大規模なプロジェクトでは、 or(nugetまたはその他の手段を介して)ビルドを分割し、すべてのソースコードへの即時の単純なアクセスを失います。

シンボル付きのNuGetフィードは、これを解決するための最も主流で最も単純な試みを提供します。

1
Chris F Carroll

ビルド済みのバイナリに切り替えることを検討していましたが、ソースコードに戻る可能性を残したいと思います

まず最初に、ビルドシステムが必要になります。ビルドシステムは cmake を使用してsourceコードとそのdependenciesを処理することをお勧めします。ここでテスト設定を取得し、作業ディレクトリが次のようになっていると仮定します。

project_folder
|-- lib
|   |-- LibA.cpp
|   |-- LibA.hpp
|-- tools
|   |-- conanfile.py
|   |-- conanfile.txt
|-- CMakeLists.txt
|-- main.cpp  

彼らが何を想定しているのか:CMakeLists.txtcmake構成ファイルであり、処理する

API/Abiブレークを特定することは可能ですか?

そしてconanfile.pyはあなたのレシピであり、packageおよびcreateビルド済みライブラリとconanfile.txtは、ビルド済みライブラリを消費するために必要なファイルです

どうやら、私は conan を使用してビルド済みのライブラリを処理するか、またはpackagesとも呼ぶことをお勧めします。

次に、私の例とその使用方法について説明します。CMakeLists.txt

cmake_minimum_required(VERSION 3.15)

project(my_project LANGUAGES CXX)

add_library(LibA lib/LibA.cpp)

add_executable(ExecutableA main.cpp)
target_link_libraries(ExecutableA LibA)

target_include_directories(LibA PUBLIC ${CMAKE_CURRENT_LIST_DIR}/lib)

私の例ではcppを使用しますが、.netフレームワークの場合は this または this を確認できます

したがって、そのファイルでtargetsを定義し、次の内容で相互の依存関係を宣言します。main.cpp

#include <iostream>
#include "LibA.hpp"


int main()
{
  printTesting();
  std::cout << "Hello World! again" << std::endl;
  return 0;
}

LibA.cpp

#include <iostream>
#include "LibA.hpp"

void printTesting(void)
{
  std::cout << "Testing Something" << std::endl;
}

LibA.hpp

#include <iostream>

void printTesting(void);

cmake に慣れていないと思いますが、cmakeがMakefileを生成するか、evtlが生成します。 .vcxproj.netジェネレーターを使用する場合、ここでは単純にしたいのでconfigureプロジェクトとbuildバイナリーにします。

mkdir ../build && cd ../build
cmake ../project_folder && make

LibAExecutableAを取得するため、ここでは特に何もしません。cmakeが依存関係とevtlを処理するようになります。何かが変更された場合は、それらを再構築します(例:プロジェクトでnew commits)。 conanfile.pyは次のようになります:

from conans import ConanFile, tools


    class LibAConan(ConanFile):
        name = "libA"
        version = "0.1"
        settings = "os", "compiler", "build_type", "Arch"
        description = "<Description of LibA here>"
        url = "None"
        license = "None"
        author = "None"
        topics = None

        def package(self):
            self.copy("*.a")

        def package_info(self):
            self.cpp_info.libs = tools.collect_libs(self)

あなたはしたい:

cp ../project_folder/tools/conanfile.py && conan export-pkg . libA/0.1@myuser/testing

私たちのパッケージ名は:0.1バージョンのlibAです。 myuser/testingはチャネルです。これは、いくつかのターゲットプラットフォームでクロスコンパイルした場合に興味深いものです。

conan export-pkgを呼び出して再利用可能なパッケージを作成しました。これは$HOME_DIR/.conan/data/libA/0.1/myuser/testingにキャッシュされます(または環境で確認してください:conan config home

Evtl。最初にコナンをインストールしたいので、これをチェックしてください インストールガイドライン またはこれ ダウンロード と特別な設定: conan with Azure devops

したがって、これらの作成されたパッケージはploaded to any remote_server$ conan upload libA/0.1@myuser/testing --all -r=my_remote_server(アナロジーとして:gitでコミットした後のgit Pushのようになります)。

したがって、configuredbuiltcmakeを付けたcreatedおよびuploadedパッケージをconanを使用して、同僚は、pythonfile.txtで要件を定義することにより、事前にビルドされたパッケージ/バイナリを再利用できます。

[requires]
libA/0.1@myuser/testing

[generators]
cmake

そして彼らはできる:

mkdir ../build_using_prebuild && cd ../build_using_prebuild && cp ../project_folder/tools/conanfile.txt . && conan install -g deploy . -r my_remote_server

conanは、必要なパッケージとevltを検索します。 my_remote_serverからダウンロードします

現在cmake ../project_folder && makeを実行している場合、最初からsrcをコンパイルする代わりに、事前に作成されたパッケージが使用されます。

もちろん、Azureでこれらの手順を自動化することをお勧めしますが、ビルドシステムおよびパッケージマネージャーを使用してビルドをオーケストレーションする方法を理解できたと思います。

0
dboy

ビルド済みのバイナリに切り替えることを検討していましたが、ソースコードに戻る可能性を残したいと思います

C++の場合は Conan を使用できます(他にも同様のツールがあるはずですが、使用していません)。ビルド済みのパッケージをサーバーにアップロードし、必要に応じて開発者にパッケージをインストールさせることができます。プロジェクトの一部として保持するconanfile.pyの要件リストに依存関係を追加するのと同じくらい簡単です。また、ソースからビルドする場合(たとえば、サーバーにバイナリがない場合)、--buildコマンドにconan installオプションを追加できます(これにより、プロジェクトの依存関係がインストールされます)。

ソースコードとビルド済みのバイナリを簡単に切り替える

バイナリとリンクするのではなく、プロジェクトのソースツリーで依存関係を維持することを切り替えようとしていますか?パッケージマネージャーを使用している場合、ソースツリーにそれを含めることによる長期的なメリットはありません。確かに、それがソースツリーの一部である場合(たとえば、ディレクトリを切り替える必要がないため)、依存関係のソースコードを変更する方が少し便利かもしれませんが、おそらく、より体系的で効率的です。独自のプロジェクトで依存関係を個別に変更するために実行します。 (そして、Conanでは、「ユーザー」と「チャネル」を使用して、サードパーティライブラリのこれらのカスタムバージョンを管理できます)

API/Abiブレークを特定することは可能ですか

私の意見では、これを管理する最良の方法は、依存バージョンを追跡することです。ここでも、要件に依存関係のバージョンを指定するため、Conanのようなパッケージマネージャーがこれを支援します。

Conanを使用することのボーナスは、環境にもたらすビルドの依存関係を追加できることです。たとえば、CMakeはビルドの依存関係になる可能性があります。したがって、パッケージは最初に指定されたCMakeバージョンをインストールし、次にCMakeでビルドされた残りの依存関係をインストールします。これにより、DevOpsの管理がはるかに簡単になります。

0
pooya13

C++プロジェクトの場合は、 CMake あなたの目的のために。 1)ソースコード全体をビルドする2)サブモジュールを一度ライブラリにビルドし、メインプロジェクトで再利用するなど、さまざまなビルドオプションを維持できます。最新のCMakeは、プリコンパイル済みヘッダーもサポートしています。これをチェックして、コンパイル時間を短縮することもできます。

コナン そして vcpkg C++モジュールで使用可能な2つのパッケージマネージャー

0
sanoj subran