Hello Wor.log

IT系大学生4人による備忘録のようなもの

c! c++!! make!!!

お久しぶりです。 CPPXのXです。

cからc++を呼ぶ処理と、makeの書き方をまとめておきます。

ファイル構成

$ls
main.c  makefile  sub.c  sub.h  subcpp.cpp  subcpp.h

こんな感じでやっていきます。

中身はお好みでどうぞ。 下で書き換えていきます。

make (cの方)

makefileの中身を以下のように書きます。

FILES = main.o sub.o

build: $(FILES)
  cc $(FILES)
  ./a.out

.c.o:
  cc -c $<

sub.o: sub.h

すると、make と打つとコンパイルされて実行ファイルが吐き出されます。

.c.o:
  cc -c $<

の部分ですが、.cのファイルを探して、.oに変換しますよ という意味らしいです。

ファイル名が $< に格納されます。 なので、echo $< とかやるとファイル名が出てきます。

sub.o: sub.h

ですが、処理を追加すると.c.oの処理よりも優先されてしまうので、依存関係を書くだけに留めておきましょう。

sub.cの変更も検知されなくなります。

c++との連携

cからc++を呼び出していきます。

subcpp.cpp, subcpp.hを以下のようにします。

  • subcpp.cpp
#include <iostream>
extern "C" void print(int value) {
  std::cout << value << std::endl;
}
  • subcpp.h
#define INCLUDE_SUBCPP
#ifndef INCLUDE_SUBCPP

#ifndef __cplusplus
extern "C"
#endif
int print(int);

#endif

extern "C" をつけるとcから見えるようになるみたいです。

戻り値と引数はcにあるものにしないとエラーがでます。

#ifndef __cplusplus

は、cの時は未定義になるので、ただの

int print(int);

として処理されます。

コンパイルしていきましょう。 次に進みます。

make(c++の方)

c++を織り交ぜてコンパイルしていきます。

makefileを以下のように書き換えます。

FILES = main.o sub.o subcpp.o

build: $(FILES)
  cc $(FILES) -lc++
  ./a.out

.c.o:
  cc -c $<

.cpp.o:
  cc -c $<

sub.o: sub.h
subcpp.o: subcpp.h
  1. FILESにsubcpp.oを追加しました
  2. ccのコンパイルオプションに-lc++を追加しました
  3. .cpp.o: を追加しました
  4. subcpp.o: subcpp.hを追加しました

それぞれ見ていきます。

(1) subcppと連携したいため、リンクするファイルを追加しました。

(2) c++とリンクする際には、-lc++のオプションをつけないと

Undefined symbols for architecture x86_64

のようなエラーが出ます。

オプションをつけずに、clang++でコンパイルしても大丈夫です。

(3) .cppを探して.oに変換してくれます。.c.oの時とだいたい同じです。

(4) こっちも処理は書かずに依存関係を書くだけに留めます。

おわり

ここまで書いて、main.cを以下のように書き換えて make と打つと、10 と表示されると思います。

#include "subcpp.h"
int main(){
  print(10);
}

makeを初めてちゃんと触ったので、もうちょっとまともに扱えるようになりたい・・・。

makeは怖いものだと思ってたので、もう少し深まったらまた記事書きます。