共有オブジェクトの API
dlopen
void* dlopen( char* filename, int flag );
共有オブジェクトを開きます。
【引数】
filename
共有オブジェクトのパス
flag
?
返り値
共有オブジェクトへのハンドル
int dlclose( void* handle );
共有オブジェクトを閉じます。
【引数】
handle
共有オブジェクトへのハンドル
dlsym
void* dlsym( void* handle, char* symbol );
共有オブジェクトに入っている関数のポインタを返します。
【引数】
handle
共有オブジェクトへのハンドル
symbol
関数名
返り値
関数のポインタ
symbol lookup error: *.so: undefined symbol: (symbol)
実行時にダイナミック・リンカーが目的の関数を見つけられないために発生します。
実行ファイルが要求する共有オブジェクトは、次のようにして調べることができます。
readelf -a (exefile) と実行して、下記の (NEEDED) が、要求する共有オブジェクトです。
Dynamic section at offset 0xaf20 contains 22 entries:
Tag Type Name/Vale
0x00000001 (NEEDED) Shared Library: [libproc-3.2.4.so]
0x00000001 (NEEDED) Shared Library: [libncurses.so.5]
0x00000001 (NEEDED) Shared Library: [libc.so.6]
参考
#!/bin/bash -xe
#// -x option echos commands
#// -e option does not continue, if error was raised
#// elf_info (input_folder) (output_folder)
#// elf_info "$HOME/work/X11R7.5" "$HOME/work/X11R7.5_elf_info"
#//*********************************************************************
#// <<< [main] >>>
#//*********************************************************************
function main {
elf_info "${g_Arguments[0]}" "${g_Arguments[1]}"
}
#//*********************************************************************
#// <<< [elf_info] >>>
#//*********************************************************************
function elf_info {
in_folder="$1"; out_folder="$2"
so_step_paths=(`find "$in_folder" -type f -name "*.so*" -print | sed -e "s%$in_folder/%%g"`)
for so_step_path in ${so_step_paths[@]};do
echo ${in_folder}/${so_step_path}
mkdir_for "${out_folder}/${so_step_path}.txt"
readelf -a ${in_folder}/${so_step_path} > ${out_folder}/${so_step_path}.txt
done
echo "Output: $out_folder"
}
#//*********************************************************************
#// <<< [mkdir_for] >>>
#//*********************************************************************
function mkdir_for {
file_path="$1"
folder_path=${file_path%/*} #// parent folder
if [ "$folder_path" == "$file_path" ]; then return "0" ;fi #// if not found "/"
if [ ! -f "$folder_path" ]; then mkdir -p "$folder_path" ;fi
}
g_Arguments=($*)
main
フォルダーの中にある全ての共有オブジェクト (*.so) の情報ファイルを出力します。
内部で readelf を使っています。
readelf -a (exefile)
実行ファイル(elf 形式)の情報ファイルを出力します。
GNU のコンパイラ兼リンカです。 make コマンドから間接的に使われます。
インストールするときは、解凍してから README ファイルを参照してください。
著作権表示は、COPYING ファイルにあります。
コンパイラは、標準的なフォルダに展開するだけでインストールされたことになります。
一般的に、makefile の中に、インストールされたフォルダを記述します。
makefile の中で、環境変数の設定を想定しているものもあります。
標準Cライブラリである 「libc6-dev」 もインストールしてください。
CodeSourcery 社の GCC 4.2.1 をベースにしています。
Linux
→ .tar.bz2
→ .tar.bz2
ターゲット
OS / モニタ
ビルドOS
Linux
Linux
ターゲット
CPU
ARM
ARM
ダウンロード
ベース
→ .exe
→ .exe
Windows
Windows
ARM
Linux
ARM
手順
cd ~/share
tar xvjf arm-2007q3-53-arm-none-eabi-i686-pc-linux-gnu.tar.bz2
arm-2007q3 フォルダができるので、arm-none-eabi に改名して /usr/local/arm/gnu/latest/
に移動します。
を開いて、圧縮ファイルがあるディレクトリに移動して解凍します。
mv arm-2007q3 arm-none-eabi
sudo mkdir -p /usr/local/arm/gnu/latest
sudo mv arm-none-eabi /usr/local/arm/gnu/latest
CROSS_COMPILE = /usr/local/arm/gnu/latest/arm-none-eabi/bin/arm-none-eabi-
新規に Makefile を作るときは、Makefile の中で、次のように定義します。
(すでに Makefile が作ってあるパッケージでは設定不要です)
関連
sudo apt-get install libc6-dev
~/share
もインストールします。
gcc より先にインストールできます。
で共有している Linux のディレクトリに、圧縮ファイルをコピーします。
バージョンの確認方法
gcc -v
gcc -dumpversion
… 詳細なバージョン
… バージョン番号のみ
→ sample1.tar.bz2
make
Makefile に記述された最初の明示ルールの (target) をメイクします
make (target)
(target) をメイクします(暗黙ルールの target も可能)
ソースファイルをコンパイルしてオブジェクトファイルができるような、依存関係があるときに、
タイムスタンプを比較して、必要なコマンドを実行します。
依存関係は、Makefile という名前のファイルに記述します。
エラーが発生したとき
make[2]: *** [buildcheck] エラー 1
上記のメッセージの場合、buildcheck のルールを実行しているときにエラーが発生しています。
関連
参考
参考
make -d V=1 2>&1| tee make.log
環境変数 V=1 を設定して、メイクします。
一般に V=1 とすると、メイクの詳細が表示されます。
は、ログを取るプログラムです。
-d オプションは、メイクルールを詳細に出力します。
don't know how to make "a.obj"
a.exe : a.obj
gcc ...
a.obj : a.c
gcc ...
原因1: a.obj がターゲット(:より左)になっているルール(作り方)が makefile に定義されていない
a.exe : a.obj
gcc ...
a.obj が無いときは、エラー
正しい
don't know how to make "a.obj"
原因2: make によって作られない a.obj ファイルが存在しない
!ERROR invalid value ENV1=$(ENV1)
変数の値が何も無い
定義されていないマクロのシンボルを指定したときの展開した結果は、何もなくなります。
例: $(Unknown)\folder1 → \folder1
マクロのシンボルは、大文字小文字を区別します。
正しいスペルは、近くにある別の makefile を参照してください。
make が実行するコマンドの詳細を表示したいとき
SILENT = @
ifeq ($(V),1)
SILENT =
endif
%.o: %.c
$(SILENT)$(CC) -c $(CFLAGS) -o $@ $<
Makefile
カーネルなどの Makefile は、make によるコマンドラインの出力の一部が表示されません。
これは、コマンド行の先頭に @ を付けたことよるものですが、次のように @ を付けないで
すべてを表示することができる Makefile もあります。
この場合、次のように make を実行すると、詳細が表示されます。
make V=1
多くのソースファイルは、暗黙ルールによってコマンドが実行されています。
nmake の場合:
make の場合:
関連
関連
実行されるメイク・ルールは、メイク・ルール・ツリーの中にあるから、つまり、メイク・
ルールの : の右(子ノード)にあるからです。
ルールの : の右に指定している変数の値と、その定義を確認してください。
参考
メイク・ルール・ツリーの中の親ノードを探す
#!/bin/bash -e
#// -x option echos commands
#// -e option does not continue, if error was raised
#// make and make profile
makefile_path="Makefile"
while getopts "C:f:z(no-print-directory)" OPT
do
case $OPT in
"f" ) makefile_path="$OPTARG";;
esac
done
echo ""
echo "+cd $PWD"
echo "+make -p > ${makefile_path}.profile.txt"
echo "+make $@"
echo ""
make -p -n "$@" > ${makefile_path}.profile.txt 2>&1 || exit_code="$?"
make "$@"
chmod 777 ./make_profile.sh
make MAKE=$PWD/make_profile.sh
cd (make を実行するフォルダー)
cp /dev/stdin ./make_profile.sh
もし、「不正なオプションです」というメッセージが表示されても無視できます。
表示させたくないときは、シェル・スクリプトの getoptsのパラメーターに追加してください。
make プロセスから、子プロセスとして make を呼び出す Makefile を使っているときに、
どの Makefile が使われているかを表示して、動きを追う方法を説明します。
また、make の -p オプションを使った、Makefile の展開結果も作成します。
シェルから次のように入力します。
内容を入力するモードになるので、スクリプトの内容をコピー&ペーストします。
最終行の改行をしてから、[Ctrl]+[C] を押すと、ファイルが作成されます。
シェルから次のように入力すると、動きを表示しながら、make を実行します。
ただし、Makefile に書かれた make の呼び出しが、MAKE という変数になっている必要があります。
all:
$(MAKE)
+cd /home/user1/work/Source
+make -p > Makefile.profile.txt
+make
実行すると、make を起動する直前に、下記のようなメッセージが追加されます。
.profile.txt ファイルが、Makefile の詳細情報です。 参考
main.o: main.c
# 暗黙ルールの探索が行われました.
# 自動変数
# @ := main.o
# 自動変数
# % :=
# 自動変数
# * := main
# 実行するコマンド (`/home/user1/work/Source/Makefile', 307 行目から):
$(CC) -c main.c
メイクルール
メイクルールは、すべて出力され、コマンドが実行されるかどうかを記録します。
暗黙ルールや、実行するコマンドの場所も記録します。
変数
Makefile に記述された変数だけでなく、環境変数や、暗黙的に定義される変数も記録します。
# makefile 変数 (`makefile.linux', 39 行目から)
SOURCES = main.c sub.c
SOURCES =
環境変数 SOURCES の内容を知りたいときは、次のキーワードで検索すると見つかるでしょ
う。 ただし、複数存在することもあります。
次のキーワードで検索すると見つかるでしょう。 ただし、複数存在することもあります。
main.o:
最終ターゲット(all など)をルートしたツリーを、ルートからたどっていくとよいでしょう。
"暗黙ルールの探索は行われませんでした." と記録されて、コマンドが実行されないときは、
最終ターゲット(all など)をルートしたツリーの中に無いか、-c オプションが無い可能性が
あります。-I オプションにパスが指定されていないために、-c を -I オプションのパラメーター
になってしまった可能性もあります。
#comment
a.exe : a1.o a2.o
$(CC) $(LFLAGS) a1.o a2.o
(target) : (source)
(command)
コマンドの行頭は空白ではなくタブである必要があります。
サンプル:
暗黙ルール
(target) が無いときか、古いときに、(command) を実行します。
ただし、(source) に対するルールのコマンドを実行した後で実行します。
(command) には、
を記述することができます。
%.o
.c.o
make を実行するときに参照する依存関係を表したファイルです。
implicit rule
必要な (target) に対応するルールが無い場合、(target) に対応するソースファイルの
存在によって、暗黙ルールを適用します。 たとえば、(target) = target.o の場合、
target.c があれば %.o : %.c の暗黙ルールを適用します。
→ nmake の makefile
や
関連
参考
(target) や (source) に記述するシンボル名に、スラッシュやピリオドも使えます。
実行する順番は、(source) にあるパスの左から、関数呼び出しのように、
たどっていき、最後に (command) を実行します。 ただし、タイムスタンプなどに
よって実行しないこともあります。
PROG = sample.exe
OBJS = sample.o
DEBUG = 1
CC = ${CROSS_COMPILE}gcc
CFLAGS =
LDFLAGS =
LIBS =
# debug
ifeq ($(DEBUG),0)
CFLAGS += -DNDEBUG
else
CFLAGS += -g
LDFLAGS += -g
endif
# rules
all: $(PROG)
$(PROG): $(OBJS) Makefile
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
#using implicit rule %.o : %.c
clean :
rm -f *.o
rm -f $(PROG)
sample.c をコンパイル&リンクして sample.exe ができる Makefile です。
を使っています。
コンパイルするルールは、.c に対応する
ライブラリを使うときは、
この部分を下にコピーして、
= を += に変えて、
ライブラリに必要な設定を
してください
… プログラムファイル名
… ソースファイルの .c を .o に変えたもの
コピーする Makefile のサンプル
copy_files : \
dst \
dst\file1.txt \
dst\file2.txt \
dst :
mkdir dst
dst\file1.txt : src\file1.txt
copy $? $@
dst\file2.txt : src\file2.txt
copy $? $@
存在しないときだけコピーする
上書きする
copy_files : \
if not exist dst mkdir dst
copy src\file1.txt dst\file1.txt
copy src\file2.txt dst\file2.txt
:
@
:=
?=
+=
$( )
#
$( : )
make clean
多くの Makefile は、
と入力すると、中間ファイルなどを削除します。
もし、メイクする前の状態に戻らなかったら、次の方法で、戻すことができます。
make して、make clean した後、
diff -q -r __old_folder__ __new_folder__ > clean_tmp.sh
#!/bin/bash -e
#// -x option echos commands
#// -e option does not continue, if error was raised
clean_target=(\
\
__file_or_folders__ \
\
)
for (( i = 0; i < ${#clean_target[@]}; i ++ ));do
target=${clean_target[$i]}
if [ -d "$target" ]; then
echo "d $target"
rm -r "$target"
elif [ -e "$target" ]; then
echo "f $target"
rm "$target"
fi
done
echo "cleaned"
__file_or_folders__ の部分を置き換えて、実行してください。
で、clean しきれていないファイルやフォルダーを調べ、下記のシェル・スクリプトの
clean.sh
関連
または
make allclean