qmake を使ったビルド

このページは,Makefile 作成ツールのひとつ,qmake の使い方を理解する目的で作成しています.
開発言語は C++ です.素材は,定番の,端末に "Hello World." と出力するプログラムです.

qmake の特徴をマニュアルの冒頭部分から改変して引用すると,

インフォメーション

目次(ページ内リンク)

  1. qmake Manual のブラウズ
  2. Hello World.:まず最初に,端末に "Hello world." と出力する定番のプログラムを素材とし,ビルドします
  3. 共有ライブラリの作成:「Hello World」プログラムを改変して共有ライブラリを作成します
  4. 共有ライブラリの利用:作成した共有ライブラリを利用するプログラムを作成します
  5. 外部ライブラリの利用:本サイトで利用している eigen と libopenbabel を使う場合のプロジェクトファイルへの記述法を紹介します
  6. 動的ライブラリの作成:共有ライブラリのプログラムを改変して動的ライブラリを作成します
  7. 動的ライブラリの利用:作成した動的ライブラリを利用するプログラムを作成します

参考にしたページ

インストールした Debian パッケージ

パッケージ名(バージョン)
g++(14.2.0)GNU C++ コンパイラ
make (4.4.1)コンパイルを制御するユーティリティ
qmake6(6.8.2)Makefile 作成ツール
qt6-base-dev(6.8.2)動的ライブラリを作る際には必須です

qmake Manual のブラウズ

マニュアルの冒頭部分と "Overview" 部分を私なりにまとめてみました.

マニュアルの章立て

2025 年 11 月 21 日現在の qmake Manual の章立ては下のようになっていました.

Overview セクション

Overview セクションでは,qmake の使い方のヒントがまとめられています.また,次に読むと良さそうな章が推奨されています.

1.プロジェクトファイルの作成

qmake を使用するためには,プログラムのソースファイル以外に,プロジェクトファイルを作成する必要があります.
プロジェクトファイルとは,

といった,プログラムの詳細情報を qmake Language で記述したテキストファイルのことです.
qmake は,プロジェクトファイルの情報を読み取って,コンパイルやリンクに必要なコマンドを実行する Makefile を作成します.

このページのような単純なプロジェクトでは,ソースファイルとヘッダーファイル,およびいくつかの基本的な設定を記述するだけで充分です.
単純なプロジェクトファイルの作成方法については,Getting Started with qmake を参照してください.

複雑なプロジェクトの場合は,それに対応するより複雑なプロジェクトファイルを作成することになります.
プロジェクトファイルの概要については,Creating Project Files を参照してください.プロジェクトファイルで使用できる変数については,Reference セクションの Variables を,関数については同セクションの Replace FunctionsTest Functions を参照してください.

アプリケーション,ライブラリ,プラグイン向けにプロジェクトファイルを設定する方法については,Building Common Project Types を参照してください.

プロジェクトファイルの生成には qmake を使用することもできます.
qmakeのコマンドライン・オプションの詳細については,Running qmake を参照してください.

2.プロジェクトの構築

単純なプロジェクトであれば,プロジェクトのトップレベルのディレクトリで qmake を実行して Makefile を生成するだけで済みます.その後,プラットフォームの make ツールを実行して,Makefile に従ってプロジェクトをビルドすることができます.
ビルドプロセスを構成する際に qmake が使用する環境変数の詳細については,Configuring qmake をご覧ください.


Hello World.

ソースコード

プログラミング入門の定番,端末に "Hello World." と出力する実行ファイル hello を作成します,
下はソースファイル main.cc です,
qhello というディレクトリを作成し,そのなかに main.cc を入れてあります.

qhello/main.cc

#include <iostream>

int main() {
 std::cout << "Hello World." << std::endl;
 return 0;
}

最も簡単な使い方

このソースファイルなら,2 コマンドで Makefile が作成できます.したがって,3 コマンドでビルド終了です.
~/qhello$ qmake6 -project:プロジェクトファイルという Makefile 作成用の指示書を作成します
~/qhello$ qmake6 -makefile:Makefile を作成します.これは qmake6 のデフォルトの動作なので,qmake6 だけでも OK
~/qhello$ make

この手順だと,いくつか課題を思いつきます,例えば,

このあたりを改善してみます.

qmake によるプロジェクトファイルの作成

~/qhello$ qmake6 -project
としたら,下の内容を記した qhello.pro というプロジェクトファイルが生成します.
特に指定しなければ,プロジェクトファイルにはディレクトリの名前が付くようです.
# でコメントが始まります.

######################################################################
# Automatically generated by qmake (3.1) Fri Nov 21 08:53:42 2025
######################################################################

TEMPLATE = app
TARGET = qhello
INCLUDEPATH += .

# You can make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# Please consult the documentation of the deprecated API in order to know
# how to port your code away from it.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_UP_TO=0x060000 # disables all APIs deprecated in Qt 6.0.0 and earlier

# Input
SOURCES += main.cc

qhello.pro のコメント部分を削除し,さらに多少変更を加えたものを下に示します.
プロジェクトファイルで使用できる変数については,Reference セクションの Variables で説明されています.


TEMPLATE = app  #アプリケーションを作成する.ライブラリを作成する場合は lib と記す
TARGET = hello  #最終的に生成するファイルの名前.ここでは実行ファイル名
INCLUDEPATH += .  #インクルードすべきファイルが別のディレクトリにあれば,この書式で追加.+= は,C++ などのインクリメンタル演算子と同じ使い方
SOURCES += main.cc  #ソースファイルを追加.ヘッダファイルを追加する場合は,HEADDER += という行を作成

target.path = /usr/local/bin  #インストール先
INSTALLS += target  #インストールされるファイル.TARGET = で設定したファイル

QT = #Qt を使わない

qmake による Make ファイルの作成

引き続いて,
~/qhello$ qmake6make -makefile でも同じ)
としたら,Makefile が作成されました.さらに,.qmake.stash という隠しファイルも作成されていました.

ビルド

~/qhello$ make
としたら,

g++ -c -pipe -O2 -Wall -Wextra -D_REENTRANT -DQT_NO_DEBUG -I. -I. -I/usr/lib/x86_64-linux-gnu/qt6/mkspecs/linux-g++ -o main.o main.cc
g++ -Wl,-O1 -o hello  main.o   -lpthread

と出力されて,プロジェクトファイル qhello.pro に名前を記した実行ファイル hello が生成しました.
出力を見ると,Qt 関連のライブラリがリンクされていることが判ります.

インストールと実行

今回は,プロジェクトファイル qhello.pro に hello が /usr/local/bin にインストールされるように設定しています.
~/qhello$ sudo make install
と端末に入力するとインストールがおこなわれます.

~/qhello$ hello
とすると,"Hello World."と出力されました.
qmake を使ってプログラムのビルドとインストールができました.

なお,作成された Makefile で,アンインストールや作業ディレクトリの掃除も可能です.
~/qhello sudo make uninstall
~/qhello make distclean


共有ライブラリの作成

ライブラリは,プログラムの一部分を本体から分離したものです.
ここでは,上で作成したプログラムのなかから 端末に "Hello World." と出力する機能をグルーバル関数として分離し,共有ライブラリにしてみます.

ソースファイル

2 個のソースファイルを作業用のディレクトリ qlibhello に作成しました.

qlibhello
├─ hello.h
└─ hello.cc

hello.h


#ifndef ___HELLO
#define ___HELLO

#include <iostream>

void hello();

#endif

hello.cc


#include "hello.h"

void hello() {
 std::cout << "Hello World." << std::endl;
}

プロジェクトファイル

ソースファイルを格納したディレクトリで,端末に,
~/qlibhello qmake6 -project -t lib
とすると,ライブラリ用のプロジェクトファイル qlibhello.pro が生成します.
といっても TEMPLATE = の右辺が lib か app かの違いだけなので,qmake6 -project でプロジェクトファイルを作成し,後で修正しても手間はほぼ同じだと思います.


######################################################################
# Automatically generated by qmake (3.1) Sun Nov 23 05:39:33 2025
######################################################################

TEMPLATE = lib
TARGET = qlibhello
INCLUDEPATH += .

# You can make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# Please consult the documentation of the deprecated API in order to know
# how to port your code away from it.
# You can also select to disable deprecated APIs only up to a certain version of
 Qt.
#DEFINES += QT_DISABLE_DEPRECATED_UP_TO=0x060000 # disables all APIs deprecated
in Qt 6.0.0 and earlier

# Input
HEADERS += hello.h
SOURCES += hello.cc

プロジェクトファイルの修正

変更してコメント行を削除したものを下に示します.

qlibhello.pro


TEMPLATE = lib
TARGET = hello
INCLUDEPATH += .

HEADERS += hello.h
SOURCES += hello.cc

headersDataFiles.files = hello.h
headersDataFiles.path = /usr/local/include
INSTALLS += headersDataFiles

target.path = /usr/local/lib
INSTALLS += target

QT =

変更,追加箇所は,

ビルドとインストール

ソースファイルを格納したディレクトリで,端末に,
~/qlibhello qmake6
~/qlibhello make
~/qlibhello sudo make install
とすれば,以下のファイルがインストールされます.

キャッシュファイル /etc/ld.so.cache を作成しないと,プログラムから利用できません.
~/qlibhello sudo ldconfig

インターフェースバージョンの設定

libhello.so.1.0.0 が本体(real name)で,他はそれへのシンボリックリンクです.
so に続く数字はインターフェースバージョンといい,異なるバージョンのライブラリを共存させる仕組みです.インターフェースバージョンの付け方を勉強したときのまとめが,Autotools を使ったライブラリのビルドシステム#ライブラリインターフェースのバージョン管理にあります.

任意のインターフェースバージョンを設定するには,プロジェクトファイル qlibhello.pro に設定を追加します.
例えば,


VERSION = 1.2.3
CONFIG += version_number

とすると,ライブラリの名前は次のように変更されます.


共有ライブラリの利用

ここでは,上のセクションで作成した共有ライブラリを利用するアプリケーションを作成します.

ソースファイル

ソースファイル main.cc を作業用のディレクトリ qexehello に作成しました.qexehello.pro は,作業中に作成,編集します

qexehello
└─ main.cc

main.cc


#include <hello.h>

int main() {
 hello();
}

プロジェクトファイル

ソースファイルを格納したディレクトリで,端末に,
~/qexehello qmake6 -project
とするとプロジェクトファイルの雛形 qexehello.pro が作成できます.
コメント行を削除して,いくつか変更を加えたのが下のコードです.

qexehello.pro


TEMPLATE = app
TARGET = hello #実行ファイルの名前を変更.デフォルトではディレクトリの名前 qexehello が設定されます
#INCLUDEPATH += . コメントアウト
SOURCES += main.cc

#共有ライブラリを利用する際の g++ のコンパイルおよびリンクオプション
LIBS += -L/usr/local/lib/ -lhello
INCLUDEPATH += /usr/local/include

#インストール先の設定
target.path = /usr/local/bin
INSTALLS += target

QT =

ビルド,インストール,実行

ソースファイルを格納したディレクトリで,端末に,
~/qexehello qmake6・・・Makefile が生成します
~/qexehello make・・・実行ファイルが生成します
~/qexehello sudo make install・・・実行ファイルがインストールされます
~/qexehello hello
としたら端末に "Hello World." と表示されました.


外部ライブラリの利用

本サイトで開発している 分子モデリングソフト Builcule では,C++17 に含まれるライブラリ,線形代数テンプレートライブラリ Eigen: Main Page,libopenbabel(ライブラリ版 OpenBabel;Write software using the Open Babel libraryl)を利用しています.
qmake を使って これらををビルドするためには,プロジェクトファイルにそのための指示を記す必要があります.そのときに調べた設定を記しておきます.
なお,実際に qmakeで ビルドしているのは Builcule のみです.

C++17 を使う場合

プロジェクトファイルには次のように記述します.


CONFIG += c++17

Eigen を使う場合

Eigen はテンプレートライブラリなので,プロジェクトファイルにはヘッダファイルの位置を記すだけです.


INCLUDEPATH += /usr/include/eigen3

libopenbabel を使う場合

この場合は,プロジェクトファイルにヘッダファイルの位置とライブラリ本体のディレクトリを記します.


INCLUDEPATH += /usr/include/openbabel3
LIBS += -lopenbabel

動的ライブラリの作成

Creating Shared Libraries を参考にして,グローバル関数で動的ライブラリを作成します.タイトルが "shared" となっていますが,このサイトで言っているところの「共有ライブラリ」ではなくて「動的ライブラリ」です.
上で作成した,共有ライブラリを改変します.

ソースファイル

4 個のソースファイルを作業用のディレクトリ qlibhello に作成しました.

qlibhello
├─ hello_global.h
├─ hello.h
├─ hello.cc
└─ qlibhello.pro

ソースコード

hello_global.h

C++ では,動的ライブラリを使う側のプログラムから,dlopen() 関数で呼び出される関数には "extern "C" 宣言をするのでした(C++ による動的ライブラリの作成).qmake を使う場合は,特有のマクロを追加します.
hello_global.h は,そのためのヘッダファイルです.下のように定義した場合には,"extern "C" 宣言の代わりに "HELLO_EXPORT" マクロを追加します.


#include <QtCore/QtGlobal>

#if defined(HELLO_LIBRARY)
#  define HELLO_EXPORT Q_DECL_EXPORT
#else
#  define HELLO_EXPORT Q_DECL_IMPORT
#endif

hello.h

hello() 関数には "extern "C" 宣言に続いて "HELLO_EXPORT" マクロを追加しました.
"extern "C" 宣言がないと,ライブラリがロードできませんでした(ライブラリを利用するプログラムが実行時エラーになりました).


#include "hello_global.h"

extern "C" HELLO_EXPORT void hello();

hello.cc


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

void hello() {
 std::cout << "Hello World." << std::endl;
}

qlibhello.pro

プロジェクトファイルには,hello_global.h で定義した HELLO_LIBRARY を追加します.


TEMPLATE = lib
TARGET = hello
INCLUDEPATH += .

HEADERS += hello.h hello_global.h
SOURCES += hello.cc

DEFINES += HELLO_LIBRARY

headersDataFiles.files = hello.h hello_global.h
headersDataFiles.path = /usr/local/include
INSTALLS += headersDataFiles

target.path = /usr/local/lib
INSTALLS += target

ビルドとインストール

ソースファイルを格納したディレクトリで,端末に,
~/qlibhello qmake6
~/qlibhello make
~/qlibhello sudo make install
とすれば,ビルドとインストールおこなえます.

ライブラリの検索パスは,/etc/ld.so.conf 記述されています.
/usr/local/lib をパスに加える簡単な方法は,/etc/ld.so.conf に /usr/local/lib 行を記述し,
$ sudo ldconfig
を実行することですす.
この作業により,プログラムの実行時にライブラリを利用できるようになります.


動的ライブラリの利用

作成した動的ライブラリを利用するプログラムを作成します.

ソースファイル

2 個のソースファイルを作業用のディレクトリ qexehello に作成しました.

qlibhello
├─ main.cc
└─ qexehello.pro

main.cc


#include <dlfcn.h>
#include <iostream>

int main() {
 void* handle = dlopen("libhello.so", RTLD_LAZY);

 typedef void (*hello_t)();

 hello_t hello = (hello_t) dlsym(handle, "hello");
 if(!hello) {
  std::cout << dlerror() << std::endl;
  exit(1);
 }

 hello();

 dlclose(handle);

 return 0;
}

hello.pro


TEMPLATE = app
TARGET = hello
INCLUDEPATH += .

SOURCES += main.cc

INCLUDEPATH += /usr/local/include
LIBS += -ldl #リンクオプションは -ldl だけでよさそうです

target.path = /usr/local/bin
INSTALLS += target

QT =

ビルドとインストール,実行

ソースファイルを格納したディレクトリで,端末に,
~/qlibhello qmake6
~/qlibhello make
~/qlibhello sudo make install
とすれば,ビルドとインストールおこなえます.

$ hello
とすると,端末に Hello World. と出力されました.