60

私は次のレイアウトを持っています:

top_project
    + subproject1
    + subproject2

とのそれぞれがスタティック ライブラリsubproject1を作成します。subproject2これらの静的ライブラリをレベルで単一の共有ライブラリにリンクしたいと思いtop_projectます。

これまでに収集した情報は次のとおりです。

  • -fPic静的ライブラリを単一の共有ライブラリにリンクできるようにする位置に依存しないコードを作成するために、(Windows 以外のすべてで必要)を使用してコンパイルするか、すべての静的ライブラリを解凍し (たとえば、を使用ar)、それらを共有ライブラリに再リンクします (これは、エレガントで移植性のないソリューションだと思います)
  • すべてのソースファイルは、add_libraryコマンドに明示的に指定する必要があります: 私が理解できない何らかの理由で、単に書き込みadd_library(${PROJECT_NAME} SHARED subproject1 subproject2)が期待どおりに機能しません (本質的に空のライブラリが作成され、依存関係が適切に登録されません)。
  • CMake には OBJECT ライブラリ機能がありますが、その目的は本当に私がやりたいことだとは思いません。

何かご意見は?

4

6 に答える 6

37

OK、私はそれを理解しました。これは、本来あるべきよりもはるかに苦痛です. ごく最近まで、Kitware の人々は、静的ライブラリから DLL を作成したい理由を理解していませんでした。彼らの主張は、top_projectそれが実質的に独自のプロジェクトであるため、メイン (たとえば私の場合) ディレクトリにソース ファイルが常に存在する必要があるというものです。私は物事の見方が異なり、top_project独立して存在してはならない小さなサブプロジェクトに分割する必要があります(つまり、それらのために本格的なプロジェクトを作成し、それらを使用して追加しても意味がありませんExternalProject_Add)。さらに、共有ライブラリを (たとえば Java Native Interface で使用するために) 出荷する場合、プロジェクトの内部レイアウトを公開することになるため、何十もの共有ライブラリを出荷したくありません。とにかく、静的ライブラリから共有ライブラリを作成することを主張したと思いますが、技術的な詳細に進みます。

subproject1およびの CMakeLists.txt でsubproject2、OBJECT ライブラリ機能 (CMake 2.8.8 で導入) を使用してターゲットを作成する必要があります。

add_library(${PROJECT_NAME} OBJECT ${SRC})

whereSRCはソース ファイルのリストを指定します (ファイルの追加や削除など、CMakeLists.txt の変更が検出されたときに make が CMake を再起動できるようにするため、これらは CMakeLists.txt ファイルで明示的に設定する必要があることに注意してください)。

top_project、次を使用してサブプロジェクトを追加します。

add_subdirectory(subproject1)
add_subdirectory(subproject2)

スタティック ライブラリのシンボルを表示するには、次を使用します。

set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--export-all-symbols")

次に、以下を使用して共有ライブラリを作成できます。

add_library(${PROJECT_NAME} SHARED $<TARGET_OBJECTS:subproject1>
                                   $<TARGET_OBJECTS:subproject2>)

「通常の」ライブラリ (つまり、オブジェクトではない) は別のコマンドで追加する必要があることがわかりましたadd_library。そうしないと、単純に無視されます。

実行可能ファイルの場合、次を使用できます。

add_executable(name_of_executable $<TARGET_OBJECTS:subproject1>
                  $<TARGET_OBJECTS:subproject2>)
set(LINK_FLAGS ${LINK_FLAGS} "-Wl,-whole-archive")
target_link_libraries(name_of_executable ${PROJECT_NAME}

繰り返しますが、これは CMake のバージョン 2.8.8 以降でのみ機能します。同様に、CMakeは依存関係を非常にうまく管理し、クロスプラットフォームです。これは、単純な古いMakefileよりも痛みが少なくなく、柔軟性が確かに低いためです.

于 2012-07-12T09:31:10.060 に答える
4

それを行う別の方法。

この方法はより簡単に思えますが、それがどれほど完璧かはわかりません。

https://stackoverflow.com/a/14347487/602340

于 2013-01-15T21:44:29.867 に答える
2

もう 1 つの方法は、すべてのプロジェクトのソース ファイルとヘッダー ファイルのパスを指定し、それらを一緒にビルドして .so を生成することです。これは通常、静的ライブラリを作成してから共有ライブラリを作成する代わりに、推奨される方法です。

基本的に、次のことを行う必要があります。

FILE(GLOB subproject1_sources
  <sub_project1_lib_sources_dir>/file1.c
  <sub_project1_lib_sources_dir>/file2.c //... etc
)

FILE(GLOB subproject2_sources
  <sub_project2_lib_sources_dir>/file1.c
  <sub_project2_lib_sources_dir>/file2.c //... etc
)

FILE(GLOB topProject_sources
  <top_project_lib_sources_dir>/file1.c
  <top_project_lib_sources_dir>/file2.c //... etc
)

include_directories("<sub_project1_lib_sources_dir>")
include_directories("<sub_project2_lib_sources_dir>")
include_directories("<top_project_lib_sources_dir>") //should be "." if you're building from here

add_library(topProject SHARED ${topProject_sources} ${subproject1_sources} ${subproject2_sources})
于 2015-05-29T20:07:08.440 に答える