Linux C/C++ 自作ライブラリ作成環境の構築

270, 2019-12-27

目次

環境

  • ディストロ: Debian GNU/Linux
  • シェル: bash
  • コンパイラ: Clang 3.5

最初に

個人的な備忘録です。試される方にはバックアップ(特に.bashrc)を推奨します。この環境はいわゆる「ぼくのかんがえたさいきょうの〜」に属します。

下準備

ホーム~/にsrc, include, libディレクトリをそれぞれ作成。

$ cd
$ mkdir src include lib
$ ls
src include lib

「hello」ライブラリの作成

src/にhelloディレクトリを作成。

$ cd src
$ mkdir hello
$ ls
hello

hello/にhello.c, hello.hを作成。

$ cd hello
$ ls
hello.c hello.h
// hello.h
#pragma once

#include <stdio.h>

void hello(char const* s);
// hello.c
#include "hello.h"

void hello(char const* s) {
    printf("hello %s\n", s);
}


共有ライブラリとしてビルド。

$ clang -shared ./hello.c -o ./libhello.so
$ ls
hello.c hello.h libhello.so

「hello」ライブラリが完成。これを使いたい。

シンボリックリンクを貼る

~/以下のinclude, libディレクトリにシンボリックリンクを貼る。includeにhelloディレクトリへのリンク。

$ cd ~/include
$ ln -s ~/src/hello/ .
$ ls
hello
$ file hello
hello: symbolic link to `/home/user-name/src/hello/'

libにhello/libhello.soへのリンク。

$ cd ~/lib
$ ln -s ~/src/hello/libhello.so .
$ ls
libhello.so
$ file libhello.so 
libhello.so: symbolic link to `/home/user-name/src/hello/libhello.so'

fileでbrokenとか出た場合はlnに失敗してると思われ。リンク先ディレクトリにcdしてからlnすればおk。

環境変数の設定

参考:RとLinuxと... - C_INCLUDE_PATH

適当なファイルを作って「hello」ライブラリを試す。

$ cd ~/src
// test.c
#include <hello/hello.h>

int main(void) {
    hello("world");
    return 0;
}
$ clang test.c -lhello
test.c:1:10: error: 'hello/hello.h' file not found with <angled> include; use
      "quotes" instead
#include <hello/hello.h>
         ^~~~~~~~~~~~~~~
         "hello/hello.h"
1 error generated.

エラーが出た。コンパイラが「hello」ライブラリの置き場を知らない。
バックアップを取ってから.bashrcの末尾にパスを書く。パスは~/以下のinclude, libディレクトリを指定。

$ cd
$ cp .bashrc .bashrc-bak
$ vi .bashrc
...

# GNU* 環境変数: C/C++ コンパイル用のインクルード・ディレクトリのパスを指定します。
export CPATH=$CPATH:$HOME/include

# GNU* 環境変数: C コンパイル用のインクルード・ディレクトリのパスを指定します。
# ここではコメントアウト
# export C_INCLUDE_PATH=$C_INCLUDE_PATH:

# GNU* 環境変数: C++ コンパイル用のインクルード・ディレクトリのパスを指定します。
# ここではコメントアウト
# export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:

# GNU* 環境変数: LIBRARY_PATH の値は、PATH のようにコロンで区切られたディレクトリのリストです。
export LIBRARY_PATH=$LIBRARY_PATH:$HOME/lib

# 共用オブジェクトの場所を指定します。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/lib

sourceを更新する。これで設定したパスが、現在のttyでのみ有効になる(要確認)。ちなみにFreeBSDでは'source'コマンドはなく、ビルトインされた'.'を使うらしい。

$ source ~/.bashrc
$ echo $CPATH
:/home/user-name/include
$ echo $LIBRARY_PATH
:/home/user-name/lib
$ echo $LD_LIBRARY_PATH
:/home/user-name/lib

これで環境変数の設定が完了。


「hello」ライブラリを使う

$ cd ~/src
// test.c
#include <hello/hello.h>

int main(void) {
    hello("world");
    return 0;
}
$ clang test.c -lhello
$ ./a.out 
hello world

バイナリにリンクされたライブラリを確認する

$ ldd ./a.out
    ... 
    libhello.so => /home/user-name/lib/libhello.so (0x12341234)
    ...

環境変数に叩きのめされたエラー集

その1。環境変数を設定しない場合。

$ clang test.c -lhello
test.c:1:10: error: 'hello/hello.h' file not found with <angled> include; use
      "quotes" instead
#include <hello/hello.h>
         ^~~~~~~~~~~~~~~
         "hello/hello.h"
1 error generated.

その2。CPATHのみ設定した場合。

$ clang test.c -lhello
/usr/bin/ld: cannot find -lhello
clang: error: linker command failed with exit code 1 (use -v to see invocation)

その3。CPATHとLIBRARY_PATHのみを設定した場合。コンパイル後、実行しようとしてエラー。

$ clang test.c -lhello
$ ./a.out 
./a.out: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory

その4。CPATH, LIBRARY_PATH, LD_LIBRARY_PATHを設定した場合。

$ clang test.c -lhello
$ ./a.out 
hello world

思ったこと

ここを見ると、このシンボリックリンクの貼り方はよろしくないのかも。つまりバージョン管理ができないというか。まあいいか。

追記:環境変数をどこに書くかについて

この記事を公開してから以下の記事を読みました。

環境変数は.bash_profileに書くのが適当らしく、イッケネーと思い試してみましたが、上手くいきませんでした。端末が.bashrcは読み込んでくれますが.bash_profileを読み込んでくれません。私のデスクトップ環境はGNOME3 Classicですが、ググってみると使っているgnome-terminalの設定に問題があったようです。

Gnome3 Terminal does not execute my .bash_profile

gnome-terminalのメニュー「編集」→「プロファイルの設定」→「タイトルとコマンド」の「ログインシェルとしてコマンドを実行する」にチェックを入れると、.bash_profileを読み込んでくれます。デフォルトでは未チェックでした。
この記事ではデフォルトのgnome-terminalの設定でも有効になるように.bashrcを編集していますが、気になる方は適度.bash_profileに置き換えてみてください。

さらに追記:環境変数をどこに書くかについて

現在は特にこだわりもせずにすべて .bashrc に書いてます。これといった問題はないようです。

投稿者名です。64字以内で入力してください。

必要な場合はEメールアドレスを入力してください(全体に公開されます)。

投稿する内容です。

スポンサーリンク

スポンサーリンク

スポンサーリンク

スポンサーリンク