의존성과 갱신된 파일을 고려하여 자동으로 컴파일을 해주는 작은 프로그램인 make 의 인자로 들어가는 Makefile 파일을 자동으로 만드는 스크립트를 만들어서 사용해 보자.
make 는 인자가 없이 실행되면 그 명령어가 실행된 경로에 존재하는 Makefile 을 읽어서 그 안에 지시된 대로 컴파일 및 link 를 하는 유틸리티이다. 그런데, 나의 경우, 분석하는 cpp 파일을 수시로 새로 만들게 되고, 개인적으로 사용하는 library 도 빈도가 적기는 하나 새로 만들거나 수정이 된다. 그런데 이럴 때마다 Makefile 을 새로 만드는 것이 귀찮더군. 그래서 아예 Makefile을 자동으로 만드는 스크립트를 작성하여 사용한다. 그 스크립트 이름이 makefile.py 인데, 이 스크립트가 실행된 경로에 있는 모든 cpp 파일을 읽어서, 그 cpp 파일들이 사용하는 개인 library 와 별도의 외부 library 를 compile 하기 위한 지시자를 Makefile 에 작성하는 스크립트인 것이다. 한 번 만들어 놓으니 거의 수정 없이 여기저기서 사용하게 되었다. ㅋㅋㅋ. 역시나 진리의 파이썬으로 초간단하게 작성. 다음은 그 코드다. 당연히 저 코드를 그대로 사용할 수는 없을테지. 이 글은, 일단, 이렇게 할 수 있다는 것을 말함과 동시에, 그 예를 보여 주기 위한 글이다. (파이썬에선 줄 마지막에 세미콜론이 필요 없다는 것을 나도 알고 있다. 하지만 C++ 과 파이썬 코딩을 '동시에' 하는 일이 잦은 나는 차라리 둘 모두에서 ; 를 붙이는 것이 편하기 때문에 그냥 이렇게 하고 있다)
#! /usr/bin/python
import os;
import sys;
import re;
import glob;
def has_main(cpp_file):
f = open(cpp_file);
for line in f:
if line.find('int main()' == 0: return True;
return False;
def get_custom_header(cpp_file):
header_path = '/home/adnoctum/LJSLibrary/headers/';
f = open(cpp_file);
header = [];
for line in f:
m = re.search('#include <(.*?)>$',line);
if m:
if os.path.exists(header_path+m.group(1)) == True:
header.append(m.group(1));
return header;
def get_all_included(cpp_file):
f = open(cpp_file);
header = [];
for line in f:
m = re.search('#include <(.*?)>$',line);
if m:
header.append(m.group(1));
return header;
def post_process_executible_command(exec_cmd, cpp_file):
all_included = get_all_included(cpp_file);
if all_included.count('gmp.h') == 1:
exec_cmd = exec_cmd + ' -lgmp';
if all_included.count('gmpxx.h') == 1:
exec_cmd = exec_cmd + ' -lgmpxx';
return exec_cmd;
def main():
all_cpp_files = glob.glob('*.cpp');
content = [];
custom_header = [];
all = 'all:';
for cpp_file in all_cpp_files:
if has_main(cpp_file) == False: continue;
executible = cpp_file[0:-4];
obj = executible + '.o';
all = all + ' ' + executible;
header = get_custom_header(cpp_file);
lib_config = '';
for h in header:
if lib_config.find(h[0:-1]) == -1:
# statutil.o should be supplied with modutil.h because modutil.h uses statutil.h
if h[0:-1] == 'modutil.':
if lib_config.find('statutil') == -1:
lib_config = lib_config + ' ' + '$(LIB_PATH)/' + 'statutil.o';
if custom_header.count('statutil.h') == 0: custom_header_append('statutil.h');
lib_config = lib_config + ' ' + '$(LIB_PATH)/' + h[0:-1] + 'o';
if custom_header.count(h) == 0: custom_header.append(h);
lib_config = lib_config.strip();
exec_req = executible + ': '+ obj + ' ' + lib_config;
exec_cmd = '\tg++ -o ' + executible + ' ' + obj + ' ' + lib_config;
exec_cmd = post_process_executible_command(exec_cmd, cpp_file);
obj_req = obj + ': '+cpp_file;
obj_cmd = '\tg++ -c '+cpp_file;
content.append(exec_req);
content.append(exec_cmd);
content.append(obj_req);
content.append(obj_cmd);
content.append('\n');
content.insert(0, all+'\n');
for ch in custom_header:
obj = ch[0:-1]+'o';
obj_cpp = ch[0:-1]+'cpp';
obj_req = '$(LIB_PATH)/'+obj + ': $(LIB_SRC_PATH)/'+obj_cpp;
obj_cmd = '\tg++ -c $(LIB_SRC_PATH)/'+obj_cpp;
obj_move = '\tmv '+obj+' $(LIB_PATH)';
content.append(obj_req);
content.append(obj_cmd);
content.append(obj_move);
w = open('Makefile', 'w');
w.write('LIB_PATH=/home/adnoctum/LJSLibrary/library\n');
w.write('LIB_SRC_PATH=/home/adnoctum/LJSLibrary/source\n');
w.write('\n');
for line in content:
w.write(line+'\n');
w.close();
os.system('make');
if __name__ == '__main__':
main();
import os;
import sys;
import re;
import glob;
def has_main(cpp_file):
f = open(cpp_file);
for line in f:
if line.find('int main()' == 0: return True;
return False;
def get_custom_header(cpp_file):
header_path = '/home/adnoctum/LJSLibrary/headers/';
f = open(cpp_file);
header = [];
for line in f:
m = re.search('#include <(.*?)>$',line);
if m:
if os.path.exists(header_path+m.group(1)) == True:
header.append(m.group(1));
return header;
def get_all_included(cpp_file):
f = open(cpp_file);
header = [];
for line in f:
m = re.search('#include <(.*?)>$',line);
if m:
header.append(m.group(1));
return header;
def post_process_executible_command(exec_cmd, cpp_file):
all_included = get_all_included(cpp_file);
if all_included.count('gmp.h') == 1:
exec_cmd = exec_cmd + ' -lgmp';
if all_included.count('gmpxx.h') == 1:
exec_cmd = exec_cmd + ' -lgmpxx';
return exec_cmd;
def main():
all_cpp_files = glob.glob('*.cpp');
content = [];
custom_header = [];
all = 'all:';
for cpp_file in all_cpp_files:
if has_main(cpp_file) == False: continue;
executible = cpp_file[0:-4];
obj = executible + '.o';
all = all + ' ' + executible;
header = get_custom_header(cpp_file);
lib_config = '';
for h in header:
if lib_config.find(h[0:-1]) == -1:
# statutil.o should be supplied with modutil.h because modutil.h uses statutil.h
if h[0:-1] == 'modutil.':
if lib_config.find('statutil') == -1:
lib_config = lib_config + ' ' + '$(LIB_PATH)/' + 'statutil.o';
if custom_header.count('statutil.h') == 0: custom_header_append('statutil.h');
lib_config = lib_config + ' ' + '$(LIB_PATH)/' + h[0:-1] + 'o';
if custom_header.count(h) == 0: custom_header.append(h);
lib_config = lib_config.strip();
exec_req = executible + ': '+ obj + ' ' + lib_config;
exec_cmd = '\tg++ -o ' + executible + ' ' + obj + ' ' + lib_config;
exec_cmd = post_process_executible_command(exec_cmd, cpp_file);
obj_req = obj + ': '+cpp_file;
obj_cmd = '\tg++ -c '+cpp_file;
content.append(exec_req);
content.append(exec_cmd);
content.append(obj_req);
content.append(obj_cmd);
content.append('\n');
content.insert(0, all+'\n');
for ch in custom_header:
obj = ch[0:-1]+'o';
obj_cpp = ch[0:-1]+'cpp';
obj_req = '$(LIB_PATH)/'+obj + ': $(LIB_SRC_PATH)/'+obj_cpp;
obj_cmd = '\tg++ -c $(LIB_SRC_PATH)/'+obj_cpp;
obj_move = '\tmv '+obj+' $(LIB_PATH)';
content.append(obj_req);
content.append(obj_cmd);
content.append(obj_move);
w = open('Makefile', 'w');
w.write('LIB_PATH=/home/adnoctum/LJSLibrary/library\n');
w.write('LIB_SRC_PATH=/home/adnoctum/LJSLibrary/source\n');
w.write('\n');
for line in content:
w.write(line+'\n');
w.close();
os.system('make');
if __name__ == '__main__':
main();
요것이 makefile.py 파일. syntax highlight 가 없어서 보기 불편한데, 어쨌든, ㅋ. 역시나 진리의 파이썬!!
'컴퓨터 > 자질구레 팁' 카테고리의 다른 글
Gmail 도착 알리미 (0) | 2011.02.06 |
---|---|
지정된 항목을 빨리 선택하기 (0) | 2011.01.31 |
탐색기에서 python 파일로 drag & drop 사용 (0) | 2011.01.10 |
유용한 파이썬 라이브러리 (0) | 2010.12.21 |
도스창 크기 등을 조절하기 (0) | 2010.12.15 |