C/C++開発ツール

コンパイラ

Visual C++

Microsoftによるコンパイラ

GCC/MinGW + MSYS

GCCGNUによるコンパイラMinGWと言うWindows版もある。
MSYSはWindows上で動作するBashUNIXユーティリティ。MinGWを補う目的で作られた。

Cygwin

MinGWを使うのも良いが、WindowsUNIX環境を構築できるCygwinを使うという手もある。この場合、ランタイムライブラリのCygwin1.dllを開発したプログラムに同梱する必要がある。

LLVM

オープンソースの新しいコンパイラAppleなどによって開発されており、GCCをリプレースする存在になるのではないかと注目されている。流行りのプログラミング言語であるRustでもLLVMをバックエンドにして開発されている。

Clang

LLVMで動作するC言語コンパイラ

LLVMとctagsで開発環境を整える

Windowsを使うのであれば、LLVMとctagsで開発環境を整えるのがおすすめ。

Intel C++ Compiler

Intelによるコンパイラ

C++Builder/VCL/CLX

ボーランドによるコンパイラ統合開発環境
VCLとCLXは、DelphiC++Builderで使われるライブラリ。

GCC

GNUコンパイラコレクション

GNUによるコンパイラ

gccの例

例:

gcc -o test test.c

test.cをコンパイル・リンクして、実行ファイルtestを作成する。

gccのオプション

オプション 説明
-c コンパイルのみを行う。(オブジェクトファイルを作成する。)
-o test.o コンパイルしてその結果をtest.oとする。
-O0 最適化無効。
-O1 特定の最適化を無効。
-O2 (または -O) 標準の最適化を行う。デフォルト設定。
-O3 さらなる強力な最適化を行う。
-g デバッグ情報を付加する。
-g3 デバッグ情報を付加する。gdbでマクロも使えるようになる。
-Wall 警告オプション全てを有効にする。
-lm リンクを行う。mはライブラリの名前(libm.a)を意味する。
-Ldir ライブラリを探すディレクトリにdirを追加する。
-Idir ヘッダファイルを探すディレクトリにdirを追加する。

g++の例

C++の場合:

g++ -o test2 test2.cpp

gfortranの例

GCCではFortranコンパイルできる:

gfortran hello.f90

フロントエンドとバックエンド

GCCは、「フロントエンド - 最適化部(中間コード) - バックエンド」という設計をしている。

こうすることによって、フロントエンドとバックエンドの部分を開発するだけで、さまざまなプログラミング言語とさまざまなCPUプロセッサ向けの機械語に対応できる。
フロントエンドを作るだけで新しいプログラミング言語(自作のプログラミング言語の場合も含む)にも対応でき、バックエンドを作るだけで新しいCPUプロセッサに対応できる。
そのため、新しいプログラミング言語を作りたい場合は、GCCのフロントエンドだけを開発すれば良い。
フロントエンドは構文解析のbisonや字句解析のflexというツールが使われている。

ロスコンパイラ環境の導入

ロスコンパイルとは、組み込みシステムなどで、x86のパソコンから別のCPUアーキテクチャ向けのバイナリ実行ファイルを出力すること。
PowerPC向けのELFバイナリを吐く場合は、ビルド用の「powerpc-elf」ディレクトリを切って、binutilsgccをソースから「--target=powerpc-elf」のようなオプションをつけてビルドする。そして、

$ powerpc-elf-gcc -nostdlib -g -O hello.c

のようにビルドする。targetを変えるだけで別のアーキテクチャ向けにビルドできる。

lex/yacc

コンパイラを作る時に使われる技術。
lexは、字句解析(ソースプログラムを、「字句(トークン)」の並びに分割する処理)を行うレキシカルアナライザを自動作成する。
yaccは、構文解析トークンの並びから、解析木を構築する処理)を行うパーサを自動作成する。

Binutils (as, ldなど)

さまざまなオブジェクトフォーマットを含むオブジェクトファイルを扱うためのプログラミングツール。
主なコマンドとして、as(アセンブラ)やld(リンカ)がある。gcc/make/gdbで使う補助のためにも必要。

Make/Autotools

Makefileの書き方

Makefileの基本

ターゲット名: 依存ファイル名1 依存ファイル名2 依存ファイル名3
              コマンド行1
              コマンド行2
              コマンド行3

実行は、

$ make ターゲット名

Makefileの例

GNU makeは、プログラムのソースコードコンパイルする時、更新されたファイルだけをコンパイルするなど、色んなことが出来ます。
以下はMakefileの例:

program : main.o iodat.o dorun.o lo.o /usr/fred/lib/crtn.a
    cc -o program main.o iodat.o dorun.o lo.o /usr/fred/lib/crtn.a
main.o : main.c
    cc -c main.c
iodat.o : iodat.c
    cc -c iodat.c
dorun.o : dorun.c
    cc -c dorun.c
lo.o : lo.s
    as -o lo.o lo.s

プログラムの実行例:

$ make program

コロンの左にターゲット、右にコンポーネントが位置し、タブで字下げされたコマンド行には、コンポーネントからターゲットを作り出す方法が記述されている。
ここでの一行目には、programがmain.o, iodat.o, dorun.o, lo.o, /usr/fred/lib/crtn.aに依存していると言うことが、二行目にはこれらのファイルからprogramを作り出すためのコンパイルコマンドが記述されている。
依存関係を辿っていって、programが存在した場合、programより新しいものが依存関係の中に存在しないかをチェックする。全ての.oファイルに対して、そのコンポーネントとの関係をチェックする。
更新されたファイルがmain.cだけだった場合、次のコマンドが実行される。

cc -c main.c
cc -o program main.o iodat.o dorun.o lo.o /usr/fred/lib/crtn.a

(「make 改訂版 - オライリー・ジャパン」を参考に執筆・引用しました。)

Autoconfで移植性を高める

Autoconfは移植性を高めるためのツールで、プログラムをビルドするために使うconfigureというシェルスクリプトを自動作成する。

Automakeで楽にMakefileを作る

Autoconfには補助ツールとしてAutomakeとlibtoolがある。Automakeを使うと、簡単な記述でMakefileを自動作成してくれる。
Automakeはさまざまな変数の使い方などを理解するのが難しいが、慣れるとMakefileを書く必要がない。XOrg Serverのソースツリーなどを見ていると、各ディレクトリにそのディレクトリの中にあるソースファイルの一覧のような内容を記したMakefile.amがある。たくさんの必要なファイルとたくさんの必要な入力・実行作業があって最初は戸惑うかもしれない。昔は、これでも楽だった。

ビルドシステム

Apache Ant

Javaによるビルドシステム。XMLを用いてビルドを行う。
Makeに代わる新しいビルドツール。「GNU makeのJava版」とも。
ソースコードの依存関係をXMLで記述する。
Javaオープンソースで作られている。
Java統合開発環境Eclipseでサポートされている。

Apache Maven

Apache MavenJavaプロジェクトの管理ツール。Apache Antに代わるものとして作られた。プラグイン拡張によりさまざまな使い方ができる。

pkg-config

GTK+アプリケーションはpkg-configを用いて独自のコマンドでコンパイルする。
pkg-configによるコンパイルは以下のようになる。

$ gcc hello.c `pkg-config --cflags --libs gtk+-3.0`

主にC言語によるGTK+プログラムでは、上のようにコンパイルを実行しなければコンパイルが通らない。

CMake

KDEアプリケーションはCMakeをビルドシステムに使う。

Meson+Ninja

最近は、Meson+Ninjaのような新しいビルドシステムもあり、X.orgやGNOME3でもMesonを使っているようである。

開発ツール

Visual C++(Visual Studio)

MicrosoftによるC/C++の開発環境。

Eclipse CDT

オープンソースC/C++開発環境。
「Visual C++は高すぎる。だからといってWindows開発者への道を諦めたくない。どうしたものか…」といった人には、このEclipse CDTを使うのが良いかもしれません。
僕も、WindowsC言語のロボットを開発した時は、EclipseにCDT/MinGWを入れて使いました。
ただ、僕は良く分かっていないので、もしかしたらWindows関係のライブラリやAPIが足りないかもしれません。思い切ってLinuxでのC/C++開発者になってみてはいかかでしょうか。本当のGCCを使うことができます。GCCが嫌ならばLLVMの開発者になれば、きっと自分で独自の言語をRustのように作ることもきっとできます。
最近分かったこととして、Eclipse CDT + MinGWでもWindows APIを使ったWindowsアプリケーションを開発することはできるようです。

Emacs & Vim

C/C++の開発に利用出来るオープンソーステキストエディタLinuxで開発するのであれば、Emacs/Vimを使いましょう。

Atom

今流行りの新しいテキストエディタ

Atomは、GitHubによる今流行りの新しいテキストエディタ
GitHubによるElectronと呼ばれる、Web技術(HTML+CSS+JavaScript)でデスクトップアプリケーションを作るクロスプラットフォームな技術によって作られた。
WindowsLinuxMacで動く。また、パッケージと呼ばれるEmacsでいうELispのようなものを導入することで、自由自在に拡張できる。たとえば、自動補完のような機能を使うこともできる。メニューや設定画面を日本語にするのにもパッケージを使う。
今の時代、viやEmacsのような前時代的なテキストエディタをいつまでも盲信し続けるのではなく、Atomを使ってEmacsのようなスタイルをもっと新しく使うのが流行っている。
Atomは上級エンジニアから初心者のプログラミング学習者まで幅広くおすすめできるエディタで、LinuxでもEmacs/viに無理に慣れようとするよりも、最初からAtomを使った方が良いと僕は思う。

MacLinuxでは新しい標準的存在

実際のところ、AtomMacLinuxでは新しい標準的な存在です。
僕も、作業所のMacではAtomを使います。それは、MacWindowsLinuxも、標準のテキストエディタがお粗末で、「付属のエディタが全く使えない」からです。
たとえば、Macのテキストエディットは、ダブルクオーテーションを「"text"」のままではなく「“text”」に強制的に変換します。これではプログラム開発に使えるはずがありません。
Windowsのメモ帳も、何の機能もありませんが、メモ帳はまだマシです。GNOMEのgeditはありえないです。日本語の文字とASCII文字が別の幅で表示されるなど、日本人ユーザーのことを全く考慮できていません。Pythonで開発しようにも、geditではできません。また、KDEのエディタでは日本語入力すらできないことがあります。(ただし僕はAtomLinuxに導入したことがないため、何らかの問題があるかどうかは分からない。僕はLinuxならviを使う。)
そう、Atomを使わざるを得ません。僕はWindowsではサクラエディタを使っていますが、Atomを使うとMacLinuxと共通の環境を使うこともできて、便利です。
後日注記:Macのスマート引用符は設定でオフにできます。また、僕が使う範囲で言えば、LinuxAtomでは日本語入力ができない場合がありました。よって僕はLinuxではVimを使い、MacではAtomを使う、という感じです。LinuxでVS-Codeがどれくらい動くかそのうち試してみたいと思っています。

Windows API

MFC

MicrosoftによるC++向けライブラリ。

Managed C++C++/CLI

.NET向けのC++拡張。

UNIX & X11 API

システムコール・ライブラリ関数(libc)

カーネルとC標準ライブラリ(libc)のAPI

libcの重要性

libcは、その名の通りCの標準ライブラリの実装。
カーネルコンパイラだけでは、Cのプログラムは動かない。カーネルシステムコールコンパイラの言語処理系と合わせて、「C言語の関数を実行できる」ようなライブラリが必要である。
libcはカーネルと並んでとても重要で、さまざまなCのライブラリ関数を使うためにはカーネルとlibcがタッグを組む必要がある。その上でgccなどの言語処理系が必要。Linuxではこれらは全てフリーソフトウェアで入手できる。GNUプロジェクトがglibcを開発し、Linuxカーネルの開発者と緊密に協力した結果である。
Linuxで利用できるlibcには、GNUによるglibcのほかさまざまな軽量版libcが存在する。また、FreeBSDNetBSDなどもそれぞれのOSカーネルと合わせてlibcを開発しており、組み込みシステムなどではglibcではなくNetBSDのlibcを使うなどといった事例もある。

C++については

また、C++で開発を行うためにも、同様にC++の標準ライブラリが必要である。LinuxではGCCプロジェクトのlibstdc++などが利用できる。

GlibcLinux libc

GNUによるlibc(標準Cライブラリ)の実装。かつてはLinuxの開発者が"Linux libc"をフォークさせたこともあったが、glibc 2.0でたくさんの機能追加と移植性の向上が行なわれ、Linuxの開発者はglibcに戻った。
フル機能のGlibcは多機能だが、サイズが大きく、サイズを小型化するためにmuslのようなCライブラリの実装も使われることがある。また、ライセンスにコピーレフトのものを使いたくない場合や移植性などを考えて、*BSDのlibc実装が使われることもあり、AndroidではNetBSDのlibcが使われている。

Musl

Muslは軽量なglibcの代替。Void Linuxなどで標準とは違う軽量なCライブラリとして利用出来る。
Linux向けのCライブラリの実装は他にもあるが、機能を増やせば巨大になり、機能を減らせば軽量になるという関係にある。Muslはその中間に位置する。

uClibc/Newlib/dietlibc

uClibcは、メモリ管理ユニットを必要としないマイクロコントローラに対応したμClinux向けに開発された小型のCライブラリ。組み込みLinux向けに用いる。
glibcと比べてずっと小さく、機能単位で有効・無効が可能。MMUのないシステムにも対応している。
Newlib/dietlibcも、小型のCライブラリ。組み込み向けに用いる。

標準コマンドのソースコードcoreutils

coreutilsのgitで基本的なコマンドのコードを読むことが出来ます。

Xlib

X11の低レベルなグラフィックスAPI

GTK

GTKC言語によるX11ウィジェットツールキット。

GNOME

GNOMEAPI

Qt

C++によるX11ウィジェットツールキット。

KDE

KDEAPI

デバッガ

gdb

GNUによるデバッガ。
基本的に、gccに-gオプションをつけてバイナリをコンパイルし、

gdb app

として、以下を実行する:

コマンド 説明
b 関数名 実行前に関数にブレークポイントを設定。
b ファイル名:行数 実行前にファイルの中の行にブレークポイントを設定。
i b ブレークポイントの一覧を表示。
d no 番号に対応するブレークポイントを削除。
run 実行。
attach pid 実行中のプログラムをデバッグ
p 変数名 変数の値を表示。おそらく最もよく使うコマンド。
構造体のメンバはa.bで要素を、ポインタは*fpで中身を見れる。
set 書き込み先=式 変数の値を書き換える。
n ステップ実行(関数には入らない)。
s 関数の中までステップ実行。
c 次のブレークポイントまでを実行。
f 現在の関数を抜けるまでを実行。
u 現在のループを抜けるまでを実行。
where 現在どこを実行中かを関数レベルで表示。
bt バックトレース(現在の関数が呼び出されるまでの経路を表示)。
l ソースコードを表示。
何も打たずにリターン 直前のコマンドを再度実行する。

「何がどこで実行中か」を見ながら作る

ある意味、プログラムの基本とは、「何がどこで実行中か」ということがポイントだと思います。
いつ、そのプログラムがどこで何を実行しているのか、それが分かると、たとえばループの条件判断に関数を入れ込むなど、といった荒業でプログラムを書くことができます。

バグのないプログラム

僕は、パソコンのプログラムを開発するという仕事は、たくさんの部品を組み合わせて作る自動車などとよく似ていると思います。
自動車の製造過程では、それぞれの部品が上手く働くかを入念にテストし、きちんと動く部品だけを組み合わせて全体の自動車を組み立てます。
プログラムもこれと同じで、入念にそれぞれのモジュールやコンポーネントをテストして、バグのないプログラムを作ることができます。
ですが、プログラムという特性上、きちんとプログラムが動くかどうかをテストするのは難しいものです。たとえば、入出力だけをテストしても、内部のデータ変数全てが適切に働いているかどうかをチェックすることは、デバッガを使わないとできず、またデバッガを使っても難しいです。
それから、プログラムはアナログな部品と違って、とても多くの実行パターンを考えなければなりません。画像処理であればあらゆるグラフィック処理の全ての場合を考えなければなりませんし、コンパイラインタープリタであれば、あらゆる言語的記述の全ての場合を考えなければなりません。
ここで、一番簡単にできるのは、もし金儲けを考えない場合であれば、オープンソースにして、みんなでプログラムにバグがないかをチェックする、という方法です。
よって、僕はオープンソースは、自動車などの製造で巧みな技術を持っている日本の製造業に親和性が高いと思います。同時に、日本がきちんとしたテスト用のフレームワークを作れば、オープンソースにしなくても、同程度の高品質のプログラム開発を行うことは可能ではないかと思います。
デバッガを使うことで、ある程度のプログラムのコード分析を行うことができます。値をその時のブレークポイントでチェックしたり、変数にさまざまな値を代入してテストすることができます。printfチェックなども併用しながら、プログラムにバグが混入しないように注意して開発しましょう。
最近は、Windowsなどの開発も高度になってきており、.NETなどの新技術も使いながら、たくさんの資金を投入して安定したOSをMSも作っています。以前のように「Windowsは不安定だがUNIXは安定している」とは必ずしも言えなくなっています。特に最近はLinuxでもGUIの巨大デスクトップ環境を開発しており、Windowsと同じぐらいバグがあります。特にオープンソースでは、きちんとテストされているかどうかは不透明で、保証もなく、また一部ではアマチュアプログラマがコードを書いていたりして、必ずしもオープンソースは高品質ではなくなっています。
後日注記:実際には、オープンソースにするだけでバグがなくなるということはなく、プログラマによる設計と実装が重要になる。たとえば、コアの関数を正しく書き、どの処理でもその関数を使うようにすれば、バグの入る余地を減らすことができる。また、たくさんの処理が増えすぎた時は、全てのコードを書き直す必要もある。これは仕事でプログラミングを書く時にも言えて、バグが解決できない時はもう一度全て書き直すしかない。これがそのまま「デスマーチ」へと繋がるのである。

持論:コンパイラはフリーでなければならない

僕の持論として、「コンパイラだけはフリーでなければならない」というのがあります。
それは、「プログラミングは、万人に手段が平等に与えられるものでなければ、万人がコンピュータを使ってプログラミングすることができない」からです。
Windowsフリーソフトには、Visual C++で作られたソフトウェアが多いですが、この場合、ソースコードコンパイルしたり、自分で作ったり開発に参加するためには、Visual C++を買わなければなりません。
たとえ、ソフト自体がフリーであっても、それを作るための手段はフリーではないのです。
GNUというプロジェクトが、コンパイラなどの開発ツールから始まり、GNU OSが実用化される以前から、「フリーなコンパイラ」として有名だったのは、その理由があると思います。みんな、開発ツールがフリーでほしかったのです。だから、GNUGNU OSが完成する前から、UNIXで使える開発ツールとして有名になったのでしょう。そして、さまざまな人間に改良され、Linuxカーネルの開発者がLinuxの上でのコンパイラや標準のツールなどとして使うに至ったのでしょう。
コンパイラがフリー(無料)であることは、教育においても良い効果を発揮します。誰もが、コストを支払わずにプログラミングの勉強や入門ができます。また、自由という側面で言えば、ソースコードが公開されているため、ただWindows APIを使うだけではなく、自分でコマンドやライブラリのソースコードを見ることができます。これはプログラミングの学習環境として、とても優れています。Pythonなどもオープンソースですが、コンパイルした実行ファイルを簡単に再配布できる、という点で言えば、コンパイル言語の優位性も依然としてあるでしょう。ですが、Linuxをインストールせず、Windowsのままで実行ファイルが作れる、Windows APIやVisual C++のライブラリを完備した互換コンパイラとライブラリがあれば良いのですが、そこまですると、逆にMicrosoftの開発意欲を損ねてしまうでしょう。
本当は、コンパイラが有料であることは良い側面もあります。コンパイラは、プログラミング界でもっとも作るのが難しいソフトウェアのひとつです。オープンソースでは作れない領域でも、Microsoftなら作れるでしょう。ですが、PHPRubyを見るように、言語処理系の流行はオープンソースの機運に乗っているように思います。Rustなどが最たる例でしょう。
後日注記:MicrosoftWindowsに標準でVisual Studioを含めるようにすれば良いと思います。短期的な利益は少なくなるかもしれませんが、Windowsアプリケーションを開発する人が増えて、Windowsエコ・システムは拡大し、Windowsアプリケーションは豊かになるでしょう。