【CMake入門と上級編(2)】CMakeのコンパイル設定 - 複数ソースファイルのコンパイルとライブラリファイルの生成(コード付き)

複数のソースファイル       

        前回の記事では、単一のソース ファイルの cmake コンパイルについて学びましたが、ソース ファイルの例は意味がないと思われるので、hello.h ヘッダー ファイルと hello.c ソース ファイルを追加してみましょう。hello 関数は hello.c ファイルで定義されており、この関数は main.c ソース ファイルで呼び出されます。

        ⚫ hello.h ファイルの内容

#ifndef __TEST_HELLO_
#define __TEST_HELLO_

void hello(const char *name);

#endif //__TEST_HELLO_

        ⚫ hello.c ファイルの内容

#include <stdio.h>
#include "hello.h"

void hello(const char *name){
 printf("Hello %s!\n", name);
}

        ⚫ main.c ファイルの内容

#include "hello.h"

int main(void){
 hello("World");
 return 0;
}

        ⚫ 次に、CMakeLists.txt ファイルを準備します。

project(HELLO)
set(SRC_LIST main.c hello.c)
add_executable(hello ${SRC_LIST})

        プロジェクトのディレクトリ構造は次のとおりです。

├── build //文件夹
├── CMakeLists.txt
├── hello.c
├── hello.h
└── main.c

        同様にビルドディレクトリに入り、cmakeを実行し、さらにmakeを実行してプロジェクトをコンパイルすると、最終的に実行ファイルhelloが取得されます。

        この例では、CMakeLists.txt ファイルで set コマンドが使用されています。set コマンドは、変数を設定するために使用されます。変数が存在しない場合は、変数を作成して設定します。この例では、SRC_LIST 変数を定義します。 SRC_LIST 変数はソース ファイル リストで、実行可能ファイル hello の生成に必要なソース ファイル main.c と hello.c を記録し、この変数は add_executable コマンドで参照されます。もちろん、ソース ファイルを直接書き込むこともできます。 SRC_LIST 変数を定義せずに add_executable に list コマンド内で次のようにします。

add_executable(hello main.c hello.c)

ライブラリファイルを生成する

       この例では、実行可能ファイル hello を生成することに加えて、hello.c を静的ライブラリ ファイルまたは動的ライブラリ ファイルにコンパイルする必要もあります。前の例に基づいて、CMakeLists.txt ファイルを次のように変更します。

project(HELLO)
add_library(libhello hello.c)
add_executable(hello main.c)
target_link_libraries(hello libhello)

        ビルド ディレクトリに移動し、cmake を実行し、次に make を実行してプロジェクトをコンパイルします。コンパイルが完了すると、以下に示すように、実行可能ファイル hello とライブラリ ファイルがビルド ディレクトリに生成されます。

         ディレクトリ構造は次のとおりです。

├── build
│ ├── hello
│ └── liblibhello.a
├── CMakeLists.txt
├── hello.c
├── hello.h
└── main.c

CMakeLists.txt ファイルの説明

        この例では、add_library コマンドと target_link_libraries コマンドを使用しました。add_library コマンドは、ライブラリ ファイルの生成に使用されます。この例では、2 つのパラメータを渡します。最初のパラメータは、ライブラリ ファイルの名前を示します。この名前には、プレフィックスとサフィックスが含まれていないことに注意してください。Linux では、 system 、ライブラリ ファイルのプレフィックスは lib、ダイナミック ライブラリ ファイルのサフィックスは .so、スタティック ライブラリ ファイルのサフィックスは .a であるため、最終的に生成されるライブラリ ファイルに対応する名前が自動的に付けられることを意味します。プレフィックスとサフィックスを追加します。

        2 番目のパラメータは、ライブラリ ファイルに対応するソース ファイルを示します。

        この例では、add_library コマンドにより静的ライブラリ ファイル liblibhello.a が生成されます。動的ライブラリ ファイルを生成したい場合は、次のように実行できます。

add_library(libhello SHARED hello.c) #生成动态库文件
add_library(libhello STATIC hello.c) #生成静态库文件

target_link_libraries コマンドは、ターゲットの依存ライブラリを指定します。この例では、hello.c がライブラリ ファイルとしてコンパイルされ、hello プログラムにリンクされます。

生成されたライブラリファイル名を変更します

         この例では、非常に不快な点が 1 つあります。生成されたライブラリは liblibhello.a で、その名前は非常に醜いです。liblibhello.a を生成したい場合はどうすればよいでしょうか? 次のようにadd_libraryコマンドのパラメータを直接変更することは可能でしょうか?

add_library(hello hello.c)

        答えは「いいえ」です。hello ターゲットがすでに存在し (add_executable(hello main.c))、ターゲット名はプロジェクト全体で一意であり、同じ名前のターゲットは存在できないため、この方法は絶対に不可能です。上記では、次のコマンドを CMakeLists.txt ファイルに追加するだけです。

set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

        set_target_properties は、ターゲットのプロパティを設定するために使用されます。ここでは、libhello ターゲットの OUTPUT_NAME プロパティが set_target_properties コマンドによって設定され、hello に設定されます。

        実験を行っており、CMakeLists.txt ファイルの内容は次のとおりです。

cmake_minimum_required(VERSION 3.5)
project(HELLO)
add_library(libhello SHARED hello.c)
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")
add_executable(hello main.c)
target_link_libraries(hello libhello)

        set_target_properties コマンドの追加に加えて、現在のプロジェクトに必要な cmake の最小バージョン番号を設定するために使用される cmake_minimum_required コマンドも追加しました。もちろん、これは必須ではありませんが、追加することをお勧めします。ビルド ディレクトリに移動し、cmake+make を使用してプロジェクト全体をコンパイルします。コンパイルが完了すると、生成されたライブラリ ファイルが liblibhello.a ではなく libhello.a であることがわかります。

├── build
│ ├── hello
│ └── libhello.so
├── CMakeLists.txt
├── hello.c
├── hello.h
└── main.c

ソースファイルを別のディレクトリに整理する

        上記の例では複数のソースファイルを追加しましたが、これらのソースファイルはすべて同じディレクトリに配置されており、形式的ではないため、ソースファイルはタイプ、関数、モジュールに応じて異なる場所に配置する必要があります。作成者がプロジェクトのソースコードを整理しました。現在のディレクトリ構造は次のとおりです。

├── build #build 目录
├── CMakeLists.txt
├── libhello
│ ├── CMakeLists.txt
│ ├── hello.c
│ └── hello.h
└── src
 ├── CMakeLists.txt
 └── main.c

        プロジェクト ディレクトリに src ディレクトリと libhello ディレクトリを作成し、hello.c ファイルと hello.h ファイルを libhello ディレクトリに移動し、main.c ファイルを src ディレクトリに移動し、トップ ディレクトリに libhello ディレクトリと src を移動しました。ディレクトリの下に CMakeLists.txt ファイルがあります。CMakeLists.txt ファイルの数が 1 から 3 に変わり、突然少し準備ができていないように感じました。幸いなことに、どれも複雑なものではありません。各 CMakeLists.txt ファイルの内容を見てみましょう。

        ⚫ トップレベルの CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(HELLO)
add_subdirectory(libhello)
add_subdirectory(src)

        ⚫ src ディレクトリ内の CMakeLists.txt

include_directories(${PROJECT_SOURCE_DIR}/libhello)
add_executable(hello main.c)
target_link_libraries(hello libhello)

        ⚫ libhello ディレクトリ下の CMakeLists.txt

add_library(libhello hello.c)
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

        add_subdirectory コマンドはトップレベルの CMakeLists.txt で使用され、cmake にサブディレクトリ内で新しい CMakeLists.txt ファイルを見つけて解析するように指示します。また、src の CMakeList.txt ファイルには、次のことを示す新しい include_directories コマンドが追加されます。ヘッダー ファイルの場所はパスであり、パスを指す PROJECT_SOURCE_DIR 変数が使用されます。名前から、この変数はプロジェクト ソース コードのディレクトリを表します。

        前と同様に、ビルド ディレクトリに移動してビルドとコンパイルを行い、最後に実行可能ファイル hello (build/src/hello) とライブラリ ファイル libhello.a (build/libhello/libhello.a) を取得します。

├── build
│ ├── libhello
│ │ └── libhello.a
│ └── src
│   └── hello
├── CMakeLists.txt
├── libhello
│ ├── CMakeLists.txt
│ ├── hello.c
│ └── hello.h
└── src
 ├── CMakeLists.txt
 └── main.c

生成された実行可能ファイルとライブラリ ファイルを別のディレクトリに配置します。

        デフォルトでは、cmake が生成する中間ファイル (CMakeCache.txt、CmakeFiles、cmake_install.cmake、Makefile など) に、make コンパイルで生成される実行ファイルやライブラリ ファイルが混在します。コマンド、つまり、それらは同じディレクトリ内にあります。実行可能ファイルを bin ディレクトリに個別に配置し、ライブラリ ファイルを lib ディレクトリに個別に配置したい場合は、次のようにします。

├── build
├── lib
│ └── libhello.a
└── bin
  └── hello

        ライブラリファイルはbuildディレクトリ配下のlibディレクトリに、実行ファイルはbuildディレクトリ配下のbinディレクトリに格納するのですが、この場合はどうすればよいでしょうか?現時点では、2 つの変数を通じてこれを実現し、src ディレクトリ内の CMakeList.txt ファイルを次のように変更します。

include_directories(${PROJECT_SOURCE_DIR}/libhello)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
add_executable(hello main.c)
target_link_libraries(hello libhello)

        次に、libhello ディレクトリ内の CMakeList.txt ファイルを次のように変更します。

set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
add_library(libhello hello.c)
set_target_properties(libhello PROPERTIES OUTPUT_NAME "hello")

        修正完了後、再度手順に従ってプロジェクトをビルド、コンパイルすると、生成された実行ファイルhelloはbuild/binディレクトリに、ライブラリファイルlibhello.aはbuild/libディレクトリに配置されます。要件に従ってディレクトリを作成します。最終的なディレクトリ構造は次のようになります。

├── build
│ ├── bin
│ │ └── hello
│ └── lib
│   └── libhello.a
├── CMakeLists.txt
├── libhello
│ ├── CMakeLists.txt
│ ├── hello.c
│ └── hello.h
└── src
  ├── CMakeLists.txt
  └── main.c

        実際、この要件を実現するのは非常に簡単です。LIBRARY_OUTPUT_PATH 変数と EXECUTABLE_OUTPUT_PATH 変数を設定することで実現できます。EXECUTABLE_OUTPUT_PATH 変数は実行可能ファイルの出力パスを制御し、LIBRARY_OUTPUT_PATH 変数はライブラリ ファイルの出力パスを制御します。

おすすめ

転載: blog.csdn.net/cj_lsk/article/details/131001173