Bare git으로 부터 source code 복사하기

Android에 기반한 project를 repo로 mirror로 만들때는 –mirror option을 주어서 bare git을 만든다(지난 posting 참조). 만약 이렇게 만들어진 bare repository로 부터 일반적인 형태의 source repository를 생성하려 한다면 어떻게 해야 할까? 이 posting에서는 git-daemon등을 설치 하지 않고 local에 있는 bare git으로 부터 source 구조를 만들어 내는 방법을 설명한다.

Repo Init

$ repo init help
Usage: repo init -u url [options]

repo init 명령을 수행할 때 -u 뒤에 url을 적어준다. 일반적으로 이 부분에 ‘git://’이나 ‘ssh://’ protocol로 시작하는 주소를 적지만 우리가 하려는 것은 file 복사 이므로 ‘file://’을 적어서 repo init을 수행한다.

$ repo init -u file://PATH_TO_MIRROR -b BRANCH -m MANIFEST_XML

놀랍게도(!) init이 수행되면서 .repo directory가 생성된다.

Fetch Address 수정

.repo/manifests에서 fetch address를 가지고 있는 xml file을 찾아서 접근 address를 file경로로 수정한다.

  <!-- 
  <remote name="REMOTE_NAME" fetch="ssh://SERVER_IP" review="REVIEW_ADDRESS:8080"/> 
  -->
  <remote name="REMOTE_NAME" fetch="file://<path_to_mirror>/" review="REVIEW_ADDRESS:8080"/>

init이 완료 되고 난 후에는 일반적인 것과 같이 repo sync 명령어를 수행하면 된다. file://로 수정한 xml file들을 원래 상태로 되돌리는 건 다들 아실테고 … 😉

OpenGrok 설치

OpenGrok을 설치하는 가장 간단한 방법은 tomcat5~6 사이의 버전을 사용하고, 설치하는 위치를 /var/opengrok 으로 정하는 것이다. 이렇게 하면 별도의 수정없이 거의 그대로 OpenGrok을 사용할 수 있다. (OpenGrok 설치 빨리 하기 참조)

이 posting에서는 Source를 <YOUR_SOURCE_REPOSITORY_TOP> 경로 아래에 각 project별로 따로 보관하고, <YOUR_HOME_DIRECTORY>/opengrok 경로 아래에 OpenGrok과 관련된 file들을 보관하는 상황을 가정하고 설명한다.

설치 환경

Ubuntu 12.04에 tomcat7을 설치하고, OpenGrok에 관련된 file들은 <YOUR_HOME_DIRECTORY>/opengrok 아래에 보관하고, source code들은 별도로<YOUR_SOURCE_REPOSITORY_TOP> 아래에 project별로 구성되어 있는 상황을 가정한다.

필요한 package들

$ sudo apt-get install tomcat7 tomcat7-admin exuberant-ctags

설치가 완료된 후에 http://localhost:8080으로 접근하면 tomcat이 제대로 동작하는지 확인해 볼 수 있다. Tomcat이 동작하는 것을 확인한 후에는 OpenGrok을 download 받아 압축을 해제한다.

$ wget http://hub.opensolaris.org/bin/download/Project+opengrok/files/opengrok-0.11.1.tar.gz
$ tar xvzf opengrok-0.11.1.tar.gz

OpenGrok 실행 환경 만들기

OpenGrok이 동작할 환경을 만든다. bin, data, etc, src가 필요한데 bin은 OpenGrok script를 비롯한 실행 file들이 들어갈 곳이고, data는 indexing된 결과물이 저장된다. etc에는 configuration에 관련된 data가 포함되고 src에는 OpenGrok이 분석할 source code가 저장되는 곳이다. 하지만 앞서 말한것 처럼 source는 이미 다른 위치에 있는 것을 가정하고 환경을 설정할 것이다.

$ mkdir -p opengrok/bin
$ mkdir -p opengrok/data
$ mkdir -p opengrok/etc

압축을 해제한 곳으로 부터 bin directory로 실행에 필요한 파일들을 복사한다.

$ cp bin/OpenGrok opengrok/bin
$ cp -r lib opengrok/

Tomcat7 경로 추가

FATAL ERROR: Unable to determine Deployment Directory for Tomcat - Aborting

OpenGrok을 deploy하기 위해 명령을 치면 tomcat directory를 찾지 못했다는 오류와 함께 실행이 중단된다. 이것은 OpenGrok 0.11.1 version에서 tomcat7에 대한 고려가 되어있지 않기 때문인데 bin directory로 복사한 OpenGrok script를 편집기로 열어서 아래와 같이 2곳에 tomcat7이 포함되도록 추가해 준다.

1. FindApplicationServerType()에 tomcat7 추가 (Line 489)

    # This implementation favours Tomcat, but needs a lot of work,
    # especially if Glassfish is perferrerd or it is under the control
    # of SMF (Service Management Facility)

    # Maybe a better implementation would be to call Application
    # Server specific WAR Directory and see if they exist.

    if [    -d "/var/tomcat6/webapps"        \   
         -o -d "/var/lib/tomcat6/webapps"    \   
         -o -d "/var/lib/tomcat5/webapps"    \   
         -o -d "/var/lib/tomcat5.5/webapps"  \
         -o -d "/var/lib/tomcat7/webapps"    \   
       ]   
    then
        echo "Tomcat"
        return
    fi

2. DetermineWarDirectoryTomcat()에 tomcat7 추가 (Line 524)

    for prefix in               \   
        ${OPENGROK_TOMCAT_BASE} \
        /var/tomcat6            \   
        /var/lib/tomcat6        \   
        /var/lib/tomcat5        \   
        /var/lib/tomcat5.5      \   
        /var/lib/tomcat7
    do

OpenGrok script의 실행경로 변경하기

OpenGrok script는 /var/opengrok directory아래에 bin, data, ext, src가 있는 것을 가정하고 작성되어 있다. Source 경로는 별도의 directory에 보관하고 있는 것을 그대로 사용하고, bin, data, ext는 home directory에 opengrok directory 아래에 있는 것을 사용하므로, OpenGrok script를 열어서 관련 부분을 수정해 준다.

1. OPENGROK_INSTANCE_BASE

: 이 값을 기준으로 bin, data, ext, src의 경로가 기본값으로 설정되어 있으므로, 원하는 경로로 이 값을 바꾼다.

    #OPENGROK_INSTANCE_BASE="${OPENGROK_INSTANCE_BASE:-/var/opengrok}"
    OPENGROK_INSTANCE_BASE="${OPENGROK_INSTANCE_BASE:-/<YOUR_HOME_DIRECTORY>/opengrok}"

2. SRC_ROOT

: Source code는 다른경로에 있는 것을 사용하므로, SRC_ROOT를 변경한다.

    # REQUIRED: Source Code/Repository Root
    #           (your source code or the root of all repositories)
    #SRC_ROOT="${OPENGROK_INSTANCE_BASE}/src"
    SRC_ROOT="<YOUR_SOURCE_REPOSITORY_TOP>"

configuration.xml 위치 변경

web.xml에서 configuration.xml 생성위치를 변경해준다. 이 파일은 source.war안에 들어 있으므로 압축을 해제한 후 수정하고 재 압축하는 다소 번거로운 절차를 따라야 한다.

1. 먼저 source.war file의 압축을 푼다.

$ unzip opengrok/lib/source.war -d opengrok/lib/source

2. web.xml을 수정한다.

: opengrok/lib/source/WEB-INF/web.xml file을 열어서 CONFIGURATION 부분의 <param-value> 값을 우리가 사용할 etc 위치로 변경해 준다. (Line 9)

$ vi opengrok/lib/source/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
  <display-name>OpenGrok</display-name>
  <description>A wicked fast source browser</description>
  <context-param>
    <param-name>CONFIGURATION</param-name>
    <!-- <param-value>/var/opengrok/etc/configuration.xml</param-value> -->
    <param-value><YOUR_HOME_DIRECTORY>/opengrok/etc/configuration.xml</param-value>
    <description>Full path to the configuration file where OpenGrok can read it's configuration</description>
  </context-param>

3. 다시 zip으로 압축한다.

$ zip -u opengrok/lib/source.war opengrok/lib/source/WEB-INF/web.xml 
  adding: opengrok/lib/source/WEB-INF/web.xml (deflated 80%)

Deploy with the script

이제 모든 준비가 되었으니 super user로 deploy를 실행한다.

$ sudo ./OpenGrok deploy
[sudo] password for <YOUR_ACCOUT>: 
Loading the default instance configuration ...
Installing /usr/opengrok/bin/../lib/source.war to /var/lib/tomcat/webapps ...

Start your application server (Tomcat),  if it is not already
running, or wait until it loads the just installed web  application.

OpenGrok should be available on <HOST>:<PORT>/source
  where HOST and PORT are configured in Tomcat.

Indexing

OpenGrok을 사용하려면 source code들에 대해서 indexing하는 과정을 거쳐야 하는데, source code의 크기와 PC성능에 따라 다르지만, source code가 크면 꽤 오랜 시간이 소요될 수도 있다.

$ opengrok/OpenGrok index
Loading the default instance configuration ...
  Creating default <YOUR_HOME_DIRECTORY>/opengrok/logging.properties ... 
WARNING: Can't find distribution logging configuration (<YOUR_HOME_DIRECTORY>/opengrok/bin/../lib/../doc/logging.properties) to install as default logging configuration (<YOUR_HOME_DIRECTORY>/opengrok/logging.properties)

사용

Indexing 작업이 완료된 후에는 http://localhost:8080/source 경로로 접근하면 OpenGrok을 사용할 수 있다.

OpenGrok ScreenShot

[BinaryHack#11] 실행 파일에 데이터 삽입하기 (64bits)

‘Binary Hacks’의 hack #11에는 objcopy를 이용해서 실행파일에 binary를 추가하는 방법이 나온다. 이것을 따라 64 bits machine에서 build하면 i386:x86-64 출력물과 i386 출력물이 incompatible 해서 link할 수 없다는 오류가 발생한다.

$> objcopy -I binary -O elf32-i386 -B i386 binary.bmp binary.o
$> gcc -c main.c
$> gcc -o program main.o binary.o
/usr/bin/ld: i386 architecture of input file 'binary.o' is incompatible with i386:x86-64 output
collect2: error: ld returned 1 exit status

gcc로 만들어진 main.o는 ELF-64 format인데 objcopy로 생성한 ELF-32 format이어서 함께 link할 수 없다는 것이다. 이 문제는 동일한 ELF format이 되도록 하면 해결된다. 즉, gcc로 compile한 결과물이 objcopy의 결과물인 ELF-32와 동일하게 되도록 하거나 objcopy의 결과 물이 main.o와 동일한 ELF-64가 되도록 해야한다.

첫번째 방법 – ELF-32 format으로 object를 compile
gcc에 -m32 option을 추가하면 ELF32로 compile된 object file을 얻을 수 있다. 이것을 objcopy의 결과 물과 link한다.

$> objcopy -I binary -O elf32-i386 -B i386 binary.bmp binary.o
$> gcc -m32 -c main.c
$> gcc -m32 -o program main.o binary.o

두번째 방법 – ELF-64 format으로 binary를 생성
objcopy가 ELF64를 생성하도록 하면 gcc로 compile한 다른 object file들과 link할 수 있다.

$> objcopy -I binary -O elf64-x86-64 -B i386 binary.bmp binary.o
$> gcc -c main.c
$> gcc -o program main.o binary.o

 

* objcopy로 생성된 ELF object에서 담고 있는 symbol의 목록은 nm 명령어나 readelf -s option으로 볼 수 있다.

$> nm binary.o
00000000002fd036 D _binary_binary_bmp_end
00000000002fd036 A _binary_binary_bmp_size
0000000000000000 D _binary_binary_bmp_start

$>readelf -s binary.o
Symbol table '.symtab' contains 5 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     2: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    1 _binary_binary_bmp_start
     3: 00000000002fd036     0 NOTYPE  GLOBAL DEFAULT    1 _binary_binary_bmp_end
     4: 00000000002fd036     0 NOTYPE  GLOBAL DEFAULT  ABS _binary_binary_bmp_size