2017-12-13 10 views
5

プロジェクトでは、CMakeでAndroid gradleyスクリプトを使用していますが、gradleプラグインはバージョン3:0:0、CMakeバージョン3.6です。 gradleとCMakeの両方のファイルはかなりシンプルで面白くありません(使用するファイルを定義するだけで、必要に応じてコピー&ペーストできます)。CMake共有プロジェクトのサブディレクトリが再構築されない

私は以下のプロジェクト構造を持っています。基本的には、数十個の.soファイル(apkにパッケージ化され、それによって「実行可能ファイル」と呼ばれるAndroidパッケージのネイティブ部分)を生成するコードベースです。これらはすべて、同じ共有ライブラリコード(静的ライブラリ、 ')。ライブラリコードはまだ(比較的)揮発性であるため、実行可能ファイルにプロジェクトレベルの依存関係を持たせて、実行可能ファイルがビルドされるたびにコードが変更されるたびにライブラリをオンデマンドで再構築するようにします。 構造のようになります。図書館のCMakeListsは、実行可能ファイルのプロジェクトは

add_subdirectory(${PROJECTS_ROOT}/LibProjects/${LibraryName} ${PROJECTS_ROOT}/Framework/Bin/Android/${ANDROID_ABI}/${LibraryName})... 
『通常通り』のライブラリの依存関係を追加

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY {CMAKE_CURRENT_SOURCE_DIR}/../Bin/${ANDROID_ABI}/${LibraryName}) 

を使用してBinフォルダにその出力をリダイレクト

+ LibProjects/ 
---Bin/ (Originally empty) 
---Lib1/CMakeLists.txt (+sources files, same level as the CMakeLists.txt) 
... 
---Lib10/CMakeLists.txt (same) 
+ Executables/ 
---Executable1/CMakeLists.txt (source files here) 
--------------/AndroidFiles/build.gradle (and other android project files)(points to the CMakeLists.txt) 
... 
---Executable40/CMakeLists.txt 

私は感覚的な実行可能ファイルを得ることができ、実行可能ファイルはライブラリのビルドをトリガするという意味で、ほとんどすべてが動作します。

問題は、実行可能ファイルを順番にビルドするときに、それぞれがライブラリプロジェクトの出力を再利用しないことです。Executable1をビルドすると、すべてのライブラリ(通常)がビルドされ、ビルドされます。その後、私はExecutable2をビルドすると、既にExecutable1用に構築されたライブラリを再利用しません。これによりビルド時間が10分の1になります。

各ライブラリのビルドの出力は、期待通りに/ Binフォルダ内にありますが、実行可能ファイル間で再利用されることはありません.CMakeの "プロジェクトファイル"(これは正しい用語です)はbinフォルダにありませんそれらのすべてが実行可能ビルドディレクトリ内で生成されます。

私が解決しようとしている問題は、各ライブラリが各実行ファイルに対して再構築されるという事実から生じるビルド時間です。

私が検討している解決策は、何とかCMakeに、実行可能ファイルではなく、独自のフォルダ内の各ライブラリの作業フォルダとしてBinフォルダ(または別のフォルダ)を使用するように指示して、gradle android plugin cmakefilesもオブジェクトファイルも再生成する必要がなく、再構築を避けることができるほどスマートになります。

私はコードベース自体を再構築できないこと、そして各実行ファイルは別々にビルド可能でなければならないということです - 最上位のCMakeの可能性は全くありません - 各実行ファイルが起動できるはずですそのままで。

+0

あなたはExecutable1の下にしかありませんか?あるいはこれらのうち40個はありますか? –

+0

依存関係の問題のように見えますが、ターゲットがすべてのターゲットの依存関係を明示的にリストしているかどうか確認できますか?また、ライブラリと実行可能ファイルの 'CMakeLists.txt'を投稿することもできます。 – AmeyaVS

+0

AndroidFiles私は40を持っています。私はCMakeListsを投稿することができますが、彼らはあなたに何も言わないでしょう - 依存関係は文字通り私が投稿したものです。それは行動が*期待されているという意味での "依存問題"ではない*それは私が欲しいものではない - 以下のOlivの答えを見る。 –

答えて

2

CMakeは、現在のビルドディレクトリから情報を読み込むことによって、ビルドが最新であるかどうかを判断できます。

Executables/<x>ディレクトリでCMake manualyを実行すると、cmakeはExecutable/<x>ディレクトリに関連付けられたビルドディレクトリから情報を取得します。次に、ビルドされたファイルのタイムスタンプが、このビルドディレクトリで実行された最後のビルドに対応するかどうかを確認します。そうでなければ、再構築する。あなたはExecutable1をビルドした後にLib1をビルドした後、Executalbe2でcmakeを実行し、Lib1ターゲットファイルのタイムスタンプを比較し、このファイルがcmakeビルドのこのインスタンスによって生成されていないことを確認してから、libを再ビルドします。等々。

の1-どちらのライブラリを構築し、binディレクトリに自分のターゲットファイルをインストールします(install cmakeのコマンドとexempleためmake install bashコマンドを使用して):

は、だから、2つのオプションがあります。次にExecutalbe<x>/CMakeListsではadd_subdirectoryの代わりにfind_libraryコマンドを使用します。

2-又は次の構造を有するスーパープロジェクト作成:

+ supper_project 
---CMakeLists.txt #add_subdirectory(LibProjects/lib<x>)... add_subdirectory(Executables/Executalbe<x>)... 
    + LibProjects/ 
    ---Bin/ (Originally empty) 
    ---Lib1/CMakeLists.txt (+sources files, same level as the CMakeLists.txt) 
    ... 
    ---Lib10/CMakeLists.txt (same) 
    + Executables/ 
    ---Executable1/CMakeLists.txt (source files here) 
    --------------/AndroidFiles/build.gradle (and other android project files) 
    (not any more:points to the CMakeLists.txt) 
    ... 
    ---Executable40/CMakeLists.txt 
+0

残念なことに、この回答は "申し訳ありません - 答えはありません"です - オプション1は避けたいものの1つ(2段階のビルディング)ですが、オプション2はオプションではありません - ビルドはミックス・アンド・マッチです。モノリス化。そのすべてが十分に公正です。誰かが何かを思い付くかどうかを私はしばらく待つでしょう、そうでなければ私はこれを授与します。 –

+0

明確化 - 私は現実ではなく、答えに失望しています:) –

+0

@Gerasimosミックス&マッチではどういう意味ですか?あなたは本当にあなたのアイデアとあなたの質問を明確にすべきです、私の答えはあなたがしていることに関する推測です。私は各ディレクトリに対してcmakeコマンドを実行することによって、各実行可能ディレクトリでビルドを実行していると思います。しかし、あなたの最後のコメントは私を混乱させる。私は確かにあなたの意図と実際に何をしているのか把握していません。 – Oliv

0

を私はこの問題は、あなたの依存関係を定義した方法であると思います。

実行可能ファイルごとに、add_subdirectoryを使用して別々のターゲットを作成しています。例: 実行可能ファイル1の場合はadd_subdirectory(${PROJECTS_ROOT}/LibProjects/${Library1})、実行ファイル2の場合はadd_subdirectory(${PROJECTS_ROOT}/LibProjects/${Library1})があるので、cmakeは実行可能ファイルのそれぞれのサブディレクトリに同じlibrary1の2つの別個のターゲットを作成し、別々のタイムスタンプとキャッシュファイルを作成します。そのため、同じライブラリを複数回構築しているように見えますが、実際にはcmakeのターゲットは異なっています。

これを修正するには、add_subdirectoryを使用して各実行可能ファイルのCMakeLists.txtに最上位CMakeLists.txtのすべてのライブラリを含めることができます。add_dependenciesコマンドを使用して依存関係を追加します。

+0

"トップレベル" cmakeの可能性はありません - 各 "実行可能ファイル"はそれぞれの "ライブラリ"に応じて別々のエンティティです。 –

+0

ライブラリの 'CMAKE_CURRENT_BINARY_DIR'を' CMAKE_BINARY_DIR'を絶対パスに設定してみてください。 –

+0

詳細を教えていただけますか? –

0

私はこの問題を回避することができましたが、結局CMakeではなく回避することでした。

私はCMakeFileレベルの依存関係(add_subdirectory)を削除し、のみ、リンクレベル(target_link_libraries実行[ライブラリファイル])でライブラリを左

をその後、私は各ライブラリのためのGradleスクリプトを作成し、これらに依存関係を追加しましたスクリプトを各アプリケーションgradleスクリプト内に作成します。その結果、ライブラリの構築はCMakeの依存関係の代わりにgradle依存関係によってトリガされます。それはgradleを避けることができる場合よりも遅くなりますが、毎回再構築するよりはるかに速く、オーバーヘッドは少なくとも一定です(1プロジェクトあたり数秒)。

関連する問題