前回はVS Code拡張 ”CMake Tools” のクイックスタートを使ってみました。これでとりあえず空のディレクトリを「CMakeできる」ようにしてくれた、と。ここを出発点に自分でCMakeLists.txtを書き換えて「お好み」な感じにしてみます。CMake Tools自体、設定すればいろいろやってくれそうではあるのですが、CMakeのお勉強かねて直接。
※ソフトな忘却力 投稿順 index はこちら
(PC上のVS Codeから、リモート接続したRaspberry Pi OS<32bit>機で作業しています。使用しているコンパイラは gcc 8.3.0 です。)
前回 VS CodeのExtensionである CMake Toolsのクイックスタートを使ってみました。これで、CPPソースからの実行ファイル生成プロジェクトの雛形と、ライブラリ生成プロジェクトの雛形が作れることが分かりました。実際には Hello world レベルです。も少し機能を追加したいです。今回は実行ファイル生成用の雛形ディレクトリの CMakeLists.txtを出発点に「改造」を試みました。改造にあたっては、以下のリファレンス・ドキュメントを参照させていただきましたが、ともかく分量多くて彷徨いますです。
まず、前回生成のCMakeLists.txt を見てみます。CTest と CPACK を除くと実体は以下のたった3行であることに気づきました。CTestはテストランナー、CPACKはインストーラという理解です。どちらも「後でやるつもり」です(本当にやれよ自分。)
cmake_minimum_required(VERSION 3.0.0) project(tst000 VERSION 0.1.0) add_executable(tst000 main.cpp)
なんだ3行じゃん、などと言いながら改造の方針は以下としました。
-
- 使用言語をCPPからCに変更
- 複数のソースファイルと階層をもったディレクトリ内のライブラリ・プロジェクトを含む
デフォルトで何も指定しないとCPPになるようです。今回はともかく「改造」ということで勝手にCに変更してみます。また、mainだけだったソースに、subという別ファイルやら、libサブディレクトリ内のfuncやらを追加してみました。階層構造はこんな感じになります。
-
- Project Root
- CMakeList.txt
- main.c
- sub.c
- sub.h
- lib
- CMakeList.txt
- func.c
- include
- func.h
- Project Root
さて、ルートにおかれたCMakeLists.txtの改造からです。まずは、cmake_minimum_requiredで指定しているバージョンを実際に使用されるcmakeのバージョンに合わせてみました。そうでなければならない理由はないのですが「改造」ということで。殊更に変更してみただけ。
cmake_minimum_required(VERSION 3.16.3)
次に project()を改造。自動生成されたものは、プロジェクト名とVERSIONのみを指定しており、言語については何も指定していませんでした。多分デフォはCPPなので、殊更に ”LANGUAGES C” 指定。当然ですが、実際のソースファイル類もCで書いておかねばなりませぬ。
project(tst000 VERSION 0.2.0 LANGUAGES C)
続いて肝心のビルドのターゲットですが、以下のような3行としてみました。まず、add_executable()は、ターゲット tst000、ソース入力ファイル main.cpp だったものを、ソース入力ファイルとして main.c と sub.c の2つを記述しました(当然、簡単なソースファイルを作成の上。)
続いてサブディレクトリ lib を掘ってその中に ライブラリ・プロジェクトを格納してみます。サブディレクトリを巻き込むため add_subdirectory(lib)などとしてみました。そしてサブディレクトリ内の処理の結果として、静的なライブラリ libfunc.a が生成される筈なので、ターゲット tst000 にライブラリ funcをリンクしてもらうため、target_link_libraries()行を加えてみました。Linuxなので、生成されるライブラリファイル名は libfunc.a ですが、ライブラリとしては func だけで通じてしまう、と。
なお、libfunc.a内の関数を参照するためのヘッダファイルは、libとは別なincludeディレクトリ内に保存してあるのですが、そこについては特に指定はしていませぬ。main.c内で#includeするときに相対パスで書いてあるので「見える」筈という目論見。ほんとか。
add_executable(tst000 main.c sub.c) add_subdirectory(lib) target_link_libraries(tst000 func)
続いて、libサブディレクトリ内のCMakeLists.txtです。ここのメインは只1行、add_libraryで、ソースファイル func.c から、ライブラリ func を作れ、という指令。これを処理すれば、buildディレクトリの配下に lib/libfunc.a が生成される筈。
cmake_minimum_required(VERSION 3.16.3) project(libfunc VERSION 0.1.0 LANGUAGES C) add_library(func func.c)
一応、肝心の main.c のソースはこちら。形だけの簡単なもの。
#include <stdio.h> #include "sub.h" #include "include/func.h" int main(int argc, char *argv[]) { printf("tst001\n"); printf("sub1: %d\n", sub1(1, 1)); printf("func1: %d\n", func1(3, 4)); }
次にmain.cの隣においてある、sub.h と sub.c。まずは sub.hの方です。
#ifndef SUB_H #define SUB_H int sub1(int a, int b); #endif /* SUB_H */
続いて sub.c、これまた形だけ。
int sub1(int a, int b) { return a + b; }
さて、ライブラリ用のヘッダ、includeサブディレクトリに格納されている func.hはこんな感じ。これまた代わり映えしない。
#ifndef FUNC_H #define FUNC_H int func1(int a, int b); #endif /* FUNC_H */
そして libサブディレクトリのライブラリ・ソースの実体がこちら。こんなものでライブラリ言うな、という感じ。
int func1(int a, int b) { return a * b; }
ともあれ、「こんなもん」でもビルドは通りました。コマンドラインから実行してみるとこんな感じ。
$ ./tst000 tst001 sub1: 2 func1: 12
動いたです。当然か。
次回はCPPに戻して、今度はシステムのライブラリモジュールとリンク必要になるような「も少し、まともなプログラム」をやってみますか。CTestはまだその先だな、先は長いです。