| 1 |
#!/usr/bin/ruby |
| 2 |
# Makefile から Makefile.am を生成するスクリプト |
| 3 |
# Satofumi KAMIMURA |
| 4 |
# $Id$ |
| 5 |
# 基本的に、Makefile.am 内の <program>_SOURCES に対する追加のみを行う |
| 6 |
# |
| 7 |
# \todo symlink が既に存在してもエラーにならないようにする |
| 8 |
|
| 9 |
require 'fileutils.rb' |
| 10 |
|
| 11 |
# Makefile.am 中の _SOURCES の項目を管理する |
| 12 |
$sources_list = [] |
| 13 |
|
| 14 |
# 指定ファイルをインクルードパスから探しだし、cpp 共々、追加する |
| 15 |
def searchAndRegister(add_file, include_pathes) |
| 16 |
|
| 17 |
#p include_pathes |
| 18 |
|
| 19 |
# 指定ファイルが include_pathes に存在するか、を探す |
| 20 |
file_rpath = nil |
| 21 |
include_pathes.each { |rpath| |
| 22 |
# ファイルの存在確認 |
| 23 |
if File.exist?(rpath + add_file) |
| 24 |
file_rpath = rpath |
| 25 |
break |
| 26 |
end |
| 27 |
} |
| 28 |
if file_rpath == nil |
| 29 |
return false |
| 30 |
end |
| 31 |
add_file_path = file_rpath + add_file |
| 32 |
add_files = [ add_file_path ] |
| 33 |
|
| 34 |
# 同じ場所に cpp が存在するか、確認する |
| 35 |
add_also_cpp = nil |
| 36 |
if File.extname(add_file) != '.cpp' |
| 37 |
check_file = file_rpath + File.basename(add_file, '.*') + '.cpp' |
| 38 |
if File.exist?(check_file) |
| 39 |
add_files.push(check_file) |
| 40 |
end |
| 41 |
end |
| 42 |
|
| 43 |
# No such file or directory なはずなので、シンボリックリンクを作成する |
| 44 |
add_files.each { |file| |
| 45 |
File.symlink(file, File.basename(file)) |
| 46 |
} |
| 47 |
|
| 48 |
# Makefile.am を追記モードで開き、追記を行う |
| 49 |
File.open('Makefile.am', 'a') { |io| |
| 50 |
add_files.each { |file| |
| 51 |
add_basename = File.basename(file) |
| 52 |
if add_files.assoc(add_basename) == nil |
| 53 |
io.write(' ' + add_basename) |
| 54 |
$sources_list.push(add_basename) |
| 55 |
end |
| 56 |
} |
| 57 |
} |
| 58 |
|
| 59 |
return true |
| 60 |
end |
| 61 |
|
| 62 |
# ----- メイン処理 ----- |
| 63 |
# 引数がなければ、使い方を表示して終了 |
| 64 |
if ARGV.size <= 0 |
| 65 |
print "usage:\n\t" + __FILE__ + " <Makefile>\n\n" |
| 66 |
exit |
| 67 |
end |
| 68 |
|
| 69 |
# パース情報の初期化 |
| 70 |
makefile = ARGV[0] |
| 71 |
makefile_rpath = File.dirname(makefile) + '/' # Makefile への相対パス |
| 72 |
include_pathes = [] |
| 73 |
|
| 74 |
# 引数渡しのファイルを Makefile と見なして読み出す |
| 75 |
File.open(makefile) { |io| |
| 76 |
while line = io.gets |
| 77 |
|
| 78 |
# INCLUDE 指定のパスを抜き出す |
| 79 |
if line =~ /^INCLUDES = (.+)/ |
| 80 |
includes = Regexp.last_match[1].split(' ') |
| 81 |
includes.each { |include| |
| 82 |
include_pathes.push(makefile_rpath + include[2, 128] + '/') |
| 83 |
} |
| 84 |
# Makfile のある場所も追加しておく |
| 85 |
include_pathes.push(makefile_rpath) |
| 86 |
end |
| 87 |
|
| 88 |
# REQUIRE_LIBS 指定のパスも、探索パスに含める |
| 89 |
if line =~ /^REQUIRE_LIBS = (.+)/ |
| 90 |
require_libs = Regexp.last_match[1].split(' ') |
| 91 |
require_libs.each { |lib| |
| 92 |
include_pathes.push(makefile_rpath + File.dirname(lib) + '/') |
| 93 |
} |
| 94 |
end |
| 95 |
end |
| 96 |
} |
| 97 |
|
| 98 |
# Makefile.am のバックアップを作っておく |
| 99 |
FileUtils.copy('Makefile.am', 'Makefile.am.bak') |
| 100 |
|
| 101 |
# Makefile.am から、SOURCES に登録済みのファイルを抜き出す |
| 102 |
File.open('Makefile.am') { |io| |
| 103 |
while line = io.gets |
| 104 |
if line =~ /_SOURCES = (.+)/ |
| 105 |
$sources_list = Regexp.last_match[1].split(' ') |
| 106 |
end |
| 107 |
end |
| 108 |
} |
| 109 |
|
| 110 |
# make を実行し、見つからないファイルを追加していく |
| 111 |
begin |
| 112 |
`make 2> errors_output.txt` |
| 113 |
make_status = $?.to_i / 256 |
| 114 |
|
| 115 |
changed = false |
| 116 |
File.open('errors_output.txt') { |io| |
| 117 |
while line = io.gets |
| 118 |
if (line =~ / (.+): No such file or directory/) || |
| 119 |
(line =~ / (.+): そのようなファイルやディレクトリはありません/) |
| 120 |
|
| 121 |
add_file = Regexp.last_match[1] |
| 122 |
|
| 123 |
# ファイルの探索と追加 |
| 124 |
print 'Adding ' + add_file + ' ... ' |
| 125 |
ret = searchAndRegister(add_file, include_pathes) |
| 126 |
if ret |
| 127 |
print "O.K.\n" |
| 128 |
else |
| 129 |
# エラーになったら、強制終了させる |
| 130 |
print "Fail !\n" |
| 131 |
|
| 132 |
# 変更がなかったことにしてループを抜け、メッセージを表示させる |
| 133 |
changed = false |
| 134 |
break; |
| 135 |
end |
| 136 |
changed = true |
| 137 |
end |
| 138 |
end |
| 139 |
} |
| 140 |
if changed == false |
| 141 |
# エラーメッセージを表示させるための処理 |
| 142 |
# !!! ひどいな... |
| 143 |
# !!! errors_output.txt のサイズによっては、正常終了とみなすべきかと |
| 144 |
if make_status != 0 |
| 145 |
print "Fail !!\n" |
| 146 |
`make` |
| 147 |
end |
| 148 |
end |
| 149 |
end while (make_status != 0) && changed |
| 150 |
|
| 151 |
# 生成したファイルを削除して、おしまい |
| 152 |
FileUtils.remove('errors_output.txt') |