コンパイルし、Windows、macOS、Linux 上で確実に実行する C アプリケーションを構築するには、ポータブルソースコードよりも多く必要です。各プラットフォームのネイティブツーリングに適応するビルドシステムが必要です。CMake、オープンソースのビルドシステムジェネレーター、簡単な設定ファイルでプロジェクトを定義し、プラットフォーム固有のビルドファイル(Makefiles、 Visual Studio ソリューションファイル、Xcode プロジェクトなど)を生成することで、この問題を解決します。この記事では、CPI プラットフォームの基本的な構成ファイルや、CPI などのクロスプラットフォーム固有のビルドファイルの作成、CAPI をクロスプラットフォーム固有のビルドする、CAPI などのシステム構築を徹底的に行うためのガイドを提供しています。

CMakeとは?

CMakeはメタビルドシステムです。コードを直接コンパイルするわけではなく、他のビルドシステムに入力ファイルを生成します。ドメイン固有の言語を使用して、プロジェクトを]に記述します。 CMakeはこれらのファイルを読み、ターゲットプラットフォームの適切なビルド指示を出力します。

CMakeの主要特性は下記のものを含んでいます:

  • [] プラットフォームアグノスティックシンタックス:[]] と同じ []] は、Unix、Windows、macOS で動作します。
  • マルチジェネレータ:]]]サポートメイク、忍者、ビジュアルスタジオ、Xコード、その他。
  • ] 外部のビルド:[ ソースコードとは別々にビルドアーティファクトを保持します。
  • [拡張性:[]]]モジュール、関数、マクロは再利用可能なビルドロジックを可能にします。
  • []パッケージの発見:] []]は、インストールされたライブラリとヘッダを見つけます。
  • CI/CD:[ との統合は、自動化されたパイプラインでシームレスに動作します。

CMakeは、LLVM、MySQL、KDEデスクトップ環境全体としてさまざまなプロジェクトで使用されるCとC++エコシステムにおけるクロスプラットフォーム開発のためのデファクト規格になりました。

十字プラットフォームC開発用CMakeを利用するメリット

CMakeを採用することで、単純な移植性よりもいくつかの具体的な利点をもたらします。

  • [] の単元:]] ビルドロジックを一度書き、各プラットフォームのファイルを生成し、壊れやすいシェルスクリプトやプラットフォーム固有の Makefile を排除します。
  • []IDEの統合:[]]チームは、同じ[を共有しながら、Visual Studio、CLion、Xcode、またはVSコードで動作させることができます。
  • モーダルプロジェクト構造:[]] を使用して、大規模なプロジェクトを自身の依存関係で管理可能なコンポーネントに分割します。
  • [条件付きロジック:[]] プラットフォーム固有のフラグ、ソースファイル、またはライブラリを必要に応じて、設定全体を複製することなく適用します。
  • ]自動依存処理:[ および]]]は、サードパーティのライブラリを使用して簡単にします。
  • [] 試験・包装:] CTest と CPack は統合され、テストを追加し、インストーラーを作成しようとします。
  • ビルド性能:]]忍者ジェネレーターとCCacheの組み合わせで再構築時間が劇的に減少します。
  • []Activeコミュニティ:]] 徹底した の公式ドキュメント とモジュールとチュートリアルの繁栄の生態系。

スタート:CプロジェクトでCMakeの設定

このセクションでは、インストールからコンパイルされた実行可能まで、完全なワークフローを3つの主要なプラットフォームで移動します。

1. CMakeをインストール

cmake.orgから最新のバイナリをダウンロードするか、システムのパッケージマネージャを使用する:

  • Linux (Debian/Ubuntu):[ ]]
  • macOS (Homebrew):[] ]
  • Windows:]]インストーラを実行し、「システムPATHにCMakeを追加」を選択していることを確認します。

でインストールを確認します。 ここに議論された機能については、バージョン3.10以上が推奨されます。

2. 最小限のCMakeLists.txtを書く

プロジェクトルートでというファイルを作成します。以下は、単一ソースCプロジェクトの場合の最小限の例です。

cmake_minimum_required(VERSION 3.10)
project(HelloWorld C)

add_executable(hello main.c)

故障:

  • は、最低の CMake バージョンを設定します。これにより、動作を改善するためのポリシー更新も有効になります。
  • [] はプロジェクト名と言語を定義します。 [ を指定すると、CMake が C++ コンパイラのスキャンから保護されます。
  • は、対象 ] が から構築されるべきCMakeを語ります。

もう少し現実的な例では、コンパイラフラグとヘッダのみの依存性を追加します。

cmake_minimum_required(VERSION 3.15)
project(Calculator C)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

add_executable(calc main.c parser.c)
target_include_directories(calc PRIVATE include)

ここでは ] は ]] の対象のみのコンパイラのヘッダー検索パスに [ を追加します。

3. ビルドファイルを生成する

ビルドディレクトリを作成し、CMakeを実行します。

mkdir build
cd build
cmake ..

Linux/macOS では、デフォルトで Makefile が生成されます。 Visual Studio をインストールした Windows では、 ファイルを生成します。異なるジェネレータをリクエストするには、 を使用します。

生成後、設定時にオプションを渡すことができます。

cmake .. -DCMAKE_BUILD_TYPE=Release -DMY_FEATURE=ON

これらの変数は [] に保存され、その後の実行時に再使用されます。

4. プロジェクトの構築

ビルドファイルが生成されると、コンパイル:

  • メイク/忍者:[ (プラットフォームとジェネレーターのすべての作業)
  • ビジュアルスタジオ:[]
  • Xcode: ]

コマンドは、クロスプラットフォームでプラットフォーム固有の呼び出しを回避します。ビルドを高速化するために、 を使用します。

世界で活躍するCMakeの高度な技術

基本を超えて、CMakeはより大きな複雑なビルドを合理化する機能を提供します。これらをマスターすると、時間を節約し、エラーを減らすことができます。

依存関係をfind package で管理

[ コマンドは、インストールされたライブラリを見つけ、パスとライブラリファイルを含む変数を設定します。 モダン CMake は、 ] インポートされたターゲット] を使用して、 クリーンな依存性伝播を促します。

find_package(SDL2 REQUIRED)
target_link_libraries(my_app PRIVATE SDL2::SDL2)

インポート対象は、ディレクトリ、コンパイル定義、リンクフラグを自動的にキャリーします。ライブラリがCMake configファイルを提供しない場合は、検索モジュールが必要な場合があります。 ]]cmake-developerでコミュニティのものに依存するか、自分で書きます。

システム全体のインストールなしでの依存関係については、[]]]は、設定時にソースコードをダウンロードして統合します。

include(FetchContent)
FetchContent_Declare(
 zlib
 GIT_REPOSITORY https://github.com/madler/zlib.git
 GIT_TAG v1.3
)
FetchContent_MakeAvailable(zlib)
target_link_libraries(my_app PRIVATE zlib)

このアプローチは、特定のバージョンをピン留めすることにより、再現可能なビルドを保証します。

CTest でテストを追加する

CMakeはCTest を通じてテストを統合します。 でテストを有効にして定義します。

enable_testing()

add_executable(test_parser test_parser.c)
target_link_libraries(test_parser PRIVATE parser_lib)

add_test(NAME ParserTest COMMAND test_parser)

でテストを実行します。:

ctest --output-on-failure

CTest は、テストフィクスチャ、ラベル、タイムアウト、並列実行をサポートしています。より包括的なテストでは、ライブラリと を使用して、ライブラリと使用することで、 のようなユニットテストフレームワークと組み合わせることを検討してください。

クロスコンパイル

CMakeは[ツールチェーンファイル]を介して相互コンパイルを簡素化します。 ツールチェーンファイルはコンパイラ、sysroot、およびターゲットアーキテクチャを設定します。 []のようなファイルを作成します。

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_SYSROOT /path/to/sysroot)

それからツールチェーンとCMakeを呼び出します:

cmake -DCMAKE_TOOLCHAIN_FILE=arm-cross.cmake ..

CMakeは、指定されたクロスコンパイラを自動的に使用し、ライブラリのsysrootを検索します。 この技術は、組み込みシステム、モバイルプラットフォーム、およびビルドマシンが対象マシンと異なる任意のシナリオのために動作します。 詳細については、公式[クロスコンパイルを参照してください。

インストールとパッケージング

コマンドを使用して、プロジェクトがデプロイされるべき方法を定義します。

install(TARGETS my_app DESTINATION bin)
install(FILES config.ini DESTINATION etc)

CPack はインストーラーを生成します。 DEB、RPM、NSIS、DMG など。 [ の最後に追加します。

include(CPack)

Debianパッケージを生成するには、を実行します。CPackはすべてのインストールルールを継承し、のような変数を使ってカスタマイズできます。

一般的なピッタフォールとベストプラクティス

経験豊富な開発者がスナッグを打つ。 頻繁に問題とそれらを避ける方法は次のとおりです。

ピットフォール:ハードコーディングパス

では絶対パスを使用しないでください。 と は、ソースツリーに相対的に使用します。 実行時ファイルの場所については、 [] を使用して、パスを埋めたり、インストールディレクトリに依存します。

ピットフォール: ジェネレーター式を無視する

ジェネレータ式()はビルド時に評価し、時間を設定しない。 それらは、設定設定設定ごとに不可欠です。

target_compile_definitions(my_app PRIVATE
 $<$<CONFIG:Debug>:_DEBUG>
)

デバッグビルドのみ[を追加します。マルチコンフィグジェネレータ(Visual Studio、Xcode)が設定時に[を設定しないため、[]を使用しないでください。

落札:グローバルコマンドをオーバーユース

、、 ]などのコマンドは、すべてのターゲットに影響します。 、 、 ]などの優先対象固有のコマンドは、より優れたカプセル化のために使われます。

落札: 適切なスコープを使ってfind package を使わない

[ スコープを適切に設定します。 近代的なCMakeでは、 を選択し、そのターゲットをリンクします。 ] を使用し、手動でリンクディレクトリを設定しないでください。

コンテンツ

CMakeは、マルチプラットフォームC開発の課題を管理可能な繰り返し処理に変えます。単一のビルド手順を書くことで、ネイティブパフォーマンス、IDEサポート、および主要なオペレーティングシステム全体で堅牢な依存性管理を得ることができます。シンプルな[から始まり、プロジェクトが成長するにつれて、テスト、クロスコンパイル、パッケージングといった高度な機能が徐々に採用されます。CMakeを学ぶ投資は、単一のコードを作成せずに、さまざまなプラットフォームで構築、テスト、またはデプロイするたびにCMakeを支払います。