2009년 3월 30일 월요일

ubuntu, cmake, boost

ubuntu 가 짱나는게 개발툴들이 버전업이 느리다는거.
결국 ppa 를 찾거나 직접 빌드해서 설치해야 하는데
둘다 기분좋은 일은 아니다.

어쨌건 boost 를 쓰게 되기까지의 과정들
  • boost 는 1.38 가져다 직접 빌드. bjam 오랜만에 써보니 인자들이 기억이 안나서 당황. ubuntu 패키지 시스템과 충돌을 피하려고 ~/boost 를 prefix 로 해서 깔았는데 이게 모든 삽질의 시작이 되었다.
  • intrepid 의 cmake 가 boost 1.38 을 지원하지 않는 버전.. 후럴... ~/boost 아래 깔린 boost 라이브러리를 못찾는 문제가 있더라. https://launchpad.net/~pgquiles/+archive/ppa 추가해서 설치. 근데 이친구는 굉장히 많은 패키지를 제공하네.
  • CMakeLists.txt 에 아래 매크로를 추가해줬다. 간단히 테스팅용도로 쓰는거니 매번 타이핑하는건 번거롭지. 처음안 아예 링크까지 매크로안에 포함시켜벼렸는데 그건 좀 그래서 다시 뺐다.
  • 음. 그런데 매크로 짜는게 쉽지 않았다. cmake 스크립트가 워낙 졸렬해서..
    # 간단히 만들어본 boost 사용
    # 최상위 CMakeLists.txt 에서
    #
    # use_boost(1.38 system date_time filesystem)
    #
    # 식으로 버전적은후 필요한 컴퍼넌트들을 줄줄이 적으면 된다.
    # foo 라는 바이너리에 부스트 라이브러리들을 링크할때는
    #
    # target_link_libraries(foo ${Boost_LIBRARIES})
    #
    # 요리 적으면 된다. 정말 편히 쓰려면 아예 link_libraries 를 박아도
    # 되고.
    macro(use_boost ver)
    set(Boost_USE_STATIC_LIBS ON)
    set(Boost_USE_MULTITHREAD ON)

    # 아오 짱나. cmake 문법은 정말 드럽군. &rest 같은놈이 없어서 ARGV 를
    # 복사하고 앞대가리를 뽑아냈다. 달랑 이거 몇줄 때문에 시간 꽤나 날아갔네.
    set(components ${ARGV})
    list(REMOVE_AT components 0)

    find_package(Boost ${ver} EXACT COMPONENTS ${components})
    if(Boost_FOUND)
    include_directories(${Boost_INCLUDE_DIRS})
    endif()
    endmacro(use_boost)


음.. 위 매크로가 추가되면서 내가 자주 써먹는 misc.cmake 는 모양이 이렇게 됐네. 보통 최상위 CMakeLists.txt 에서 이걸 인클루드 하도록 하고 쓰는게 내 현재 개발취향

펼쳐두기..



PS
아..
환경변수에서 BOOST_ROOT 잡는거 잊지 말자.

PS.
오랜만에 C++ 에 boost 까지 써먹으니 빌드속도 쩌는구먼.
아 답답해







2009년 3월 27일 금요일

ghc 소켓제한

http://hackage.haskell.org/trac/ghc/ticket/635

소켓 스트레스 테스트를 짜기위해서 먼저 그냥 소켓만 열어두고 아무일 안하는놈을 만들어봤다. haskell 쓰레드는 erlang 처럼 가벼운놈이라 몇개를 열건 별무리없이 소화하겠지.. 했는데 소켓 천개정도 만든후엔 뻗어버리더라. ulimit 제한은 먼저 풀어둔 상태고..

적절히 구글링 해보니 ghc 가 내부적으로 소켓을 다룰때 select 를 쓰기때문에 생기는 문제라고 하는데.. 뭐 수정될거라고는 하지만 기분이 좀 드럽군. ghc 면 역사가 몇년인데 아직도 이런 문제가 있는건지.

역시나 내가 하는 일들에 쓰기는 어렵구만.


2009년 3월 25일 수요일

ccache 설치

CC 환경변수를 ccache gcc 등으로 수정해서 써왔는데
이게 잘 안먹을때가 종종있네.
환경변수 무시하고 CC 잡아버리는 개발환경도 많고.
그래서 쓰는 방법을 심볼릭 링크를 통한것으로 바꿨다.


1. ~/bin 을 path 의 가장 처음으로 둔다.
2. ~/bin 에서 아래 심볼링 링크를 만든다.
  ccache -> gcc
  ccache -> g++
  ccache -> arm-elf-gcc
  ccache -> arm-elf-g++
3. 환경적용후 which gcc 등으로 ~/bin 아래의 심볼릭 링크가 먼저 실행되는지 확인
4. 그냥 쓴다.

2009년 3월 24일 화요일

2009년 3월 18일 수요일

emacs 에서 per-directory local variables 와 anything 으로 프로젝트들 빌드하기

현재 ede 사용을 검토중인데 지금 내가 쓰는 방법을 먼저 적어둔다. 꽤 오래전부터 써오던 코드라 위키 등에도 적어둔건데 정리할겸.

내가 원하는것
1. 여러개의 프로젝트들을 목록으로 관리
2. 목록중 하나를 선택하면 해당 프로젝트 루트디렉토리를 dired 모드로
3. 해당 프로젝트 아래의 소스를 편집중에 f7 을 누르면 적당한 방법으로 빌드

이게 전부.
1,2 는 anything 으로 해결했고 3 은 직접만든 함수에 추가로 예전에는 dirvars.el 을 쓰다가 emacs 자체기능으로 전환.
비슷한 일을 하는 코드들이 많지만 써보지는 않았다. 그냥 내손에 맞게 만들다 보니 이런 모양이 됐더라. 자동완성(별 필요성을 못느끼지만) 때문에 ede 를 보고 있는 중인데 ede 를 적용하면 anything 을 ede 로부터 뽑아내야 하는등 다소 변화가 있어야 해서 일단 내걸 정리해둔다.

먼저 f7 을 누르면 컴파일 되도록 하는것부터.
간단히 f7 눌리는 순간 로컬변수로부터 컴파일 커맨드 가져와서 그걸 돌리는걸로 끝. 그런데 내가 cmake 를 쓰고 아웃오브소스 빌드를 좋아하니 빌드디렉토리가 현재 버퍼의 디렉토리와 달라서 이 정보까지 구겨박아야 했다.
이때 이 로컬변수 이름을 yoonkn-build-option 이라고 하고( yoonkn 붙인건 elisp 이 네임스페이스가 없기 때문 헐. 달리 붙인 단어가 없더라) 여러 정보가 들어가야 하니 alist 로 구성했다.(구버전에서는 plist 형태였는데.. 왜바꿨는지는 기억안나네)

즉 yoonkn-build-option 의 모양은 이런 형태
(setq yoonkn-build-option '((build-directory . "/tmp/foo")
(build-command . "make "))
이정보를 가지고 f7 눌리면 /tmp/foo 에 가서 make  돌리도록 해보자.
(defun yoonkn-build ()
(interactive)
(if (and (boundp 'yoonkn-build-option)
(not (null yoonkn-build-option)))
(let ((pwd (substring (pwd) (length "Directory ")))
(wc (cdr (assq 'build-directory yoonkn-build-option)))
(compile-command (cdr (assq 'build-command yoonkn-build-option))))
(unwind-protect
(progn
(cd wc)
(call-interactively 'compile))
(cd pwd)))
(call-interactively 'compile)))
(global-set-key [f7] 'yoonkn-build
좀 드럽지만 어쨌건 돌아간다..
cmake 알기 전에 msvc 쓸때는 devenv 에 커맨드 라인주고 빌드하기도 했는데 지금은 그렇게 쓸 필요가 없지. 그리고 익스프레스버전은(지금은 모르겠고 2005때는) 커맨드라인 빌드가 잘 안됐던것으로 기억하고. 뭐 어쨌건 상용 msvc 를 쓰고있다면 cmake 없이 바로 커맨드라인으로 빌드가 가능하니 위 함수로 ms 쪽빌드도 가능하다.

음.. 그런데 생각해보니 걍 cd .. ; make 해도 될것 같기도?? 헐

yoonkn-build-option 을 디렉토리마다 다르게 주기
위처럼 때려박으면 여러 프로젝트를 동시에 쓰기가 어려우니 per-dir local var 를 써먹자. 이건 전에 적었으니 대강 넘어가고, 그냥 요런식으로 쓰면 된다.
(define-project-bindings 'foo
'((nil . ((yoonkn-build-option . ((build-directory . "/tmp/foo")
(build-command . "make ")))))))
(set-directory-project "~/scratch/foo" 'foo
나는 위 코드를 office-projects.el 또는 home-projects.el 등에 나눠 넣고 머신마다 다른 el 을 부르도록 해서 쓰고있다.

음. 추가.
per-dir 로컬변수 세팅이 아주 반복적이니 매크로를 만들었다.
(defmacro defproject/yoonkn (name root builddir buildcmd)
`(progn
(define-project-bindings ,name
'((nil . ((yoonkn-build-option . ((build-directory . ,builddir)
(build-command . ,buildcmd)))))))
(set-directory-project ,root ,name)))
매크로를 쓰면 위 너저분한 코드가 아래 한줄로
(defmacro/yoonkn 'foo "~/scratch/foo" "/tmp/foo" "make ")

anything 에 등록하기
프로젝트간에 이동을 쉽게 하기 위해서 anything 을 활용했다. 적당히 anything-source 로 등록하면 그만
;;;; Per-Directory Local Variables 하고 anything 을 이용해서 프로젝트 관리
;;; define-project-bindings, set-directory-project 로 적절히 프로젝트를
;;; 세팅해 두면 그걸 anything 이 읽어서 dired 를 띄울수 있도록 해줬다.
(defun yoonkn-projects-candidates ()
(reverse ; reverse 안해주면 set-directory-project 역순으로 나온다
(mapcar #'(lambda (x)
(symbol-name (cdr x)))
project-directory-alist)))

(defun yoonkn-projects-get-dir (name)
(let* ((name-symbol (intern name))
(dir (car (find name-symbol project-directory-alist :key 'cdr))))
dir))

(defun yoonkn-projects-dired (name)
(dired (yoonkn-projects-get-dir name)))

(defun yoonkn-projects-psvn (name)
(psvn-status (yoonkn-projects-get-dir name)))

(setq anything-sources-my-projects
'((name . "내 프로젝트들")
(candidates . yoonkn-projects-candidates)
(action . (("dired 실행하기" . yoonkn-projects-dired)
("psvn 실행하기" . yoonkn-projects-psvn))))

우왕ㅋ굳ㅋ
이제 프로젝트 굵직한게 추가되면 적당히 등록하고 anything 켜서 이동후 코딩하다가 f7 누르면 장땡. 로컬변수 잘 활용라면 ifdef 모드등도 제어가능하고..


















2009년 3월 10일 화요일

pHash: The open source perceptual hash library

http://www.phash.org/

perceptual hash 라... 이런게 있네.
비슷한 대상으로 해시를 만들면 비슷한 해시값이 떨어져서 검색등에 응용할수 있는 기술.

비슷하다는것은 오디오,비디오 적으로 비슷하다는건데 그러면 신호처리 블라블라.. 겠군.
일단 기억해두면 나중에 쓸일 있겠지.

추가.
http://en.wikipedia.org/wiki/Digital_video_fingerprinting
http://en.wikipedia.org/wiki/Object_recognition

퀘이크엔진 코드리뷰

http://fabiensanglard.net/quakeSource/index.php

기억해두자..

2009년 3월 9일 월요일

win32 cabal 바이너리 다운로드 페이지

http://www.haskell.org/cabal/download.html

이게 다시 찾으려니 안보여서 좀 헤맸네.
다시 찾으려면 또 헤멜거 같아 적어둔다.

여러 마이너(?) 언어들처럼 ghc 도 리눅스쪽이 메인플래폼이라 윈도에서 쓰려면 졸라 짜증나는데 현재 ghc 셋업본도 cabal update 후 upgrade 하면 빌드중에 에러가 뜬다. 혹시나 해서 집에 하드정리 하면서 지웠던 ghc 를 새로 깔고 cabal 새버전을 써보니 아예 upgrade 명령을 막아놨네.

시험삼아 cabal install happstack 을 해봤는데.. 헐 이놈이 happy 에 의존성이 걸린걸 자동으로 못받아 주는모양.. happy 를 직접 설치할려고 했더니 이번엔 perl 이 없다고하네. 윈도에선 게임만 해야겠다.

Tokyo Cabinet 이놈 좋아보이네

http://tokyocabinet.sourceforge.net


앞글에서 존재를 알게되서 소개글만 대강 읽어봤는데 좋아보이네.
다음에 이런류 라이브러리가 필요하면 이게 기억나길빈다.

참고
http://en.wikipedia.org/wiki/Qdbm

FriendFeed 의 DB 사용예

How FriendFeed uses MySQL to store schema-less data
reddit

이친구들 RDB 를 key-value DB 처럼 썼네. 적당히 한테이블에 죄다 때려박고 인덱스역할을 하는 테이블을 직접 만들어 쓴것. 쓰고보니 이거 완존 BDB.

뭔가 좀 어색한데 잘 쓰고 있다고 하니 기억해두자.



추가.
유사한놈 구현체중에 LightCloud 가 있는데 뭐 이런 구현체 한두개가 아니지만 소개글중에 벤치마크가 재미있어 보여 적어둔다. Tokyo Cabinet 이라 첨들어보네.

추가. 2009/06/12

2009년 3월 3일 화요일

haskell 로 프로젝트 오일러의 25번 문제를 풀어봤다

http://www.haskell.org/haskellwiki/Memoization 읽어보자.
오일러 포럼에는 수학적으로 푼 넘들도 많은데 헐..
어릴때 공부 안한게 후회스러울 따름.
http://www.haskell.org/haskellwiki/Euler_problems/21_to_30#Problem_25
도 참고해보자.. 그런데 읽기 어렵네. 어쨌건 돌려보니 내거하곤 성능차이가..
한글위키피디아에 이런 페이지도 있다.


import
Data.List(findIndex)

-- 간단한 구현. 이건 속도때문에 꽝. 코드가 트리형태로 전개되기 때문에
-- 매우 느리다.
fibBad 1 = 1
fibBad 2 = 1
fibBad n = fib (n-1) + fib (n-2)


-- 헐 쫌더 나은 버전일랑가.
-- 함수형 언어라면 간지나게 memoize 등을 써서 푸는게 맞을거 같은데
-- 간단히 Data.Map 하나 두고 캐시처럼 써먹는 모듈을 짜보려고 했으나
-- 실패. 이거뭐.. 어떻게 시작해야 할지도 모르겠더라. 일단 문제는 풀어야
-- 겠으니 익숙한 식대로 루프돌렸다.
fib 1 = 1
fib 2 = 1
fib n = f 3 1 1 2
where f step older old cur
| step == n = cur
| otherwise = let newstep = step+1
newolder = old
newold = cur
newcur = newolder+newold
in f newstep newolder newold newcur

-- fib 함수로 리스트 생성
fibs = map fib [1..]

-- 자릿수
digits :: (Num a) => a -> Int
digits = length . show

-- 풀이. 리스트는 0 base 이고 위 fib 는 1 base 이므로 1 만큼 보정을 했다.
solve = (+1) `fmap` findIndex ((==1000) . digits) fibs

-- 우왕국
-- 현재 내 PC 에서는 대략 2 초정도에 끝난다.
main = print solve