Archive for 5월, 2008

Be Strong

Maltbie Davenport Babcock

Be Strong

Be strong!

We are not here to play, to dream, to drift;

We have hard work to do, and loads to lift;

Shun not the struggle—face it; ‘tis God’s gift.

Be strong!

Say not, “The days are evil.

Who’s to blame?”

And fold the hands and acquiesce—oh shame!

Stand up, speak out, and bravely, in God’s name.

Be strong!

It matters not how deep entrenched the wrong,

How hard the battle goes, the day how long;

Faint not—fight on!

Tomorrow comes the song.

Rakefile basic

Rakefile은 Makefile과 비슷한 역할을 하는, Ruby script입니다. 따라서 Ruby라는 언어의 강력한 기능들을 그대로 가져다 쓸 수 있다는 장점이 있습니다. 단, Ruby를 알아야 제대로 사용할 수 있겠죠. Makefile을 make라는 명령어로 실행하듯이, Rakefile은 rake라는 명령어로 실행합니다. Rakefile 작성법을 Makefile 작성법과 비교하며 살펴보도록 하겠습니다. Makefile의 기본적인 작성법은
Target: Dependency list
[Tab] Command

였죠. Rakefile도 유사합니다. 단, Ruby syntax를 사용하죠. 기본적인 작성법은 다음과 같습니다.
task :name = [:prereq1, :prereq2] do
    Command
end

Makefile에서 Target에 해당하는 것이 Rakefile의 task입니다. 잘 살펴보면 task라는 함수명과 Hash, Block 두 개의 argument로 이루어진 구조라는 것을 알 수 있습니다. Hash의 key는 target이 되고 value는 prerequisites (dependency list)가 됩니다. Block은 실행해야 할 명령들로 이루어집니다. 특별히 compile하는 경우와 같이 파일을 작성하는 task의 경우에는
file "name" = ["prereq1", "prereq2"] do
    Command
end

와 같이 file task를 사용합니다. Command 부분에서 ‘name’ 또는 dependency list (prereq1, prereq2, … )를 사용하고 싶을 때는
file "name" = ["prereq1", "prereq2"] do |t|
sh "f77 -o #{t.name} #{t.prerequisites.join(' ')}"
end

과 같이 사용하여 f77 -o name prereq1 prereq2와 같은 결과를 얻을 수도 있습니다.

그럼 앞에서 만들었던 Makefile과 같은 기능을 하는 Rakefile을 만들어 비교해 보겠습니다. 앞에서 만들었던 Makefile은 다음과 같고,

01: # target: dependency list
02: # [tab] command
03: F77=gfortran
04:
05: all: main
06:
07: main: main.o sub1.o sub2.o
08:         $(F77) -O2 -o main main.o sub1.o sub2.o
09: main.o: main.f
10:         $(F77) -O2 -c main.f
11: sub1.o: sub1.f
12:         $(F77) -O2 -c sub1.f
13: sub2.o: sub2.f
14:         $(F77) -O2 -c sub2.f
15: clean:
16:         rm main main.o sub1.o sub2.o

이에 해당하는 Rakefile은 다음과 같습니다.

f90='gfortran'

task :default => ['main.e']
file 'main.e' => ['main.o','sub1.o','sub2.o'] do |t|
    sh "#{f90} -o #{t.name} main.o sub1.o sub2.o"
end

file 'main.o' => ['main.f'] do
    sh "#{f90} -c main.f"
end
file 'sub1.o' => ['sub1.f'] do
    sh "#{f90} -c sub1.f"
end
file 'sub2.o' => ['sub2.f'] do
    sh "#{f90} -c sub2.f"
end

require 'rake/clean'
CLEAN.include('*.o')
CLOBBER.include('main.e')

task :default 부분은 Makefile에서 all 이라는 target을 지정해서 사용했던 것과 같은 역할을 합니다. 단, Rakefile에서는 default task가 맨 처음에 나올 필요가 없습니다. 파일 내 아무데나 나와도 잘 인식합니다. 중간 부분은 Makefile과 매우 유사하므로 특별한 설명이 필요 없겠죠? 뒤에 있는 clean task는 rake에 이미 지정되어 있는 task입니다. 사용하기 위해서는 ‘rake/clean’을 불러옵니다. rake clean을 실행하면 CLEAN에 포함된 파일들을 지워주고 rake clobber를 실행하면 CLOBBER와 CLEAN에 지정된 파일들을 모두 지워줍니다. 위에서 볼 수 있는 것처럼, 최종 결과 파일만 CLOBBER에 포함시키고 중간에 생성되는 파일들은 CLEAN에 포함시키면 편리하게 사용할 수 있습니다.

Makefile에서는 확장자법칙을 이용해 편리하게 compile할 수 있었죠? Rakefile에도 같은 기능이 있습니다. 비교해볼까요?

01: # $^ : dependency list
02: # $@ : target
03:
04: F77=ifort
05: FFLAG=-assume byterecl -O2
06: TARGET=main
07: OBJECTS=main.o sub1.o sub2.o
08:
09: all: $(TARGET)
10:
11: $(TARGET): $(OBJECTS)
12:         $(F77) -o $@ $^
13:
14: .SUFFIXES: .o .f
15: %.o: %.f
16:         $(F77) ${FFLAG} -c $^
17:
18: clean:
19:         rm $(TARGET) $(OBJECTS)

F90='ifort'
FFLAG='-assume byterecl -O2'
TARGET='main.e'
SRC=FileList['*.f']
OBJ=SRC.ext('o')

task :default => TARGET
file TARGET => OBJ do
    sh "#{F90} -o #{TARGET} #{OBJ}"
end
rule '.o' => '.f' do |t|
    sh "#{F90} #{FFLAG} -c #{t.source}"
end

require 'rake/clean'
CLEAN.include('*.o')
CLOBBER.include('main.e')

Rakefile에서는 rule이라는 함수가 Makefile의 확장자법칙과 같은 역할을 합니다. FileList 명령은 glob pattern (여기서는 ‘*.f’)을 받아들여서 해당하는 파일들의 목록을 만들어주고, FileList 객체의 ext method는 목록에 있는 파일들의 확장자를 원하는 확장자로 바꿔서 새로운 FileList를 만들어줍니다. 앞에서 dependency list를 불러올 때 t.prerequisites.join(' ')이라고 사용했었는데 여기서는 t.source라고 사용했습니다. 앞의 방법은 전체 dependency list를 문자열로 만들어주고(‘ ‘을 이용하여 각각을 합치죠), 뒤의 방법은 dependency list의 첫 번 째 항목만 문자열로 만들어줍니다. 위의 예에서는 dependency list에 ‘.o’에 해당하는 ‘.f’ 파일 하나만 있으니까 t.source라고 사용해도 무관하겠죠?

Makefile에 없고 Rakefile에만 있는 기능 중 하나로, task에 설명을 달 수 있는 기능이 있습니다. task 또는 file task 바로 윗 줄에
desc "description"
이라고 설명을 추가해주면 rake -T라고 실행했을 때 설명과 함께 task 목록을 보여줍니다. Rakefile을 직접 보지 않고도 안에 무슨 task가 있는지 확인할 수 있는 유용한 기능이죠^^

더 자세한 내용은 다음의 site들을 참고하세요.
http://rake.rubyforge.org/
http://docs.rubyrake.org/

The Apology of Socrates

‘소크라테스의 변명’은 소크라테스가 아테네 사람들 앞에서 자신을 고발한 사람들의 고발에 대해 해명한 내용이다. 그는 자신을 고발한 사람들을 오래 된 고발자들과 최근의 고발자들로 나누고 각각의 고발 내용이 편견과 거짓이라 변론한다.

오래된 고발자들의 고발에 대한 변론은 자신이 신의 뜻에 따라 행해온 일 때문에 사람들의 미움을 사서 법정에 서게 되었다는 것이다. 그가 해온 일이란, 자신은 아무 것도 모르니 지혜 있다고 하는 사람들을 찾아가 무언가 배우기 위해 질문들을 해온 일, 그러나 결국 지혜 있다던 사람들이 사실은 무지한 사람이라는 것을 밝혀온 일이다. 멜레토스나 최근의 고발자들이 고발한 내용 – ‘소크라테스는 범죄인이다. 청년들에게 유해하고 파멸적인 영향을 주고 국가가 인정하는 신을 믿지 않으며 다른 새 귀신을 제사지내고 있다.’ – 에 대해서도 조목조목 거짓임을 밝혀낸다.

그러나 이러한 변론에도 불구하고 소크라테스는 결국 사형을 선고받는다. 동정을 구해 사형을 면할 수도 있었지만 그는 자신이 죄가 없다고 주장했고 결국 사형을 선고받았다. 왜 사람들은 그에게 사형을 선고했을까? 플라톤의 ‘국가’ 제 1권에 나오는 트라쉬마코스와 소크라테스의 대화를 읽어보니 이해가 되었다. 소크라테스가 사람들을 끝까지 ‘괴롭혀서’ 사람들에게 상당한 미움을 샀을것이란걸 짐작할 수 있었다. ‘소피의 세계’에 보면 알베르토 크녹스가 소피에게 자신의 확고한 신념을 위해 목숨을 아끼지 않은 소크라테스와 예수 그리스도가 유사한 점이 많다고 알려주는데, ‘소크라테스의 변명’을 읽어보니 그 말 뜻을 알겠다. 이 책에 ‘너 자신을 알라’는 말은 나오지 않지만, 소크라테스가 마지막으로 남긴 유사한 말이 마음에 와 닿았다.

여러분! 내 아들들이 성인이 되거든, 내가 여러분을 괴롭힌 것과 똑같이 그 애들을 괴롭혀서 분풀이를 해주시오. 만일 그 애들이 자기 자신을 훌륭하게 만드는 것보다도 금전이나 그 밖의 일에 먼저 뜻을 두거나 또는 하등 보잘 것도 없는데 벌써 무엇이나 된 줄로 착각하거든, 너희가 유의할 일엔 유의하지 않고 하찮은 인간들인 주제에 제법 무언가 상당한 인물이나 된 것처럼 생각하고 있다고, 내가 여러분에게 했듯이 그 애들을 나무라 주시오.

다음 페이지 »



팔로우

Get every new post delivered to your Inbox.

Join 39 other followers