C ++の反射のドロップ。 パート2:GitHubでの公開



重要な更新。 記事を読む前に読む
私のせいで、これらの出版物に関して混乱が生じました。 そこで、この警告を追加することにしました。

この一連の記事では、特定のcpprtに関係なく、特定のオープンソースライブラリの開発の歴史をより強調したかったのです。 ストーリーは、ソースコードの作成(ライブラリ自体に関係なく、人々が読むことに興味を持ついくつかの興味深いものに重点を置いて)から、リポジトリの作成(CMakeレッスンで)およびライブラリのプロモーション(プロモーションの一部にこのシリーズの記事の発行が含まれる)にあります。 オープンソースを投稿することを考えていたが、恐れているか、方法を知らなかった人々のためのこのようなトレーニングデモプロジェクト。

もちろん、図書館がどういうわけか活気づいたかどうかは気にしませんし、記事の中には最小限の図書館広告しかありません(ネタバレの下に隠そうとしました)。 しかし、それでも、このサイクルの目的はかなり教育的であり、私が望んでいるように、一般的には図書館とのコミュニケーションなしに適用できると考えました。

一連の記事を読むときにこれを考慮してください。


この記事は、C ++クラスに関する最小限のメタ情報を追加して使用するように設計されたcpprtライブラリに関するシリーズの第2回です。

最初の記事とは異なり、cpprtライブラリ自体についてはほとんど何もありません。 GitHubで文明化された出版物のライブラリの設計の歴史を説明するために、ライブラリから可能な限り詳細に抽象化することを試みました。

この記事では、ライセンスの問題、プロジェクト構造、およびCMakeに多くの注意が払われています。

サイクル内のすべての記事へのリンク




0.はじめに



導入的な言葉を言う必要性を遅らせるために、この出版物の構造を紹介します。

セクション番号0 。 このセクション。 出版物の構造と導入語の説明。
セクション1 。 ライセンスについて少し。
セクション2 。 メインプロジェクトのgitリポジトリとは別のサブプロジェクトのgitリポジトリを作成する方法について少し説明します。
セクション3 。 一般的なプロジェクトの構造に関する考えと、いくつかの既存のリポジトリの構造を分析しようとしています。
セクション4 。 cpprtプロジェクトのcmake構成開発記録に基づいたCMakeレッスン。
セクション5 。 ドキュメントに関するいくつかの言葉と多くのリンク。
セクション6 。 図書館の促進に関する考えを記した短いセクション。
セクション7 。 結論とクレジット。

だから 構造があり、まだどこかで開始する必要があります...さて、それをやってみましょう。

記事の目的: GitHubで公開するためにライブラリを準備した方法について説明します。

私は記事に取り組みながら、同時にオープンソフトウェアの世界のいくつかの側面を調査しました。 私の意見では、このため、この記事は旅行の最初の段階にいる人にとって貴重なものになります。素材を探してネットワーク全体を登る必要はありません。リポジトリを収集するために行かなければならなかったサイトへのリンクを最大限に維持しようとしました。

この記事のように、リポジトリが理想とはほど遠いことをよく知っています。 個人で書いて、コメントを書いて、図書館を見て、図書館にコミットしてください-私は記事のクレジットでなされた提案の著者に言及することを忘れないでしょう。 あなたの編集のそれぞれは、あなたの足跡でオープンソースソフトウェアの世界に入る人々を助けます!

たくさんの哀れみを覚えました...さて、今少し歴​​史。 シリーズの最初の記事で、cpprtライブラリクラスとマクロが私の大規模プロジェクトの一部として使用されたことに言及しました。 それらは個別に割り当てられず、単にソースコードの一部として存在していました。 しかし、ある時点で、これらのクラスはメインプロジェクトにほとんど依存せず、その機能は自給自足であり、いくつかの典型的なタスクに適用できることに気付きました。

そして、プロジェクトの一部を別のサブプロジェクトに分け、長年の夢であるオープンソースライブラリを公開することを実現することにしました。

さらに読む前に、おそらく次の考えを読むことに興味があるでしょう(最初の記事を読んでいない場合):これらの出版物の本当の陰湿な動機の認識( リンク )。

そして、読者へのさらに2つの警告:

怠に関する免責事項
この記事には実質的に私の考えが含まれていません。 これは、さまざまなソースのコンパイルです。 問題は、サイクルの最初の記事が開発(創造プロセス)に直接関係する場合、明確に規制されるべきであり、できればできるだけイニシアチブを持たない、受け入れられる標準と方法について述べていることです。 したがって、少数の自分の考えと豊富なリンク。

用語のカオスに関するメモ
また、この記事で支配的な用語の混をすぐに認識したいと思います。 「解決済み」、「ヘッダーの検索方法」、「アセンブリの目標」など...これらのすべての概念をロシア語で命名するのが慣例であるかを理解しようとしましたが、受け入れられる命名システムが見つかりませんでした。 一般的な用語を教えてくれれば、用語が明確でない場合や名前を変更する場合は、個人的に、またはコメントに書いて説明します。


それでもこの作品を読むことを思いとどまらせることができなかったら、行きましょう!

1.ライセンスの選択





ありがとう
-このセクションはユーザーCheaterの コメントに関連して多少修正され、補足されています。 いくつかの不正確さとニュアンスを指摘してくれた彼に感謝します。
-Gorthauer87に感謝します。Gorthauer87は 、このライセンスに関するコメントで不正確な点をいくつか指摘しました。


コードの品質に関係なく、私の目にはソースコードがより重くなります。 一部の人にとってはばかげているように思えるかもしれませんが、私にとってはライセンスのある帽子です。 ここに私は見ます:帽子があります-それはプロジェクトが本当に進んでいることを意味します。 帽子はありません-それほどクールではありません。 それは何らかの形で潜在意識に自動的に作用します。

したがって、ライブラリを公開することを決めたとき、最初に触れたのは、ソースにライセンス情報を含めることでした。 そして、このために、ライセンスを選択する必要がありました。

私はライセンスの問題を慎重に研究し始めました。 私はいつもこのトピックを恐れていました。 私は考えました:間違ったライセンスを選択します-そして今、私は投票権を含むいかなる権利も持たずに、私の終わりまで無料でコードをサポートする義務があります。

実際には、すべてがそれほど怖くないことが判明しました-いずれにせよ、オープンソースソフトウェアのライセンスについて話す場合(私はまだ独自のライセンスを見つけていません)。 選択する際に覚えておかなければならない唯一のことは、そのようなライセンスを2つのグループに分けることができるということです: オープンソースフリーソフトウェア 。 似ているように聞こえますが、オデッサで言うように、2つの大きな違いがあります。 よく見てみましょう:

オープンソース 注意、オープンソースの「オープン」は偶然ではありません! オープンソースは、それを使用するすべてのコードをオープンソースにします。同時に、オープンソースコードのソースは要求に応じてオープンする必要があります。
たとえば、オープンソースライセンスの下でプロジェクトでライブラリを使用します。 1年を使い、2年を使います...そして突然、 すべてのコード表示するように求められます。 そして、あなたには拒否する権利はありません! 強制IT共産主義。 「ソースごとのそれぞれから、ソースごとのそれぞれへ。」 この見込み客があなたを怖がらせている場合-接続しているプロジェクトのライセンスに注意してください。
オープンソースライセンスファミリ内のコードのオープン性を保証する一連のメソッドには、 独自の名前copyleftがあります。 コピーレフトを含むメインライセンスは、GPL (General Public License)とその関連ライセンスです(コピーレフトのGPL 3ライセンスから引用: 「GNU General Public Licenseは、ソフトウェアおよびその他の種類の作品の無料のコピーレフトライセンスです )) 。
ライセンス自体からの引用とともに、GPLの詳細をご覧ください
GPL 3.0のライセンスを理解し、 この翻訳を読んで、あいまいな瞬間にオリジナルを参照しました。

ライセンスのウイルス性の疑いは、条項5を使用して実装されます。この条項では、GPLライセンスに基づいて配布される製品の修正バージョンもGPLライセンスに準拠する必要があります。これは、この製品が元の製品の「修正」および変更の正確な日付であることを示しています。

定義(ライセンスのポイント0)を読んだ場合、ソースコードの変更という概念では、元のコードの変更とコードでの使用の両方を意味します。 引用:

作品(ライセンス製品はライセンス製品)を「修正する」とは、正確なコピーを作成する以外に、著作権の許可を必要とする方法で作品の全部または一部をコピーまたは改変することを意味します。 結果の作品は、以前の作品の「修正版」 または「以前の作品に基づいた」作品」と呼ばれます。

したがって、GPLライセンスの下でライブラリ関数が呼び出されるファイルはライブラリの修正であり、GPLの下で配布されるようになります。 同じことが、それを使用するすべてのファイルで発生し、原則として、すべてのコードは関数呼び出しのツリーの意味で一貫しているため、すべてのコードはGPLになります。

GPLイデオロギー 、つまり「ニーズに合わせてプログラムを自由に修正する」という条項を考慮すると、GPLライセンスが「バイラル」である理由は明らかです。 ライセンスが、ライブラリAPIと直接対話するコードをオープンアクセスのみでレイアウトする要件を課す場合、ライブラリ関数をそれ自体から呼び出し、要求に応じて、たとえばコードのみを直接開くなど、関数のレイヤーを作成することで簡単にバイパスすることができますライブラリコードを使用すると、ユーザーは独立した値を持たない関数のこのレイヤーのみを開きます。

コンパイルされたプログラムの配信時にソースコードを開く要件は、ライセンスの条項6によって保証されています。さらに、この条項では、修正の作成者がソースコードのアセンブリをセットアップし、このためのビルドシステムのスクリプトまたはその他のファイルを提供するのを支援する必要があります。

検索中に見つかった興味深いもの:
1.「譲渡したコピーごとに価格を設定する場合としない場合があり、サポートを提供するか、料金を保証することができます。」 これについては、gnu.org FAQの一部としての回答があります 。 つまり、金銭のコードサポートを販売したり、金銭のコードを販売したりすることもできますが、同時にプログラムのコピーを受け取った人は、自分に適した方法でそれを配布することもできます。このテーマに関するgnu.org FAQリンク)。
2. GPLの下での「製品」の概念の一般化:
Times: 「プログラム」とは、このライセンスの下でライセンスされている著作権のある作品を指します ''
2: 作品の「ソースコード」とは、作品に修正を加えるための作品の好ましい形態を意味します。 「オブジェクトコード」とは、非ソース形式の作品を意味します」
この一般化により、ライセンスはソースコード以外の製品に適用できます。
3.「ライセンス作品を他の独立した作品とコンパイルします。これらは本質的にライセンス作品の延長ではなく、記憶媒体上で大きなプログラムを形成するためにライセンス作品と接続していません。コンパイルとその最終著作権が使用されない場合、オリジナルの作品に関する編集ユーザーのアクセスまたは法的権利を制限するため。 ライセンスされた作品を集約に含めることは、このライセンスの有効性を集約の他の部分に拡張するものではありません。 つまり、GPLライセンスの下でコード呼び出しとまったく接続されていないプログラム内のコードの孤立した部分がある場合、コードのこの部分のソースコードを開く必要はありません(そのような状況はほとんど想像できませんが、ポイントはです)。

利点:コードの完全なオープン性により、読者の範囲が広がるため品質が向上し、作家の範囲が広くなるため開発が加速されます。 そして、もちろん、もう一つの利点-あなたは世界に良いものをもたらすと感じています。 戦争ではなくオープンソースを作りましょう!
短所:独自のコードおよび/または商用秘密を含むコードでGPLライセンスの下で製品を使用する能力は制限されています。 オンデマンドでそれを伝える必要がある場合、それはどのような秘密ですか?

フリーソフトウェア 。 フリーソフトウェアライセンスにより、ユーザーは制限なしでコードを使用して何でもできます。場合によっては、純粋に条件付きの要件があります(たとえば、元のライブラリの作成者を示す義務があります)。 そのようなライセンスの1つは、たとえばMITライセンスです。 これには、 BSDライセンスファミリも含まれます。
利点:寛大な商業会社からの追加の品質コミット。
短所:貪欲な企業は、コミュニティと共有せずに、コードを自分で盗み、企業リポジトリに分岐し、自分だけのために静かに開発できます。

劣等公的ライセンス
オープンソースコードのライセンスには、LGPL (Lesser General Public License)および関連ライセンスが含まれます。 このタイプのライセンスには、オープンソースとフリーソフトウェアの両方の機能が含まれています。
LGPLは、制限なく、コードを開く必要なく、商用プロジェクトを含め、どこでもバイナリ表現(実行可能ファイルまたは動的ライブラリ)にコンパイルされたコードを自由に使用できます。
ただし、LGPLライセンスの下でプロジェクトソースをプロジェクトのコードに静的にリンクする場合は、オープンソースの世界で独自のソースが必要になります。 幸いなことに、ライセンスにはソースコードの公開は必要ありません。 悪い点は、これらのソースが収集されるオブジェクトファイルの公開が必要なため、他の人がそれらを再リンクして、オープンソースのイデオロギーによって指示されたソフトウェアを変更する権利を遵守できることです。
LGPLを使用したプロジェクトの例はQtです。 LGPLライセンスにより、そのダイナミックライブラリは、制限なしに独自のソフトウェアで使用できます(公式Qtフォーラムでのこれの議論とqtcentreウェブサイトでの同様の議論 )。
ライセンス自体からの引用とともに、LGPLの詳細をご覧ください
このライセンスのロシア語へのわかりやすい翻訳は見つかりませんでした(その条項が元の文言に対応していないGPL条項に直接関係する翻訳のみを見つけました)。 これは、gnu.orgの元のライセンスリンクです。

このライセンスはGPLに基づいていますが、多くの条項を明確にし、多くの新しい用語を導入します。主な用語は「ライブラリ」(ライブラリ-これはライセンスの下にある製品の名前、GPLがWorkと呼ぶもの)および「結合」です作業」(新しいコードとライブラリを使用またはリンクすると、結合作業が得られます):

「ライブラリ」とは、以下で定義されるアプリケーションまたは結合著作物以外の、本ライセンスが適用される対象著作物を指します
「A「結合された作品」は、アプリケーションをライブラリと結合またはリンクすることによって作成された作品です。 結合作業が行われたライブラリの特定のバージョンは、「リンクバージョン」とも呼ばれます»

ライセンスの本質の大部分は4番目の段落に記載されており、ライブラリのライセンスを付録とともに配布するための標準要件に加えて、アプリケーションの作成者はライブラリに動的にリンクするか、誰でもコードを収集できるオブジェクトファイルを提供する必要があると述べていますアプリケーションファイルを変更して、オブジェクトファイルを作成します。

より興味深いこと:
1.このライセンスは、GPLに対する追加の譲歩のセットとしてGPLとともに言及されるべきであり、GPLが別個のファイルとして使用された場合、LGPLは明確化された追加ファイルとして記述されるべきです。
2.ライセンスの2番目の段落( Conveying Modified Versions )は、LGPLライセンスの下でライブラリ自体のソースコードに変更が加えられた場合(この場合、ライブラリ関数への引数の受け渡しに加えて、これらが変更であることを明確にします)、公開された変更は、変更されたライブラリの機能を保証するか、LGPLが免除することなくGPLのライセンスを変更する必要があります。
3.ライセンスの3番目のポイントは、ライブラリヘッダーファイルを、ライブラリを使用するアプリケーションのバイナリコードにコンパイルする機能を示します(アプリケーションのソースコードを公開する要件はありませんが、LGPLライセンスでアプリケーションを配布する要件があります)。

利点:商業組織のコードの品質に対する間接的な関心(収集されたライブラリのコードがうまく機能することを望んでいます)と同時に、LGPLプロジェクトの開発の禁止は、無料のソフトウェアライセンスで可能な「サイレント」です。
短所:独自のソフトウェアでLGPLライセンスの下でライブラリを使用するには、dll(または.so)でアセンブルされたライブラリと製品のリンクを整理する必要があります。 LGPLを使用するコードが収集されています。

他の興味深いライセンスについて知っている場合は、コメントでそれらについて書くことができます。 誰にとっても面白いと思います。

既存のライセンスを検討した後、私はMITライセンスを最も自由なライセンスの1つとして選択しました 。 他の利点の中でも、MITライセンスは非常に簡潔です-理解可能であり、派生製品のオープン性に対する権利を保護するための複雑なルールを含める必要はありません。
このセクションの最後にあるこれらのリンクの中には、MITライセンスに関するものがいくつかあります。 そこで彼女は十分によく言われた、私は本質を歪めないために、私は言い直したくない。

セクションの最後で、ライセンス情報をプロジェクトに追加した方法(設計オプションの1つ)について簡単に説明します。

1.リポジトリのルートに、 このサイトからコピーしたライセンステキストを含むlicense.txtファイル(またはLICENCE.txt)を配置します。
2.すべてのソースコードファイルに次のヘッダーを追加しました。

サンプルライセンスヘッダー
//////////////////////////////////////////////////// ///////////////////////////////
//
// <ファイル名>
//
// Copyright©<ライセンス有効期間> <著者名>(<オプション、著者メール>)
//
// <ライセンス名>で配布(添付ファイルLICENSE.txtを参照するか、
// <ライセンスサイトへのパス>)
//

注:ソースコードのヘッダーにライセンスの全文が追加されたいくつかのリポジトリに出会いました。 おそらくこれがコードをより確実に保護する方法ですが、扱うファイルごとにこの長いライセンスエントリをめくるユーザーを悩ますでしょう。


ライセンスについては、gnu.orgを読むこともできます。 彼らはGPLおよび関連するものを使用してソースコードのライセンスを取得する原則について徹底的に話します。 彼らが提供する方法はどのライセンスにも適用できると思います。

約束どおり、興味深い資料への追加リンクのリストでセクションを終了します。
便利なリンク
1.これが私が最初に読んだ記事です。 2002、ええ、この記事は信じられないほど古いですが、多かれ少なかれ関連性があり、記事自体には、6つの異なるオープンソースとフリーソフトウェアライセンスの便利な比較版があります。 そのようなタブレットでは不十分な場合は、ウィキペディアでより強力なタブレットを見ることができます。
2. 1つの図のメインのオープンソースライセンスについて。
3.オープンソースライセンスについてもう少し
4.オープンソースライセンスの詳細 。 同じ記事にあるMITライセンスに関する情報
5. MITのライセンスについての詳細 、歴史的な遠足。
6. MITライセンスに関する詳細な記事 。 さらに、一般的なオープンソースソフトウェアに関するいくつかの考えも興味深いものです。
7.フリーソフトウェアとオープンソースの違いに関するGNUコミュニティの哲学を含む非常に詳細な記事
8.オープンソースソフトウェアの世界ではそれほど単純ではない興味深い記事
9.大胆で興味深いアイデアを持つ記事 :ソースコードを開かずに、テストとテスト結果を必要とするライセンスを作成します。
10.トースターで私がかつて尋ねた質問 (2016年3月に今それを読み直すのは面白かったです)。 この件で、 @ littlegugaというニックネームを持つユーザーが、最終的に使用したMITライセンスについてアドバイスしてくれました。


2.メインプロジェクトからコードを切断する





そのため、ライブラリにしたいコードが別のリポジトリに分離されないことがあります。 彼は、メインリポジトリのあるフォルダー内のプロジェクトの作業の最初から生きることができます。これらのソースの編集の履歴は、メインプロジェクトの履歴と密接に関連しており、それを解除する機会はありません。

幸いなことに、すべてはそれほど悲しいことではありません。 このような場合、gitサブツリー分割メカニズムを使用できます。 ここでこのトリックを学びました (まだここで言及されていますが、別の方法であるフィルター分岐についてのです)。 おもしろければ、この石ハンマーを使って私が経験した冒険について、モノリシックリポジトリをサブモジュールに分割し、サブモジュールを使用してそれらからさまざまなものを接着することについて、さらに詳しく説明できます。 ここでは、メインリポジトリの特定のフォルダの編集履歴を別のリポジトリに転送する方法を簡単に説明します。

1. cd {main-repo-path}
最初に、メインリポジトリ(フォルダーをアンフックするリポジトリ)のルートに移動する必要があります。

2. git subtree split -P {サブモジュール相対パス} -b {サブモジュール分岐}
{submodule-relative-path} -ブランチで分離するフォルダーへのリポジトリのルートからの相対パス。
{submodule-branch} -パス{submodule-relative-path}にあるフォルダーのソースの操作履歴全体がコピーされるブランチ。

このコマンドを呼び出した後、{submodule-branch}ブランチがローカルリポジトリに追加され、{submodule-relative-path}フォルダーの変更に関連付けられたすべてのコミットが含まれます。 このコマンドを呼び出すと、新しいブランチが作成されてコミットがコピーされるだけで、それ以外は変更されません。

注:コピーされたコミットに関連付けられたコミットメッセージは変更されないままであることに注意してください。 フォルダーの編集の履歴に不必要な情報を保存できます(フォルダー内とフォルダー外の両方のコミットに変更があった場合)。 私はそれを回避する方法を知りませんし、どうにかしてそれを回避することは全く可能だとは思いません。

3. git push {submodule-repo-URL} {submodule-branch}:{master}
新しいブランチを別のリポジトリにプッシュします。

{submodule-repo-URL} -フォルダーの変更履歴を保存するリモートリポジトリのURL。
{master} -remootリポジトリ{submodule-repo-URL}の{submodule-branch}ブランチが受け取る名前。 これがリポジトリに追加される最初のブランチである場合、gitのメインブランチに名前を付けるという古代の伝統に従って、「マスター」と呼ぶのが最善です。

このコマンドを呼び出した後、{master}という名前の新しいブランチが、{submodule-relative-path}フォルダーへの変更の履歴を含むURL {submodule-repo-URL}にあるリポジトリに追加されます。

4. git branch -D {submodule-branch}
{submodule-relative-path}フォルダーの編集履歴を持つブランチが不要になった場合、このブランチを削除する必要があります。 -D-bigは、ブランチの削除を強制することを意味します。 -dでブランチを削除すると、gitは誓います:削除する前にこのブランチをプッシュしなかったと言っています(gitは実際に別のリポジトリにプッシュしたものを撃ちません)。


一般に、それですべてです。 私のメインプロジェクトで説明した手順に従って、将来のcpprtライブラリのソースコードを編集する履歴を分離し、非常に大まかなリポジトリを取得して、ファイルの変更履歴全体を保存します(コミットメッセージにゴミが含まれている場合もあります)。

リポジトリは準備ができていました...しかし、それはまだ公開にはほど遠いものでした。 リポジトリを適切な形式にすることも想定されていました。 このため、ソースコードとライセンスでは不十分でした。テスト、例、組み立て可能なすべてのアセンブリメカニズムの検討、あらゆる種類のread meファイル、ドキュメントなどの作成を支援する材料の束を作成する必要がありました。これらすべてのために、リポジトリの構造を検討する必要があります。この記事の次のセクションでは、プロジェクトの構造について説明します。

便利なリンク:
1. サブモジュールとサブツリーのどちらかを選択して、私が一度尋ねた質問かなり長い議論と多くのリンクがあります(そのうちのいくつかは既に上で使用しました)。おそらく、プロジェクトのモジュール構成のトピックに興味がある人は、ディスカッションを読んでリンクをたどることが面白いと思うかもしれません。ところで、私はこの機会に、Andy_Uにこの問題について活発に議論してくれたことに感謝したいと思います-最終的にサブモジュールを選択したという事実にもかかわらず。
2. サブツリーを操作しようとしたときに遭遇した困難について説明した別の質問 ...ところで、誰かが私が間違ったことを説明できるかもしれません。

3.リポジトリの構造に関する考察





だから、リポジトリの構造...私の意見では、これはアーキテクチャのカテゴリからのものです。コードのアーキテクチャは、その要素の相互作用の原則を設定します。アーキテクチャ-それは構造でもあります-プロジェクトのリポジトリは、他のプロジェクトとの相互作用の原則を設定します。ここで言う「他のプロジェクト」とは、コードベース、アセンブリシステム、またはビジネスプロセスだけではありません。私はまた、あなたのコードを使用し、それを変更する人々を意味します。

私の理解のために、私はユーザーの観点と貢献者の観点からプロジェクトの要件を策定しようとしました。

ライブラリユーザーの位置からの眺め



ライブラリに精通しているときに、発生順に要件をリストします
。1.自分が何を扱っているかを理解したい。これがプロジェクトのルートにあるものの簡単な説明と、GitHubのプロジェクトページに表示されるように、ある種のReadme。まあ、もちろん、ドキュメント。できれば写真付き。
2.コードの使用方法を確認したい。テスト、コードの使用例、そしてそれがどのように行われるかは明確でした。
3.プロジェクト自体について...アセンブリ、構成、統合に最小限の神経と時間を費やしたいと思います。ヘッダーと、コンパイラーとプラットフォーム用のコンパイル済みライブラリーがあるフォルダーがあれば、それは素晴らしいことです。接続し、本番にリンクします。このビルドシステムを理解したくありません。
注:ここで、さらにC ++に固有のことについて話します。他の言語では、すべてがややシンプルになります...
4.プラットフォームに依存しないプロジェクトがあります!自分でビルドシステムに適応する必要なく、自分でライブラリをビルドできるようにしたいと考えています。言い換えると、CMakeが必要です(CMakeが明確でない場合は、大丈夫です。後で説明します)。
追加要件:
5.したがって、ライブラリには可能性が多すぎます。配送中のツールはありますか?そして、すぐに収集することをお勧めします。
6.私はあなたのプロジェクトを長い間使用しています。彼が最近更新したと聞きましたか?何が変わったのか知りたい。

提示された要件を考慮して、以下の構造が得られます:

ファイルツリー表記法について
:

file_in_root
, . . file_in_root. /, , , .

/folder_in_root
, .

-file_in_folder
, . , , . . , - , , , .

-/folder_in_folder
, , .



1.どんな種類の図書館ですか?
README.txt-プロジェクトの簡単な説明。
/ doc-プロジェクトとそのAPIを詳細に説明するファイルです。

2.テストと例。
/ tests-できるだけ簡単に実行できるプロジェクトをテストします。
/ examples-できるだけシンプルに実行する必要があるサンプル。

3.すぐに接続します...
/ include-アセンブルされたライブラリのAPIにアクセスするためのインターフェイス。
/ lib-ソースの静的ライブラリへのアセンブリ。
/ bin-動的ライブラリへのソースのアセンブリ。
注: libおよびbinフォルダーには、できればメインのコンパイラーとプラットフォームのアセンブリーを含める必要があります。

4.自分で組み立てたい!
/ src-プロジェクトのソースコード。
cmake_readme.txt -cmakeファイルを使用してプロジェクト構成を生成する方法に関するオプション情報。
CMakeLists.txt-アセンブリ構成のファイル。

5.ツール?ここに行きましょう:
/ tools-ライブラリでの作業を簡単にするツール。収集されるか、ソースコードの形式で。

6.
change_list.txt-プロジェクトの最新の変更に関する情報を更新します

図書館寄稿者の視点からの外観



ライブラリを知るときの要件は、出現順にリストされています:
0。ライブラリを知る最初の段階では、私は寄稿者ではなく、ユーザーです。したがって、最低限、私の要件には上記のユーザー要件が含まれます。
1.私はあなたのプロジェクトが好きで、それを開発したいと思います。友好的な貢献者の家族に参加する方法について、何らかの種類のReadmeを読みたいと思います。
2.ライブラリが内部にどのように配置されているかを理解したい。開発者向けの詳細なドキュメントが必要です。理想的には、プロジェクトのビルドシステムにもドキュメントが必要です。
3.ビルドシステムで作業するとき、プロジェクト全体を登りたくありません。アセンブリに豊富な構成ファイルまたは追加プログラムが必要な場合は、別のフォルダーに入れてください...一般に、すべてが適切である必要があり、ファイルは目的別にグループ化する必要があります。
その他の要件:
4.カスタムツールはもちろん優れています...しかし、プロジェクトは本当に大きなものです。開発者向けのツールが必要です。

全体として、要件を考慮して、理想的なプロジェクトの構造について以下の明確化が得られます

。1.導入情報:
contributors_README.txt-開発に投資したい人のためのプロジェクトの簡単な説明。

2.ドキュメント:
/ doc-
/ developer_doc-プロジェクトの詳細を含むドキュメント。
注:この構造では、ユーザードキュメントもdocフォルダー内の別のフォルダー(一部のuser_doc)に保存する必要があります。私の意見では、このようなドキュメンテーションの構造は、構造的な順序に加えて、ドックを持っている好奇心の強い読者に興味をそそります。「入門者のためのドックの中には何がありますか?」-そして、読者をおそらく貢献者にします。

3.プロジェクト内の順序:
/ build
ビルドシステムのあるフォルダー。プロジェクトのこのフォルダの外に、最小限のビルドシステムファイルをハングアップすることをお勧めします。

4.開発
ツール / tools-
/ developer_tools
ドキュメントと同様に、目的に合わせてツールを収集します:ユーザー固有、開発者固有。

ここにリストされている要件は、私の知覚にとって主観的なものです。それについて何か考えがあれば、それを共有してください。

GitHubを使用してプロジェクトを分析しているときに、CMakeユーティリティを操作するためのファイルについて頻繁に言及していることに気付きました。さらに、いくつかの資料から判断すると、C ++でのオープンプラットフォームのクロスプラットフォームソフトウェアリポジトリの古典的な構造の形成に影響を与えたのはCMakeでした。彼は逃げられないという気持ちが醸成されていました。来る...

4. CMakeへの道





謝辞: CMakeを勉強するきっかけとなったスタニスラフ・マカロフ(Nipheris)に感謝します。

CMakeは、特定のメイクシステム(および/または一部のIDEのプロジェクト)の構成ファイルを生成して、ユニバーサルな抽象的な構成(サポートされているビルドシステム/ IDEのリスト)に基づいてC / C ++プロジェクトを構築できるユーティリティです。生成後、CMakeの終了時に取得された構成および/またはプロジェクトファイルは、特定のビルドメカニズムによって既に使用されています。彼らの仕事の結果としてのみ、組み立てられた製品が得られます。
CMakeはメタメイクツールであり、C / C ++プロジェクトのアセンブリシステムを抽象化したものであると言えます。

私はcpprtライブラリのリポジトリ構造を構築するとき、CMakeの使用をあらゆる方法で回避したことを認めます。典型的な先延ばし...さまざまな言い訳を思いつき、Python、ボディーシャツ、そして私が知っているイチジクでビルドシステムを構成し、サブモジュールにいくつかの壊れやすいデザインを付けました。このすべての狂気の神格化は、CMakeの私の拒絶を正当化する理論全体でした。同様に、cpprtライブラリは非常に小さいため(2つのファイルのみ)、その統合のために、「ライブラリ」のソースコードをサブモジュールとしてユーザープロジェクトに直接挿入するだけで十分です。また、サンプルとツールのソースコードもサブモジュールで配布する必要があります。これにより、ユーザーは必要に応じてライブラリのカブにそれらを取り込むことができます。
さらに、例とツールはcpprtライブラリに依存するため、ライブラリ自体も(注意!)これらのサブリポジトリにサブモジュールとしてビルドする必要があります。結局、例はライブラリをプロジェクトに埋め込む方法を示しているはずです。

したがって、この異端の理論に基づいて、Frankensteinのモンスターのようなリポジトリを、gitメカニズムで接続されたいくつかのミニリポジトリから縫い付けました。それは本当のゴミでした(ここで賞賛できます)。言い訳を拒否する場合は、CMakeを教えるだけではなく、これだけを行いました

しかし、良心はテレビではありません。彼女の音を消すことはできません。無料の検索の過程でランダムな資料に出くわし、次第に気づきました。CMakeは、C ++向けのオープンソースクロスプラットフォームソフトウェアの現代世界の柱の1つです。CMakeを使用せずにこのようなプロジェクトを行うことは、まったくナンセンスです。これは完全に間違っています。記事でそのような決定について人々に伝えることは、とりわけ、人々に悪いことを教えることを意味します。

したがって、4月12日火曜日、私は座ってCMakeを勉強しました。翌日の夕方までに、私はすでにプロジェクトのCMake構成が機能していて、自分の不安に笑いました。思ったより簡単で、とても便利でした。

以下は、CMakeに没頭したことの記録です。これが誰かを助けることを願っています。

CMakeが必要な理由の詳細をご覧ください。
, CMake. , , , , . – .

, ++ , (Java, C#, Python, ..)? , ++ ( = ). , , , , .

, , ( = + + + - ) . , C++ , IDE. , ? .

. , , , , .
, Visual Studio. , , , – , , -- .

– MinGW, Eclipse IDE . , — , . MinGW+Eclipse , , . , , Eclipse IDE, … NMake . … IDE. – .

, — , — IDE. , .

, , CMake! CMakeLists.txt, CMake – , CMake.exe, ( IDE), -/IDE . , !

CMake. .

PS: , CMake , CMakeLists.txt. . , : ( IDE). CMake .

— . .

CMakeを知った後、私自身と私の知り合いの一部と、C ++の5年の経験を持つ非常に経験豊富な人が、ほとんどすべてのオープンソースライブラリを誤って使用していることがわかりました。 ほぼすべてのクロスプラットフォームライブラリは、CMakeアセンブリのためのシンプルで便利な機会を提供し、すぐにアセンブルされたライブラリ、または最悪の場合はIDE用の既製のプロジェクトファイルを探しています-CMakeを使用して10秒でIDEのプロジェクトを生成する代わりに、さらに、収集したい内容(ライブラリ自体、テスト、例、ツール、その他のサポートプロジェクトなど)を微調整する機能を備えています。
顕微鏡を使った広範囲の釘付けのこの話は、カップにお茶を注ぐのを簡単にするために長い砂糖の袋を発明した人についての有名な悲しい話を思い出しましたが、誰もこれらの袋を正しく使用せず、男は自殺しました。

C ++のオープンソースソフトウェアでCMakeを使用する可能性を無視するたびに、ライブラリの作成者の1人が世界で叫ぶことを忘れないでください。 ツールを正しく使用してください。



14の標準と1つの新規がCMakeではない理由について
CMakeに関連して、読者はおそらく、14の標準とそれらを1つにまとめようとすると表示される15の標準に関する有名な写真を思い出すでしょう。 ただし、この場合、この写真は不適切です。 実際のところ、CMakeは、プロジェクトのアセンブリインフラストラクチャに異質のものとして埋め込む必要はありません。 メインプロジェクトのアセンブリインフラストラクチャに便利な構成ファイル(またはIDEのプロジェクト)を取得するには、CMakeを単独で実行するだけで十分です。その後、これらのファイル(またはプロジェクト)は、プロジェクトの既存の組織およびターゲットプラットフォームに対応するものとして簡単に埋め込むことができます。

CMakeはビルドシステムではありません。 CMake over buildシステム。 彼は彼らを支配します。




どれくらいの蜂蜜、蜂蜜、単一のタール分子なし...しかし、もちろん欠点もあり、実際にそれらについて話します。

CMakeが何であるか、CMakeがなぜであり、CMakeがどれほど優れているかを知ったので、それを知る時が来たと思います。 だからクロニクル...


以下に示すすべてのイベントは、実際には2016年4月12日火曜日に行われました。 ブラウザのページ要求履歴によって復元されました。

(0:35)材料の初期検索





CMake( ここから )をダウンロードしてインストールした後、レッスンを探し始めました。

" cmakeチュートリアル "の要求で、最初のリンクは公式のドックにつながりました。 基本的に、私はそれを理解しました。 cpprtはまだ非常に小さなプロジェクトであるため、ドックの最初の5つのステップを十分に理解して、ライブラリを構築するための考えられるすべての目標(構築ツールと例を含む)の構成を説明しました。

Googleの最初のページにある「 CMake habrahabr 」のリクエストに応じて、教育的なものとして考案された3つの記事がありました。 私はこの記事が一番好きでした(ちなみに、「cmake tutorial」のリクエストで2番目に脱落しています)。 いくつかの点でドックの翻訳に似ているいくつかの点での良いチュートリアル記事-しかし、より簡潔。 セクションに分かれており、各セクションでCMakeの機能について説明し、不要な殻を使わずに簡単な例を示します。 この記事を追加のトレーニング資料として使用しました。

他のリンクが見つかりました
1. 別の CMakeチュートリアル。 私は本当に始まりが本当に好きでした-プロジェクトの構造さえ非常にはっきりと美しく書かれていました。 しかし、最初の小さく理解しやすい例の後、著者は例を劇的に複雑にし始め、私は混乱し、上記の記事を使い続けることに決めました。
2. LZ4ライブラリのCMakeアセンブリの小さな分析 (GitHubを使用した比較的小さなプロジェクト)。 おそらく、CMakeの経験がある人にとっては、分析はかなり良いものですが、彼は、このビジネスにとって非常に新しいので、大量のコードとLZ4に固有のいくつかの変数を含む少量のコメントで私を怖がらせました。
3.よい入門レッスン

ハブでサーフィンをしているときにすでに見つけたリンクのうち、 CMake時計という短い記事に非常に驚かされます。 私はコードから何も理解していませんでしたが、それは同じくらいクールで、奇妙です。


(2:00)最初のCMake構成を構築します





CMakeで、午前2時に戻りました。 私は簡単にレッスンに精通し、可能な限り単純なプロジェクトで、いくつかのテストで練習することにしました。 次の内容のフォルダーを作成しました( {cmake_test}という名前にします )。

main.cpp
構成を生成するアセンブリのテストファイル。
ファイルの内容
#include <iostream> int main() { std::cout << "Hello from CMake!" << std::endl; return 0; } 



CMakeLists.txt
ソースアセンブリ構成main.cppの説明を含むファイル。 ここで、さらに新しい各CMakeチームに詳細なコメントをします。
ファイルの内容
#cmake_minimum_requiredコマンドにコメントし、CMakeのコマンド引数に関するいくつかの単語
公式cmake_minimum_requiredドキュメント

このコマンドは、この構成を構築できるCMakeの最小バージョンを設定します。 バージョンが古すぎる場合にCMakeを更新するようにユーザーにすぐに伝えるために使用されます。

これは最初のCMakeコマンドであるため、ここで引数を渡すのが慣例であることに注意してください。 引数間の区切り文字は空白(スペース、タブ、改行)です。 同時に、CMakeには名前付き引数があります。 したがって、たとえば、提示された呼び出しでは、「バージョン2.8.8」は、cmake_minimum_requiredコマンドの名前付き引数VERSIONの引数の値2.8.8の転送です。 次のコマンド(プロジェクト)の呼び出しでは、名前なしで引数が渡されます。
正直なところ、渡された値が引数であるか、 引数の値であるかをCMakeが認識する原理はよくわかりませんでした。 コマンドを呼び出す構文について公式のドックを読んだ後でも、私はこれを理解していませんでした...しかし、95%の場合、それなしで生きることができるように思えます。

cmake_minimum_required(バージョン2.8.8)

#プロジェクトチームへのコメント
プロジェクトチームの公式ドキュメント

このコマンドは、CMakeプロジェクトに関する情報を設定します。 これは、一般的にIDEのプロジェクトと呼ばれるものではありません。 これは、プロジェクト階層の1つ上のレベルを指します。 Visual Studioではこれはソリューションと呼ばれ、Eclipseではワークスペースと呼ばれます
CMakeプロジェクトのフレームワーク内で、いくつかのライブラリと実行可能ファイルをアセンブルするための構成、およびそれらを相互にリンクするためのルールを指定できます。

#この場合、プロジェクトにtest_projectという名前を付けます
プロジェクト(test_project)

#add_executableコマンドに関するコメント
add_executableコマンドの公式ドキュメント

プロジェクトにターゲットを追加して、実行可能ファイルをビルドします。 実行ファイルとライブラリは、CMakeのビルドターゲットの目標になる場合があります(アセンブリの目的は、CMakeビルドシステムに関するドックのセクションの冒頭にあります)。

最初の引数はビルドターゲットの名前です。その後、実行可能ファイルが収集されるソースコードファイルへのパスがリストされます。
さらに微調整するために、いくつかの追加の引数があります。これについては公式ドックで読むことができます。 単純なプロジェクトの場合、指定された構成で十分です。

#この場合、1つのソースをアセンブリに追加します-main.cpp
add_executable(test_executable main.cpp)


これらすべてのテストファイルを作成した後、コンソールを開いて次のことを行いました。

cd {cmake_test}
mkdirビルド
cdビルド
テストアセンブリのあるフォルダーに移動しました。
その中にフォルダーを作成し、そこにCMakeコマンドを使用して構成ファイルを生成します。
作成されたフォルダに移動しました。

cmake -G "MinGW Makefiles" ../
MinGWツールチェーンを介してアセンブリ構成ファイルを生成するための呼び出し。
-G "MinGW Makefiles" -構成ファイルを作成するためのジェネレーターの選択。 Generator-抽象CMake構成から特定のツールチェーン(またはIDE)の構成ファイルを生成するプログラム。
この場合、MinGWツールチェーンに付属しているMinGW32-makeツールのメイクファイルを取得したかったのです。
../-CMakeLists.txtが配置されているフォルダーへのパスと、構成の説明。
説明したコマンドを呼び出した後、プロジェクトをビルドするための構成ファイルが、呼び出し元のフォルダーに表示されます。 この場合、ソースmain.cppからの1つの実行可能ファイルのアセンブリ構成が予期されていました。

代替オプション
@SilentBob は、構成ファイルを生成するときに使用できる便利な属性を提案しました 。 そのため、アセンブリ構成を生成するフォルダーに対してmkdirを呼び出すことはできません。

属性-B {build-folder} 。 {build-folder}は、CMakeが構成を生成するフォルダーです。 作成する必要はありません。この呼び出しが行われるフォルダー内にCMake自体によって作成されます。 CMakeはmkdirと同様のアクションを実行します。

このコマンドを使用すると、構築時に身体の動きを減らすことができます。 たとえば、コンピューターの任意のフォルダーにあるこの例の構成を生成し、同時にこのフォルダーにあるビルドフォルダーに構成をきれいに配置するには、次のコマンドを呼び出します。

cmake {cmake_test} -Bbuild -G "MinGW Makefiles"

ビルドフォルダーが作成され、CMakeは作成されたビルド構成をその中に配置します。


この呼び出しは午前2時25分に行いました。 時間は、リクエストの履歴に基づいて、つまり、次の問題に対する最初のリクエストの時間に基づいて復元されます。

(2:25)問題



何も集まりませんでした。 CMakeは次のエラーを生成しました(エラーに関連するメッセージの部分のみを残し、パスを非表示にします)。

{my cmake_path} /share/cmake-2.8/Modules/CMakeMinGWFindMake.cmake:20(MESSAGE)でのCMakeエラー:sh.exeがPATHで見つかりました:ここで{some path}
PATHにsh.exeがないシェルからcmakeを実行します。


私はそれについてグーグルで調べて、 そのような情報を見つけました。 簡単に言うと、sh.exeがシステムパスで使用可能な場合、MinGWのジェネレーターは機能しません。 理由-まだ最後まで理解できず、夜の3時半には特に整理したくありませんでした。特に、私の場合、この問題は簡単に解決できることを考慮してください。

sh.exeが追加されたシステムパス(私の場合はgit)を一時的に削除し、CMakeを再度起動しましたが、...エラーが再度表示されましたが、別のエラーが発生しました。 新しいエラーはもっと気のめいるように見えました(エラーに関するメッセージの部分のみを残します)。

Cオブジェクトの作成CMakeFiles / cmTC_ebbab.dir / testCCompiler.c.obj
C:\ MinGW \ bin \ gcc.exe -o CMakeFiles \ cmTC_ebbab.dir \ testCCompiler.c.obj -c C:\ Users \ test \ Desktop \ ‚јї \ cpprt_FINAL \ current \ github \ build \ CMakeFiles \ CMakeTmp \ testCCompiler.c
gcc.exe:エラー:C:\ Users \ test \ Desktop \ ‚јї \ cpprt_FINAL \ current \ github \ build \ CMakeFiles \ CMakeTmp \ testCCompiler.c:そのようなファイルまたはディレクトリはありません

さまざまなソースを再度読んだ後、このエラー自体が次の理由で発生したことに気付きました。 特定のツールチェーンの構成ファイルを生成する前に、CMakeはこのツールチェーンのコンポーネント(コンパイラ、リンカなど)の存在をチェックし、これらのコンポーネントが正しく機能するかどうかもチェックします。 これを行うには、一時フォルダーにソースコードtestCCompiler.cを作成し、コンパイラーを使用してビルドしようとします。 私の場合、何らかの理由でCMakeはそのようなファイルを作成しませんでした。
残念ながら、これについて具体的なリンクを述べることはできません。このメカニズムのいくつかのエコーを以下に示します。

一般に、エラー自体はもちろん、上記の理由で発生しました。 しかし、これが原因ではなく結果であることは明らかでした。 理由を見つけるために、私は4泊目の始まりの前に、約40分間グーグルで検索しました。 それは「農民」の精神における典型的な二日酔いでした。 このクソコードを機能させ、最後に、そして眠りにつくことは...私を打ち負かしました。 最初にfirstめました。 これは私が夜に3時半まで掘り下げた最も賢明なリンクの1つです。

解決策 :問題は何でしたか。すでにこの記事を書いている最中でした。 実際には、アセンブリが実行されたフォルダへのパスにはロシア語の文字が含まれていました。 MinGWのmakefileのアセンブリが成功したため、同様の欠陥のないパスにフォルダーにアセンブルする価値がありました。
結論: Unicodeパスに注意してください! 何かが機能せず、理由がわからない場合は、パスでユニコードを探し、ユニコードなしでパスを作成してみてください!

(10:38)Visual Studio向けのビルド





私は、MinGWのアセンブリとはもうやりたくないという自信を持って目を覚ました。 Visual Studioをインストールしていたので、最初に構成を収集して(または、スタジオの場合はソリューションとプロジェクトを収集して)、他のツールチェーンの構成の生成をテストしてみてください。

コンソールを開き、{cmake_test} / buildフォルダーに移動してCMakeを呼び出し、別のジェネレーターを指定しました。

cmake -G "Visual Studio 14 2015" ../

奇跡! ビルドフォルダーでは、test_project.slnソリューション、いくつかのプロジェクト(ここで少し驚いた-なぜいくつか)、および構成変更の場合にCMakeがソリューションとプロジェクト設定を更新できることを理解するために必要な補助ファイルの束が形成されました。毎回設定を再生成する必要があります。

ソリューションを開きました。 はい、そうは思いませんでした。 main.cppを実行可能ファイルにアセンブルするための予想されるtest_executable.vcxprojプロジェクトに加えて、他の2つの左利きのプロジェクトALL_BUILD.vcxprojおよびZERO_CHECK.vcxprojがソリューションに含まれていました。 私はグーグルで調べました。 スタックオーバーフローに関するこの回答を見つけました。 それから、これらは、CMakeLists.txtファイルが変更された場合、CMakeが各ビルドの前にプロジェクトファイルを更新するまさにそのプロジェクトであり、これらのプロジェクトファイルの生成元であることに気付きました。 一般に、すべてが正しいので、作成されているはずです。

ZERO_CHECKを取り除く方法
cpprtリポジトリの最終的な形成中に、CMakeの依存関係なし(ZERO_CHECKおよびBUILD_ALLプロジェクトなし)でスタジオのCMake構成を生成する必要がありました-CMakeを持たないユーザーがこれらのプロジェクトを実行できるようにするためです。 ZERO_CHECKを取り除く方法は、 ここで見つかりまし 。 もちろん、これはCMakeのアイデアを大きく壊す(変更が行われると構成の更新を壊す)と言われましたが、ZERO_CHECKなしでスタジオのソリューションを生成するには、CMAKE_SUPPRESS_REGENERATIONオプションをTRUEに設定するだけです(次のように設定できます:-DCMAKE_SUPPRESS_REGENERATION = TRUE、-コマンドラインを使用してソリューション生成を構成する場合)。 このオプションが設定されている場合、BUILD_ALLおよびその他の付随するCMakeファイルおよびフォルダーは引き続き作成されますが、プロジェクトを損なわずに削除できます。

ZERO_CHECKを取り除くだけでは十分ではなかった理由
これはCMakeに対する最初の繊細な誤解です。事実、私が理解しているように、CMakeは相対パスで構成を生成できません。 どういう意味?

たとえば、プロジェクトにCMakeを含むパス含めると、CMake構成に関連するパスを指定した場合でも、転送されたフォルダーへの絶対パスが作成されます。 これは、アセンブリ結果が書き込まれるフォルダーへのパスを含む、すべてのビルド構成のすべてのパスに適用されます(ビルド出力directort)!

説明されているパス生成の機能により、絶対パスは単一ユーザーの特定のパスにバインドされるため、リポジトリにCMakeで生成された構成およびプロジェクトファイルを保存することができなくなります。

私はこの問題を解決する方法をまだ見つけていません。 私はオプションCMAKE_USE_RELATIVE_PATHSを見つけましたが、公式ドックには「機能しない可能性があります!」というメモがあります。そして、いつものように、公式ドックは嘘をつきません。 うまくいきません!

この古い議論では、相対パスを使用する機能はCMakeには一般的ではなく、したがって期待できないと述べていますが、ogre3dゲームエンジンのフォーラムに関する少し最近の議論では、 この答えは同じソリューションを提供します。私はそのフォーラムユーザーをogre3dで使用しようとしました。

この問題がインターネット上でどれほど不十分にカバーされているかに驚いていると言います。 私の意見では、これは非常にデリケートな問題です。 私の意見では、cmakeからcmakeまで独立した構成を生成するオプションは、バージョン管理システムのインポートリポジトリオプションに似ています。 彼女はそうでなければなりません。
たぶん私はひどく見ていましたか、どういうわけか間違っていましたか? どういうわけかこの問題を自分で解決した場合は、コメントであなたがどのようにそれを行ったかを教えてください。 この記事の別のセクションでこれらのネタバレを作り直し、このセクションの著者としてあなたを示します。



Visual Studioでは、test_executableプロジェクトをスタートアッププロジェクトとして選択し、ctrl + f5を押しました。 コンソールに「Hello from CMake!」と印刷されました。 うらしっきー乾杯!



ボーナス:CMakeによるユニバーサルアセンブリ
@SilentBobは、彼のおかげで、CMakeで作成された特定のビルド構成のアセンブリの開始を抽象化できる非常に便利なコマンドを提案しました

cmake --build {ビルドパス} --config {ビルドタイプ}
{build-path} -CMakeによって生成されたビルド構成があるフォルダーへのパス。
{build-type} -ビルドタイプ:DEBUGまたはRELEASE。

このコマンドにより、特定のツールチェーンまたはIDEの構成を構築できます。 私の意見では、いくつかのクロスプラットフォームビルドスクリプトを作成するときに、特に自動化に非常に役立つ機能です。


作業開始から約1時間が経過しました。

(11:24)CMakeを介したアセンブリのためのリポジトリの準備



これで、CMakeをメインプロジェクトに接続できます。 CMakeの前は、すでに述べたように、私のプロジェクトにはサブモジュールに関する内部組織がありました。 CMakeのおかげで開かれた見通しを考慮して、サブモジュールの使用は放棄される可能性があります。 リポジトリのクローンを別に作成し、すべてのサブモジュールのソースコードを取得し、CMakeを使用してアセンブリを構成する方法について考え始めました。

リポジトリをわずかに再構築したため、見た「アダルト」リポジトリのように人間に見えました。 以下は、CMakeの操作に直接関係するプロジェクト構造の一部です。

/ build-ソースコードを収集することになっている空のフォルダー。
/ include-ライブラリAPIにアクセスするためのヘッダーを含むフォルダー。
/ src-ライブラリのソースコードを含むフォルダー。
/ examples-さまざまなサンプルのソースコードを含むフォルダー。
-/ __ example_hierarchies__-テストクラス階層を含むフォルダー(以下を参照)。
-/ simple_examples-小さなテストケースのソースフォルダー。
/ tools-プロジェクトを操作するためのツールのあるフォルダー。
-/ console-現時点ではツールは1つだけで、その名前はconsoleです。
CMakeLists.txt-プロジェクトのさまざまな要素を収集できるCMakeファイル。

現在のライブラリリポジトリ
この記事に記載されていることは、 e9c34bbコミットにも当てはまります。

__example_hierarchies__の詳細
__example_hierarchies__フォルダーには、cpprtマクロで登録されたいくつかのクラス階層が含まれています。 これらのクラスにはフィールドがありません。相互に継承されるだけです。仮想クラスで 、空のメソッドはcpprtが抽象クラスでどのように機能するかを示すためにのみ必要です。 cpprtライブラリはクラス継承に関するメタデータに多くの注意を払い、さまざまなテストや例で__example_hierarchies__からの継承階層を使用できるため、これらの階層が必要でした。


ライブラリの配信の一環として、次のピースを組み立てることができると判断しました。



ライブラリの黒色
実行可能ファイルの青色
アセンブリターゲット間で共有されるソースコードを含むフォルダーの緑色

図書館
1. cpprt-実際には、ライブラリ自体。 / srcフォルダーにあるソースコードと/ includeフォルダーにあるインターフェイスから収集されます。
静的ライブラリにアセンブルされ、依存関係はありません。
一例
2. simple_examplesは、OOPに慣れるための動物クラスの古典的な階層を記述し、この階層に基づいてライブラリAPIを使用する単一のファイルで構成される小さな例です。
cpprtライブラリに応じて、実行可能ファイルにアセンブルされます。
計器
3. コンソール -現時点では、これは実際にはライブラリの機能を実証する例でもありますが、独立したツールに変える計画です。
コンソールから、登録済みクラスの継承ツリーに関する情報を表示したり、オブジェクトとクラスの両方の文字列名を使用してクラスオブジェクトを作成および削除したりできます。
実行可能ファイルにアセンブルされます。これは、cpprtライブラリとクラスのテスト階層に依存します。この例では、コンソールを見ることができます。

構造の準備ができました。 CMakeを使用してこれらのアーティファクトを組み立てるための構成を説明する「何もありません」がありました。

(11:30)cpprtライブラリの構築





cpprtライブラリには2つのファイルしか含まれていなかったという事実にもかかわらず、私は将来の作業に取り組み、フォルダーに含まれるすべてのファイルを再帰的に接続する方法をすぐに学ぶことにしました(さらに多くのソースパスはリストしません)。 私はそれをグーグルで検索し、GLOB_RECURSE引数を指定したfileコマンドの使用を説明するこのリンクを見つけました。

小さなProject-OSRMプロジェクトの CMake構成を 簡単に見て、見つかった情報を使用して次の構成コードを作成しました。


CMakeLists.txt
#setコマンドに関するコメント
セットに関する公式ドキュメント

このコマンドは、変数の値を設定または再インストールするためのものです。 最初の引数は変数の名前です。 次に、その値が設定されます。 この場合、パス「。」を渡します。これは、通常どおり、現在のフォルダー、つまりCMakeLists.txtが配置されているフォルダー(この場合、リポジトリのルート)を意味します。

注: CMake呼び出し中にコマンドラインから変数を渡すことは可能ですか? CACHEパスで変数を設定すると可能です(スタックオーバーフローについての答えは次のとおりです)。 面倒に見えます-したがって、私の意見では、コマンドラインからオプションコマンドを介してフラグを渡す方が良いです(詳細は後で説明します)。

設定(CPPRT_ROOT_PATH)

#ライブラリソースのルートフォルダー値を設定します。
#変数参照について
変数参照構文に関する公式ドキュメント

CMakeは、変数値にアクセスするために共通のメカニズムを使用します。 ドックで述べたように、CMakeは変数の参照が記述されている場所で変数の値を直接置き換えます(または同じ名前の変数が定義されていない場合は空の文字列を挿入します)。 このため、テキスト変数( Quoted Argument )および変数への他の参照でも同様の挿入を使用できます。 ドックからの例:

$ {outer _ $ {inner_variable} _variable}

私が理解しているように、ここで変数inner_variableの値は別の変数の名前の一部です。 前だけの奇跡。

設定(CPPRT_SOURCES_PATH $ {CPPRT_ROOT_PATH} / src)

#ライブラリインターフェイスのルートフォルダー値を設定します。
設定(CPPRT_INCLUDE_PATH $ {CPPRT_ROOT_PATH} / include)

#ファイルコマンドに関するコメント
fileコマンドの公式ドキュメント

GLOB_RECURSE引数を指定したfileコマンドの使用についてのみ説明します。 このようなコマンドは、コマンド呼び出しで指定された検索ルールに従うファイルおよびフォルダーパスの再帰検索を実行します。 ルールは、見つかったパスのリストが書き込まれる変数の名前に続く引数によって指定されます。
, – , . , , , , (, ).

file GLOB_RECURSE, GLOB. , .

№1: , CMake . file GLOB_RECURSE (, , ) . ( ).
№2: , CMake file GLOB, file GLOB_RECURSE. . ( IDE) CMake / .

file GLOB
, , , CMake ( IDE) () CMakeLists.txt, . — CMakeLists.txt.
, , CMake file GLOB GLOB_RECURSE. , CMakeLists.txt () . 不便。


, – .

#
# . CPPRT_SOURCES
# .
file(GLOB_RECURSE CPPRT_SOURCES
${CPPRT_SOURCES_PATH}/*.h
${CPPRT_SOURCES_PATH}/*.cpp


# , .
# CPPRT_HEADERS.
file(GLOB_RECURSE CPPRT_HEADERS
${CPPRT_INCLUDE_PATH}/*.h


# add_library
add_library

. . – , : STATIC ( ) DYNAMIC (, ).

# cpprt.
add_library(cpprt STATIC ${CPPRT_SOURCES} ${CPPRT_HEADERS})


ファイルの準備が整ったら、/ buildフォルダーに移動して構成ファイルを収集しました。cmake-G

“ Visual Studio 14 2015” ../

すべてがすぐに統合されました。cpprt.vcxprojプロジェクトで解決策がありました。ソリューションを開き、スタジオを介してアセンブリを開始しました...はい。ライブラリは問題なく組み立てられました。

これは12:41に発生したもので、Facebookリンクを開いた時間に基づいて説明できます。
Facebookの後、一時的に他のタスクに切り替えました。

(16:09)simple_examplesサンプルのアセンブル



2時間半後にcmakeの構成に戻りました。ここで、ライブラリのサンプルを作成するために、構成の生成を可能にする必要がありました。これを行うには、プロジェクト間の依存関係の整理に対処する必要がありました-結局、simple_examplesプロジェクトはcpprtライブラリに静的にリンクされました:



静的ライブラリをリンクするコマンドは、ハーバーのCMakeレッスンで言及されました(2番目の例)。これらのレッスンと他のいくつかのソースを読んだ後、次の構成コードを作成しました。

CMakeLists.txt
#===============================================================
# Head

cmake_minimum_required(VERSION 2.8.8)

# option
option

-.
– , .
— , . , - CMakeLists.txt , , CMake , .
– . .

, ( cmake -G .. ) ( ). :

-D< >=ON/OFF

: set , CACHE-. , , option .

# , ,
#
option(BUILD_EXAMPLES «Build cpprt examples» OFF)

#-----------------------------------------------------------------------------------------------
# cpprt. .

project(cpprt_projects)

set(CPPRT_ROOT_PATH .)
set(CPPRT_SOURCES_PATH ${CPPRT_ROOT_PATH}/src)
set(CPPRT_INCLUDE_PATH ${CPPRT_ROOT_PATH}/include)

file(GLOB_RECURSE CPPRT_SOURCES
${CPPRT_SOURCES_PATH}/*.h
${CPPRT_SOURCES_PATH}/*.cpp


file(GLOB_RECURSE CPPRT_HEADERS
${CPPRT_INCLUDE_PATH}/*.h


include_directories(${CPPRT_INCLUDE_PATH})
add_library(cpprt STATIC ${CPPRT_SOURCES} ${CPPRT_HEADERS})

#-----------------------------------------------------------------------------------------------
###- Examples


# include_directories
include_directories

( inlcude paths) CMakeLists.txt.
, – , . – , BEFORE AFTER .

: , . , , target_include_directories , . .

include_directories(${CPPRT_INCLUDE_PATH})

# if
if

– . , .

: else() endif(), , ( : «Note that the expression in the else and endif clause is optional» ), , , , . , #endif .

# BUILD_EXAMPLES
# ON – .
if(BUILD_EXAMPLES)

#- — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - -
### — Simple examples

# .
set(SIMPLE_EXAMPLE_ROOT ${CPPRT_ROOT_PATH}/examples/simple_examples)

# .
# .
add_executable(simple_examples
${SIMPLE_EXAMPLE_ROOT}/SimpleExamples.cpp
${CPPRT_SOURCES}


# target_link_libraries
target_link_libraries

. , , . . – target_link_libraries ( : «Repeated calls for the same {target} append items in the order called» ).

: , , CMake. . , .

target_link_libraries(simple_examples cpprt)
endif(BUILD_EXAMPLES)
#========================================================


CMakeの設定からスタジオソリューションを生成しようとしました。まず、サンプルをビルドするオプションを渡し、次にそれを使用しません。たとえば、スタジオ用のソリューションをサンプルプロジェクトとともに生成したコマンドは次の

とおり

です。プロジェクト用にコンパイルされた実行可能ファイルがないこと。間違いはありませんでした。

幸いなことに、すべてが非常に簡単でした-サンプルプロジェクトをスタートアッププロジェクトとして設定するのを忘れました(アセンブリ後、CMakeはデフォルトでBUILD_ALLを設定し、その中に実行可能ファイルは収集されません)。すべてを設定した後、テスト用であるはずのすべてが画面に印刷されました。

これは、17:14までに履歴から回復できたために発生しました-FastDelegateプロジェクトをどれだけ開いたかで判断します(これは、コールバックをプラスで処理するための優れたマイクロライブラリです)。私はそれを私のメインプロジェクトに使用し、そこでビルドシステムがどのように作られたかを見たいと思いました。それは何もないことが判明した...しかし、それは可能であり、正しい。

(17:14)コンソールサンプルツールのアセンブル



コンソールを組み立てるために残った。原則として、このアセンブリに必要なすべてのコマンドを既に知っていました。プロジェクト構造を思い出してください:



コンソールはテストクラス階層でアセンブルできます。ここで、「クラス階層を使用する」という概念は、コンソールの組み立て元のソースのリストにrepository / examples / __ example_hierarchies__のソースを含めることを意味します(ヘッダー検索パスとしてではなく、単に別のソースソースとして)。

コンソールアセンブリの説明を含む構成。コードを詰まらせないように例を構築するために、上記の構成なしで構成を使用します。

CMakeLists.txt
#==========================================================
# Head

cmake_minimum_required(VERSION 2.8.8)

# -
# console :

# .
option(BUILD_TOOLS «Build cpprt tools» OFF)

#
#
option(CONSOLE_WITH_EXAMPLE «Add examples to console» ON)

#-----------------------------------------------------------------------------------------------
### — cpprt code

project(cpprt_projects)

set(CPPRT_ROOT_PATH .)
set(CPPRT_SOURCES_PATH ${CPPRT_ROOT_PATH}/src)
set(CPPRT_INCLUDE_PATH ${CPPRT_ROOT_PATH}/include)

file(GLOB_RECURSE CPPRT_SOURCES
${CPPRT_SOURCES_PATH}/*.h
${CPPRT_SOURCES_PATH}/*.cpp


file(GLOB_RECURSE CPPRT_HEADERS
${CPPRT_INCLUDE_PATH}/*.h


include_directories(${CPPRT_INCLUDE_PATH})
add_library(cpprt STATIC ${CPPRT_SOURCES} ${CPPRT_HEADERS})

#- — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - -
# ,
# __example_hierarchies__. , , .

set(EXAMPLE_HIERARCHIES_ROOT
${CPPRT_ROOT_PATH}/examples/__example_hierarchies__


file(GLOB_RECURSE EXAMPLE_HIERARCHY_PATHES
${EXAMPLE_HIERARCHIES_ROOT}/*.h
${EXAMPLE_HIERARCHIES_ROOT}/*.cpp


#-----------------------------------------------------------------------------------------------
###

if(BUILD_TOOLS)

# – ,
# .
set(TOOLS_ROOT ${CPPRT_ROOT_PATH}/tools)

#- — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - -
#
set(CONSOLE_ROOT ${TOOLS_ROOT}/console)

# , :
if (CONSOLE_WITH_EXAMPLE)

#
add_executable(cpprt_console
${CONSOLE_ROOT}/CPPRTConsole.cpp
${EXAMPLE_HIERARCHY_PATHES}


# –
# (include path).
#
# ,
# , target_include_directories
# ( , )
target_include_directories(cpprt
PUBLIC
${EXAMPLE_HIERARCHIES_ROOT}


# cpprt
target_link_libraries(cpprt_console cpprt)

else(CONSOLE_WITH_EXAMPLE)

# -
# simple_example
add_executable(cpprt_console
${CONSOLE_ROOT}/CPPRTConsole.cpp

target_link_libraries(cpprt_console cpprt)

endif(CONSOLE_WITH_EXAMPLE)

endif(BUILD_TOOLS)


コンソールはすぐに集まって獲得しました。すべて準備が整いました。

その時までに(19:23)-私はグーグルで「ミントティーがなだめる」と判断した

すべての作業の結果:現在プロジェクトで使用されているような構成:

CMakeLists.txt
#============================================================
# Head

cmake_minimum_required(VERSION 2.8.8)

option(BUILD_ALL «Build cpprt tools» OFF)

# . .
#
# .
#
# ,
# .
option(BUILD_TOOLS «Build cpprt tools» ${BUILD_ALL})
option(CONSOLE_WITH_EXAMPLE «Add examples to console» ON)

option(BUILD_EXAMPLES «Build cpprt examples» ${BUILD_ALL})

#-----------------------------------------------------------------------------------------------
### — cpprt code

project(cpprt_projects)

set(CPPRT_ROOT_PATH .)
set(CPPRT_SOURCES_PATH ${CPPRT_ROOT_PATH}/src)
set(CPPRT_INCLUDE_PATH ${CPPRT_ROOT_PATH}/include)

file(GLOB_RECURSE CPPRT_SOURCES
${CPPRT_SOURCES_PATH}/*.h
${CPPRT_SOURCES_PATH}/*.cpp


file(GLOB_RECURSE CPPRT_HEADERS
${CPPRT_INCLUDE_PATH}/*.h


include_directories(${CPPRT_INCLUDE_PATH})
add_library(cpprt STATIC ${CPPRT_SOURCES} ${CPPRT_HEADERS})

#- — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — # Global examples setup

set(EXAMPLE_HIERARCHIES_ROOT ${CPPRT_ROOT_PATH}/examples/__example_hierarchies__)

file(GLOB_RECURSE EXAMPLE_HIERARCHY_PATHES
${EXAMPLE_HIERARCHIES_ROOT}/*.h
${EXAMPLE_HIERARCHIES_ROOT}/*.cpp


#-----------------------------------------------------------------------------------------------
### — Tools

if(BUILD_TOOLS)
set(TOOLS_ROOT ${CPPRT_ROOT_PATH}/tools)

#- — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — ### — Console project
set(CONSOLE_ROOT ${TOOLS_ROOT}/console)

if (CONSOLE_WITH_EXAMPLE)
add_executable(cpprt_console
${CONSOLE_ROOT}/CPPRTConsole.cpp
${EXAMPLE_HIERARCHY_PATHES}

target_include_directories(cpprt_console
PUBLIC
${EXAMPLE_HIERARCHIES_ROOT}

target_link_libraries(cpprt_console cpprt)

else(CONSOLE_WITH_EXAMPLE)
add_executable(cpprt_console
${CONSOLE_ROOT}/CPPRTConsole.cpp

target_link_libraries(cpprt_console cpprt)

endif(CONSOLE_WITH_EXAMPLE)

endif(BUILD_TOOLS)

#-----------------------------------------------------------------------------------------------
###- Examples

if(BUILD_EXAMPLES)

#- — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — ### — Simple examples
set(SIMPLE_EXAMPLE_ROOT examples/simple_examples)

include_directories(${CPPRT_INCLUDE_PATH})
add_executable(simple_examples
${SIMPLE_EXAMPLE_ROOT}/SimpleExamples.cpp
${CPPRT_SOURCES}

target_link_libraries(simple_examples cpprt)
endif(BUILD_EXAMPLES)
#============================================================


したがって、CMakeユーティリティを使用して、基本的なレベルの実用的なレベルの純粋な時間を4時間で簡単に、そして何もせずに見つけました。私の意見では、CMakeの強力な知識を身に付けることは4時間の価値があります。

結論として、CMake:

私が気に入ったもの:
強力なユーティリティについてお話します。それは、多くのプラットフォームとコンパイラーのための構成で蒸気を発する必要を本当に取り除きます。スタジオの後に、CMakeでmingw32-make + Eclipse IDEのメイクファイルを生成し、以前のVisual Studioで行ったのと同じくらい簡単にソースを組み立てたときに、これを感じました。
気に入らなかった点:
非常に奇妙な言語設計。区切り文字として空白を使用した引数、名前付き引数を使用する奇妙な原理、プロジェクトプロパティとアセンブリ目標を設定するための透過的なメカニズムではない(プロパティはすべてのアセンブリ目標に対してグローバルに設定される場合がありますが、特定の目標に対してローカルに設定されることもあります)実際、すべての操作をファイルシステムと組み合わせ、特定の操作はコマンド引数を使用して送信されます)。

ある瞬間、エイリアンはCMakeの言語を書いたように思えました。とても賢いですが、少し違った考え方をしています。

5.ドキュメントについて





すぐに言わなければならない-私はcpprtライブラリの英語のドキュメントを編集する勇気を持っていませんでした。現在、すべてのドキュメントは、この一連の記事を読むだけで送信されます。これは、おそらくドキュメントがないことを意味します。4週間のマラソンの後、一息ついたらすぐにこの欠陥を修正しようとします。その結果、このシリーズの記事が執筆されました。

実際にはドキュメントを作成しなかったという事実にもかかわらず、ドキュメントを作成するための最良の基礎となるものについて理論的な研究を行いました。ここで見つけた情報を提供します。情報は主にこの記事とそのコメントから取得されました。

Wiki
.

:
— , , , .
— . .
— .
— « » .
— .

短所:
— . , UML, . , . , .
— , . , - / ?


Googleドキュメント
.

:
— .
— , , .
— ( ).
— .
— ( ).
— doc, pdf html.

短所:
— goolge. sistemshik : « google».
— . , , . googledocs?


酸素
Doxygen

, Doxygen Norserium . : , . , .

, : « , Doxygen , . , — . »

:
— , , . , , , — - .
latex- .

短所:
.
— , .


平文
はい – , .

: « . <...> . , plaintext. ». , Plain text .

:
— , . — .
— .

短所:
— . Plain text , , .
— .


おそらくご存知のように、このようなオープンソースドキュメントのトピックへの最初の紹介の後、Doxygenはこれまでのところお気に入りであることが判明しました。これはおそらく、私がコードを書くのが好きで、あらゆる種類の退屈なドキュメントに目を通すことを好まないプログラマーであるという事実によるものです。

それにもかかわらず、私にとっては、良いドキュメントはDoxygenだけではできません。これは、APIに精通し、場合によってはいくつかの簡単な図を表示するための優れたソリューションです。しかし、多くの場合、UMLのほかに大きくて複雑な画像やイラストを使用して、コードの動作を詳しく説明するより詳細な記事が必要です。とにかく、あなたは自分でやらなければならないでしょう、ペン、ソースコードに関するコメントだけではうまくいきません。

ドキュメントについてはこれ以上言うことはありません。書き込み-補足。

6.図書館振興について





ここでは、この一連の記事を除いて、まだ経験がありません。これは、ライブラリを促進するための実験的な試みです。あなたの経験について人々に話してください。このアプローチがどれほど優れているか見てみましょう。

この出版物および図書館自体に対する読者の肯定的な反応がある場合、このシリーズの記事を英語を話す聴衆に合わせて、どこかに公開しようとします(redditがあることは知っています...誰かが良いリソースを知っているかもしれません)?そして、我々は表示されます...

プロモーションについては、今のところ、おそらく、私はそれ以上言うことはありません。

7.結論



私の研究、過ち、そして最も重要なこととして、他の人々の素晴らしいコメントと彼らのおかげでなされた変更が、読者の皆さん、私よりも早くこの道を進むことを願っています。

集合的な創造性のアイデア
, , - . , : . , ?

GitHub, GitHub — ( ). - , , — ( ?).

GitHub , — . — ?




, .

:

Speccyfan . bmp jpg.

- UML creately .

Source: https://habr.com/ru/post/J281995/


All Articles