26
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Organization

CMake入門-基本概念と主な関数

この記事は

CMakeというビルドマネジメントツールの入門的解説です。

CMakeとは

  • 公式サイト: https://cmake.org/
  • 主にC言語、C++などC系言語のビルドに利用される
  • CMake以前、C系言語のビルドには多数のビルドシステム(MakefileやNinjaやIDEなど)が乱立していた。これを隠蔽し包括的に扱える様にしたのがCMake
  • cmakeにはコマンド版とGUI版がある
    • ここではコマンド版のみ扱います。

CMakeの基本的な使い方

  1. ビルド対象のソースコード(*.c*.cppなど)を書く
  2. CMakeLists.txtを書く
  3. cmakeコマンドを利用してプロジェクトファイル(※)をGenerateする
  4. cmakeコマンドまたは各ビルドシステムを利用して、プロジェクトファイルからビルドする

プロジェクトファイルとは上記ビルドシステムがビルドする際の設定&指示ファイル
ビルドシステムによって異なり、Makefile*.sln*.xcodeproj*.ninjaなどがある。
cmake以前はこのプロジェクトファイル自体を直接記述してビルドしていたが、cmakeによりこのプロジェクトファイル生成が自動化されるようになった。

割愛(1. ビルド対象のソースコード(*.c*.cppなど)を書く)

ソースコード自体はこの記事のスコープ外なので割愛します。

2. CMakeLists.txtを書く

例えば、

プロジェクトルート/
 |- sample.cpp
 |- CMakeLists.txt

の様にファイルを用意し

CMakeLists.txt
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)

# set the project name and version
project(MyProject VERSION 1.0)

add_executable(sample.exe sample.cpp)

のようにCMakeLists.txtを記述します。

CMakeLists.txtには実行ファイルやライブラリファイルを生成する際に必要なソースファイルや手順(依存関係など)を記述しています。
なお、書き方は多岐に渡るため、詳細はこの記事では説明しません。

3. cmakeコマンドを利用してプロジェクトファイルをGenerateする

cmake [<options>] <path-to-source>
cmake [<options>] <path-to-existing-build>
cmake [<options>] -S <path-to-source> -B <path-to-build>

この様にcmakeコマンドを実行することでプロジェクトファイルを生成します。
の中にはジェネレータを指定する-Gなどもあります。

cmake -S . -B build/ -G"Unix Makefiles"

すると、 buildディレクトリにプロジェクトファイルであるMakefileやCMake関連のファイルが生成されます。

4. cmakeコマンドまたは各ビルドシステムを利用して、プロジェクトファイルからビルドする

cmake --build <dir> [<options>] [-- <build-tool-options>]
cmake --build <dir> --target <tgt>... [<options>] [-- <build-tool-options>]

のようなコマンドでビルドします。

cmakeコマンドで実行することも、ジェネレータで指定したビルドシステムのコマンド(makeなど)で実行することもできます。

  • <dir>3で指定した<path-to-build>を指定する。
    • <path-to-build>を指定していない場合はカレントディレクトリになっているはず。
  • targetについて
    • 明示的に指定すると指定したターゲットのみビルドされる
    • 指定しなかった場合はallターゲットが指定される
cmake --build build/ --target sample.exe

とするとsample.exeが生成されます。

ここで指定しているのはターゲット名であり、出力したいファイル名ではありませんので、やっぱりsample1.exeという名前のファイルで出力したいからと言って--target sample1.exeとしてもエラーになります。

CMakeの主な概念

プロジェクト

一纏まりのソースコードにつける名前。
通常一つ設定される。(使い方によっては複数のプロジェクトを含んだようなものもある。)
上述のビルドシステム用プロジェクトファイルのプロジェクトとは若干異なるもの。

CMakeLists.txtの中でproject関数を読んでプロジェクト名やバージョンなどを設定する。

ターゲット(target)

ビルドと言っても、一つのプロジェクトで複数の実行ファイルやライブラリファイルを作成したり、テスト実行したり、様々なタスクがある。
この一つ一つのタスクを指定したものがターゲット。

ターゲットには大きく以下の3種類がありCMakeLists.txt内に記述される。

  1. 実行ファイルの生成(add_executable)
  2. ライブラリファイルの生成(add_library)
  3. カスタムターゲットの実行(add_custom_target)

その他:

ジェネレータ(Generator)

各ビルドシステム(※)毎のプロジェクトファイルを生成するモジュールでCMakeでのプロジェクトファイル生成時には内部的に利用される。

※Makefile(Borland Makefiles, Unix Makefilesなど)やNinja、VisualStudioやXcodeなどIDEなどがある。

明示的にどのジェネレータを利用するかも指定可能。

プロパティと変数

*.cmakeファイル

(概念とはちょっと違うけど書いておきます。)

cmakeを利用しているプロジェクトではCMakeLists.txtだけでなく、*.cmakeといったファイルを作成しているものがあります。

出来ること/使える関数はCMakeLists.txtも*.cmakeも大差ありませんが、
CMakeList.txtファイルはCMakeList.txtファイルが配置されたディレクトリ毎の設定やターゲットや依存関係を書くのに対し、
*.cmakeファイルはディレクトリに依存しないので、CMakeList.txtで利用する関数やパラメータを定義やディレクトリに依存しないようなカスタムターゲットを作成するにに利用されます。

CMakeList.txtファイルからincludefind_packageといった関数を通して読み込まれます。

Makefileからcmake実行

(これも概念ではないですが書いておきます)

プロジェクトファイルを生成するためのCMakeですが、CMakeコマンド実行にもオプションがあり、そのコマンドを生成するためにMakefile/makeを利用しているオープンソースプロジェクトなどがあります。
生成対象のビルドシステムもMakefileだったりすると

(cmake実行用の)Makefileを用意する
↓
(makeコマンドから)cmake実行する
↓
(ビルド用の)Makefileが作成される

のようなMakefileを作るためにMakefileを用意する、といったややこしい構図になるため、初見だと混乱します。(というか私が混乱した)

主な関数と使い方(アルファベット順)

(自分の関心のあるものについて書いています。時々追加していくかもです。)

add_custom_target

他のターゲット作成関数のadd_libraryadd_executableで作成されるターゲットでは実行ファイルやライブラリファイルを生成するが、この関数はそういったファイル生成を目的としないターゲットを作成する。

ターゲット間の依存関係を設定するのにも利用される

add_dependencies

https://cmake.org/cmake/help/latest/command/add_dependencies.html
ターゲット間の依存性を設定する関数。
ターゲット実行時に依存性が設定されている場合、その依存先のターゲットが先立って実行されるようになる。

add_executable

https://cmake.org/cmake/help/latest/command/add_executable.html
実行ファイル生成ターゲットを作成します。

  • add_executableの使い方には以下の3種類があります。
    • Normal Executables
    • Imported Executables
    • Alias Executables

Normal Executables

add_executable(<name> [WIN32] [MACOSX_BUNDLE]
               [EXCLUDE_FROM_ALL]
               [source1] [source2 ...])

一般的な実行ファイル(*.exeなど)作成用のターゲットを作成します。

Imported Executables

add_executable(<name> IMPORTED [GLOBAL])

外部で生成された実行ファイル読み込むターゲット。
他のターゲットやその内部処理で該当の実行ファイルを利用する際に利用される。

Alias Executables

add_executable(<name> ALIAS <target>)

ターゲットに別名を付ける。

add_library

https://cmake.org/cmake/help/latest/command/add_library.html
ライブラリ生成ターゲットを作成します。

  • add_libraryの使い方には以下の5種類があります。
    • Normal Libraries
    • Object Libraries
    • Interface Libraries
    • Imported Libraries
    • Alias Libraries

Normal Libraries

add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            [<source>...])

一般的なライブラリファイル(*.lib*.aなど)作成用のターゲットを作成します。

STATIC,SHARED,MODULEについてはライブラリのリンク方法をきっちり区別しようが分かりやすいと思います。

STATIC

静的ライブラリ(ビルド時にリンクされるライブラリ)を作成する

SHARED

実行ファイルを実行するときに読み込まれる動的ライブラリを作成する

MODULE

プログラムが任意にライブラリをロードした時に読み込まれる動的ライブラリを作成する

Object Libraries

add_library(<name> OBJECT [<source>...])

オブジェクトライブラリを生成する。
オブジェクトライブラリは、ソースコードのコンパイルするが、ライブラリ間をリンクしたり、一纏めのファイルにしたりはしない。
例えば、

sample_lib1.cpp
sample_lib2.cpp

からライブラリ作成する際、Normal Librariesでは一つの*.so/*.a/*.dylibが生成されるが、オブジェクトライブラリとして作成すると、sample_lib1.cppのライブラリファイルとsample_lib2.cppのライブラリファイルの2つが生成される。

使い方としては、ここで指定したターゲットを最終生成物とするのではなく、他のターゲットが依存する先のターゲットとして利用する。

Interface Libraries

add_library(<name> INTERFACE)

ソースコードもコンパイルせず、実体としてのファイル生成もしないライブラリ生成用ターゲット

ここで設定したInterface Libraries
target_link_libraries(<target> INTERFACE <item>...)target_sources(<target> INTERFACE <item>...)などで他のターゲットと紐付けられた後、target_link_libraries()で目的のターゲットに紐付けられます。(ライブラリの橋渡しを行うようなイメージです。)

例:

add_library(my_interface_lib INTERFACE)

Interface Librariesを作成し

target_link_libraries(my_interface_lib INTERFACE some_lib)

で、Interface Librariesのmy_interface_libと(Interface Librariesではない)some_libとを紐付けた後、

target_link_libraries(main_target PRIVATE my_interface_lib)

のようにしてmain_targetとmy_interface_libを紐付けることで、
main_targetsome_libとを紐付けます。

Imported Libraries

add_library(<name> <type> IMPORTED [GLOBAL])

プロジェクト外で用意されたライブラリを読み込みます。

<type>はそのライブラリがどのタイプかを指定する。
STATIC, SHARED, MODULE, UNKNOWN, OBJECT, INTERFACEがある

  • STATIC, SHARED, MODULEについては上述の通り。
  • UNKNOWNはfind_package()で見つけたモジュールに対して利用する。(たぶん)
  • OBJECTはIMPORTED_OBJECTSというプロパティで指定したオブジェクトファイルの場所を元にオブジェクトライブラリターゲットを生成する
  • INTERFACEはINTERFACE_INCLUDE_DIRECTORIESINTERFACE_COMPILE_DEFINITIONSなどのINTERFACE_*プロパティを元にInterface Libraryを生成する(たぶん)

Alias Libraries

add_library(<name> ALIAS <target>)

add_subdirectory

https://cmake.org/cmake/help/latest/command/add_subdirectory.html
ソースコードを置いているサブディレクトリ追加する

例えば

プロジェクトルート/
 |- src/
  |- main.cpp
  |- CMakeLists.txt ・・・[1]
  |- modules/
    |- CMakeLists.txt ・・・[2]
    |- module1.cpp
    |- module2.cpp

のような構成のプロジェクトの場合CMakeLists.txt ・・・[1]からは同じディレクトリにあるmain.cppしか読読み込めない。
modulesディレクトリにあるソースコードを読み込むためにCMakeLists.txt ・・・[1]

add_subdirectory(modules)

の様に指定する。

cmake_parse_arguments

https://cmake.org/cmake/help/latest/command/cmake_parse_arguments.html
関数やマクロ定義の中で利用される。

例えば

function(my_install)
    set(options OPTIONAL FAST)
    set(oneValueArgs DESTINATION RENAME)
    set(multiValueArgs TARGETS CONFIGURATIONS)
    cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}"
                          "${multiValueArgs}" ${ARGN} )
    :
endfunction()

の様に内部でcmake_parse_argumentsを利用したmy_install関数を定義し、

my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub CONFIGURATIONS)

の様に呼び出すと、以下の様に変数が設定される

MY_INSTALL_OPTIONAL = TRUE
MY_INSTALL_FAST = FALSE # optionsのFASTは呼び出し時に指定しなかったのでFALSEになる。
MY_INSTALL_DESTINATION = "bin"
MY_INSTALL_RENAME <UNDEFINED> # one_value_keywordsのRENAMEは呼び出し時に指定しなかったのでない。
MY_INSTALL_TARGETS = "foo;bar" # multi_value_keywordsのTARGETSにはlistとして複数の値が指定される。
MY_INSTALL_CONFIGURATIONS <UNDEFINED> # multi_value_keywordsのCONFIGURATIONSは呼び出し時に指定しなかったのでない。
MY_INSTALL_UNPARSED_ARGUMENTS = "blub" # optionsの"OPTIONAL"の後に指定された変数はOPTIONALに紐付けられたりしない。
MY_INSTALL_KEYWORDS_MISSING_VALUES = "CONFIGURATIONS" # "CONFIGURATIONS"に対して値指定はなかった

少々複雑、以下を参照するとよいかも:
cmakeでオプション付きの関数を定義する

configure_file

configure_file(<input> <output>
               [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
               [NO_SOURCE_PERMISSIONS]
               [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])

ファイルをコピーしつつ、コピー元のファイルで@VAR@${VAR}で書かれた部分を該当の変数値で置き換える

file

多数のモードが有るが幾つかかいつまんで。

MAKE_DIRECTORY

file(MAKE_DIRECTORY [<directories>...])

ディレクトリを作成する

GLOB, GLOB_RECURSE

file(GLOB <variable>
     [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS]
     [<globbing-expressions>...])
file(GLOB_RECURSE <variable> [FOLLOW_SYMLINKS]
     [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS]
     [<globbing-expressions>...])

<globbing-expressions>(正規表現に似たもの)に一致するファイルのリストを<variable>に代入する
GLOB_RECURSEだとサブディレクトリ以下もチェックする。その際FOLLOW_SYMLINKSが指定されているとシンボリックリンクの先もチェックされる

RELATIVEが指定されていると指定されているパスからの相対パスとして処理される。

通常GLOBではディレクトリも含むが、LIST_DIRECTORIESがfalseになっているとディレクトリは省略される

なお、ソースコードを読み込むのにこのGLOBを利用するのは推奨されない。
GLOBだとファイルが追加・削除されたときに追従できないので。
(キャッシュを削除して処理すれば、、だが毎度時間がかかる)

READ

file(READ <filename> <variable>
     [OFFSET <offset>] [LIMIT <max-in>] [HEX])

<filename>から読み取って<variable>の変数に代入する

なお、読み込んだファイルの変数をどう使うかというと、string関数などで意図する文字列があるかをチェックして別の変数に代入したりする。

RELATIVE_PATH

file(RELATIVE_PATH <variable> <directory> <file>)

<directory>から<file>への相対パスを計算して<variable>に代入する

STRINGS

file(STRINGS <filename> <variable> [<options>...])

<filename>から読み取って一行毎を<variable>の変数にlistとして代入する

TO_CMAKE_PATH

file(TO_CMAKE_PATH "<path>" <variable>)

<path>に指定されたパス表記をCMake表記のパスに変換して<variable>に代入する

WRITE

file(WRITE <filename> <content>...)

<filename><content>の内容を書き込む

find_package

基本形
find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE]
             [REQUIRED] [[COMPONENTS] [components...]]
             [OPTIONAL_COMPONENTS components...]
             [NO_POLICY_SCOPE])

外部プロジェクトを探してその設定を読み込む。

主にcmakeインストール時に組み込まれて以下のコマンドで出てくるFind***というモジュールの読み込みに使う

cmake --help-module-list
  • <PackageName>:読み込む対象のパッケージ
  • [version]:必要とするパッケージバージョン
  • [EXACT]:上記バージョンと完全一致する必要があるか。(上記バージョンの記述でも指定出来るの)
  • [QUIET]:メッセージを出力するか否か
  • [MODULE]:後述のModuleモードかConfigモードかの指定
  • [REQUIRED]:REQUIRED指定して対象パッケージが存在しなかった場合はCMakeの処理を止める
  • [COMPONENTS]:対象パッケージが必要とするコンポーネント
  • [OPTIONAL_COMPONENTS]:対象パッケージが(必須ではなく)利用するコンポーネント
  • [NO_POLICY_SCOPE]:割愛

ModuleモードとConfigモード

Moduleモードでは
Find<PackageName>.cmake
というファイルを探し、見つかれば実行され、見つからなければConfigモードに移行する。

Configモードは以下の様に検索対象を詳細指定して検索する。
なお、Configモードでも見つからなかったらエラーメッセージを出力する。

find_package(<PackageName> [version] [EXACT] [QUIET]
             [REQUIRED] [[COMPONENTS] [components...]]
             [OPTIONAL_COMPONENTS components...]
             [CONFIG|NO_MODULE]
             [NO_POLICY_SCOPE]
             [NAMES name1 [name2 ...]]
             [CONFIGS config1 [config2 ...]]
             [HINTS path1 [path2 ... ]]
             [PATHS path1 [path2 ... ]]
             [PATH_SUFFIXES suffix1 [suffix2 ...]]
             [NO_DEFAULT_PATH]
             [NO_PACKAGE_ROOT_PATH]
             [NO_CMAKE_PATH]
             [NO_CMAKE_ENVIRONMENT_PATH]
             [NO_SYSTEM_ENVIRONMENT_PATH]
             [NO_CMAKE_PACKAGE_REGISTRY]
             [NO_CMAKE_BUILDS_PATH] # Deprecated; does nothing.
             [NO_CMAKE_SYSTEM_PATH]
             [NO_CMAKE_SYSTEM_PACKAGE_REGISTRY]
             [CMAKE_FIND_ROOT_PATH_BOTH |
              ONLY_CMAKE_FIND_ROOT_PATH |
              NO_CMAKE_FIND_ROOT_PATH])

参考CMakeを使ってみた (7) find_packageとpkg_check_modulesによるライブラリ探索

find_program

https://cmake.org/cmake/help/latest/command/find_program.html
find_program (<VAR> name)
例: find_program(LCOV_PATH lcov)
の様に利用

nameに該当するプログラムが(OS上に)存在する場合はに指定した変数に、その実行ファイルパスを格納する。
なかった場合は<VAR>-NOTFOUNDとなる

function

https://cmake.org/cmake/help/latest/command/function.html
独自の関数を定義するための関数

function(<name> [<arg1> ...])
  <commands>
endfunction()
function(foo)
  <commands>
endfunction()

と定義した関数は

foo()
Foo()
FOO()
cmake_language(CALL foo)

のいずれでも呼び出せるが、基本全て小文字で扱うことが推奨される

引数について

ARGC:渡された引数の数
ARGV#:"#"部分は数字(ARGV0,ARGV1,ARGV2,...)。渡された引数が入っている変数
ARGN:渡された引数がlistとして入っている変数。

引数を明示的に定義した場合

function(<name> SAMP_ARG1 SAMP_ARG2)
  <commands>
endfunction()

の様に引数を変数定義していれば、
SAMP_ARG1,SAMP_ARG2にもそれぞれ渡された引数値が入る。
この場合は

${SAMP_ARG1} == ${ARGV0}
${SAMP_ARG2} == ${ARGV1}

となる。
また、明示的に引数定義されている場合は、呼び出し時に対応する引数を渡さないとエラーになる。

get_filename_component

get_filename_component(<var> <FileName> <mode> [CACHE])

<FileName>に当てはまるファイル名やパス名を<var>の変数に代入する関数。

(<mode>では当てはまり方を指定する。)

get_filename_componentはCMakeのversion 3.19からcmake_path()に取って代わられています。

include

https://cmake.org/cmake/help/latest/command/include.html
上述の"**.cmake"のようなCMake codeを読み込んで実行*する

list

list変数を扱う関数で、様々なモードが有る。
なお、list変数の作成は通常変数と同じくset関数を利用する
また、list変数は内部的には;で区切られた文字列群

macro

macro(<name> [<arg1> ...])
  <commands>
endmacro()

マクロ作成関数

macroとfunctionは非常に似ているが以下の点で異なる

  • 変数の意味合いが違い、macroでのARGN,ARGC,ARGV,ARGV#といったものはCMakeとしての変数ではなく、C言語のプリプロセッサが置き換える場所になる。
    • 変数利用時の指定の仕方に注意が必要
  • functionは呼び出し時にfunction側に移動して実行されるが、macroは該当のソースコードを利用先に埋め込む形になる。
    • 特にmacro利用時はreturnのスコープに影響してややこしくなるので、macroではreturnは利用しない方が良い

message

https://cmake.org/cmake/help/latest/command/message.html
massage([<mode>] "message text")

cmakeコマンド実行時にメッセージ出力する

例:message(STATUS "Building for code coverage")
の様に利用

  • mode には幾つかあるが代表的なものだと
    • 指定無し or NOTICE: stderrに出力される
    • STATUS: ユーザが必要とするだろう情報
    • FATAL_ERROR: メッセージを出しつつ、処理を停止する

option

https://cmake.org/cmake/help/latest/command/option.html
CMakeLists.txt上で定義されたoptionは、cmakeコマンド実行時に指定出来るようになる

CMakeLists.txt
option(PYTHON_COVERAGE "Python code coverage" OFF)
if(PYTHON_COVERAGE)
    message(STATUS "python coverage enabled")
    set(PYTHON_EXECUTABLE coverage run -p)
endif()

と記述しておき、cmakeコマンド実行時に

cmake -DPYTHON_COVERAGE=ON

の様に実行する

project

https://cmake.org/cmake/help/latest/command/project.html
プロジェクト名やバージョンなどを設定する。

set

https://cmake.org/cmake/help/latest/command/set.html
通常変数、キャッシュ変数、環境変数を作成する。

通常変数例
set(VALUE_A a 1 2)
message(${VALUE_A})
→a12と表示される
キャッシュ変数例
set(VALUE_B 1234 CACHE STRING SampleCache)
message(${VALUE_B})
message($CACHE{VALUE_B})
→1234と表示される
通常変数と異なり、スクリプトのどこからでも生成・参照出来る

環境変数設定は利用例が少ないので割愛

set_property

https://cmake.org/cmake/help/latest/command/set_property.html
cmakeには変数(通常変数、キャッシュ変数、環境変数)とは別に、プロパティという各種動作設定が格納される変数領域があり、それを設定するためのもの。
プロパティ取得関数のget_propertyと対になる。

set_source_files_properties

set_source_files_properties(<files> ...
                            [DIRECTORY <dirs> ...]
                            [TARGET_DIRECTORY <targets> ...]
                            PROPERTIES <prop1> <value1>
                            [<prop2> <value2>] ...)

<files>に指定したソースファイルにProperties on Source Filesのプロパティ(※)を設定する

※例えばGENERATEDという、該当のソースファイルが、ビルド時に外部システムまたはCMake自身によって生成されるものかを指定することによって、非存在チェックを免除する設定などがある。

target_compile_definitions

target_compile_definitions(<target>
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

<target>に指定したターゲット実行時に、
- PUBLICPRIVATECOMPILE_DEFINITIONSの埋め込みをおこなう。
- COMPILE_DEFINITIONSとはターゲットのソースコードコンパイル時のプリプロセッサ定義。
- PUBLICINTERFACEINTERFACE_COMPILE_DEFINITIONSの埋め込みを行う。

要はソースコードの#ifdef XXXXXとかに埋め込む値の設定

target_compile_definitions(foo PUBLIC -DFOO)

の様に-Dで指定すると該当の項目は削除される

target_link_libraries

基本形
target_link_libraries(<target> ... <item>... ...)

ターゲットにライブラリを紐付ける。

  • <target>add_executableadd_libraryで生成されたターゲットを指定する。
  • <item>は幾つかパターンがある
    • add_libraryで生成された他のライブラリターゲット
    • ライブラリファイルへのフルパス
    • 素のライブラリ名(紐付けたいライブラリファイルがfoo.libだったらfoo)
    • リンクフラグ
    • ビルドシステムによってリンク(ビルド)時に指定されるオプションの指定
    • generator expression
    • 評価計算され、上記(ライブラリターゲット、フルパス、ライブラリ名など)として扱われる
    • debug, optimized, generalキーワードと上記の<item>
    • 詳細は割愛
target_link_libraries(<target>
                      <PRIVATE|PUBLIC|INTERFACE> <item>...
                     [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)

というような使い方が多い。
PRIVATE|PUBLIC|INTERFACEがそれぞれなんなのかは以下が詳しい。
参考CMake: target_link_libraries(PUBLIC/PRIVATE/INTERFACE) の実践的な解説

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
26
Help us understand the problem. What are the problem?