달력

52024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

git reference

Tool/git 2010. 7. 5. 20:54
git user manual
http://www.kernel.org/pub/software/scm/git/docs/user-manual.html

git user manual 한글 번역본
http://namhyung.springnote.com/pages/3132772

git diagram 비롯한 사용법
http://osteele.com/archives/2008/05/my-git-workflow

git tutorial 1&2
http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html
http://www.kernel.org/pub/software/scm/git/docs/gittutorial-2.html

'Tool > git' 카테고리의 다른 글

git commit 복구하기  (3) 2010.12.08
git 알면 편한 기능  (0) 2010.11.13
git staic build  (0) 2010.04.27
git init --bare 이용  (1) 2010.04.23
git init --bare 발단  (0) 2010.04.23
Posted by neodelicious
|
공부 좀 하자.
그리고 정리를 잘 해서 필요할 때 바로 써 먹을 수 있도록 하자.

cmake example
   git clone git://github.com/neodelicious/cmake_example.git
pthread example
   git clone git://github.com/neodelicious/pthread_example.git

'Personal Interest > ETC' 카테고리의 다른 글

체리새우 깡...  (0) 2016.02.17
ubuntu 10.10 netbook version - unity  (0) 2010.11.14
홈페이지 텍스트큐브로 전환  (0) 2010.03.03
Eclipse bug in Ubuntu 9.10  (0) 2010.02.15
ssd 대신 tmpfs 을 쓰자  (0) 2010.02.14
Posted by neodelicious
|
프로그램을 짜다 보면 flag용으로만 사용하여 실제로는 1byte는 커녕 1bit만 할당해도 사용하는데 충분한 경우가 있다. 이때 bit 단위로 실제 사용 크기만큼만 할당해서 사용하면 메모리를 아낄 뿐 아니라 해당 변수를 복사할 때 빠를 것으로 생각된다.

물론 함수 내에서 잠깐 사용할 경우에는 int 로 선언해도 무방하고, 다른 모든 곳에서도 int 혹은 char 등으로 선언해도 사용하는데도 된다.

그러니까 아마도 주로 사용하는 struct 내에  Bool과 같이 단순 flag만으로 사용하는 변수가 많을 경우 유용할 것이다.

사용 방법은 간단한다.
변수 뒤에 ' : 크기' 와 같은 방식으로 bit 크기를 설정하면 되며, 주의할 것은 unsigned 를 붙여야 한다는 것이다.
예를 들어 unsigned char a1 : 1; 는 1 bit 크기를 할당한다.

관련해서 테스트 소스를 아래와 같이 작성했다.

#include <stdio.h>

struct Mystr {
 unsigned char a1 : 4;
 unsigned char a2 : 2;
 unsigned char a3 : 1;
};

int main(int argc, char *argv[])
{
 int i;
 struct Mystr mystr = { .a3=1, };

 printf("sizeof(struct Mystr) is %d\n", sizeof(struct Mystr));
 if (mystr.a3 == 1)
  printf(".a3=1 works!\n");

 return 0;
}
그 결과는 다음과 같다.
참고적으로 struct Mystr내 bit 크기가 8보다 큰 9라면 sizeof() 결과는 2가 된다.
그리고 unsigned char가 아닌 char 를 쓰면 '1'이 아닌 '0xFFFF'와 같은 값이 저장되어 문제가 된다.
sizeof(struct Mystr) is 1
.a3=1 works!

'Lang, Tool, Env' 카테고리의 다른 글

Linux version  (0) 2016.02.15
Ubuntu /home 옮기기  (0) 2012.08.04
struct timeval & long long  (0) 2010.03.31
IEEE Floating-Point Format  (1) 2009.09.13
chroot  (0) 2008.04.06
Posted by neodelicious
|

CMake 를 써 보자

Tool/build 2010. 5. 8. 07:13

Autotools보다 cMake가 얼마나 좋을까?
CMake는 Linux 외에 다른 OS에서도 범용적으로 build 환경을 제공한다는 점에서 분명히 장점이 있을 것 같다.

그런데 아직 CMake를 많이 안 써봐서 모르겠지만,
Autotools 에서는 기본값으로 되어 있는 'build command 보이기' 나 '-g 옵션을 추가' 등이
CMake에는 기본값으로 되어 있지 않은 등 분명 사용함에 있어서 차이가 있어 보인다.

KDE의 CMake 선정을 비롯한 사례로 볼 때 아마도 아직 내가 모를 뿐,
CMake에서도 Autotools의 기능을 대부분 지원하지 않을까 싶다.

아무튼 개인적으로 CMake의 소위 build template을 만들면서 공부한 것을 정리해서 올린다.

아래 링크에서 source code를 download 할 수 있으며, 이하 글은 이 source code를 설명한다.

http://www.neodelicious.com/repos/cmake_example.tar.bz2


Assumption
1. Linux 환경을 기준으로 설명하며, '$'는 Linux Shell Prompt 를 의미함
2. 각 module 별로 CMakeLists.txt 파일을 생성하지 않고, (top directory)/CMakeLists.txt 에 모두 기술함을 기본으로 함
  2.1 원하면 (top directory)/CMakeLists.txt 파일에서 하위 directory 별로 CMakeLists.txt 파일로 분리하고 상위 directory의 CMakeLists.txt 에서 add_subdirectory 명령어를 통해 재귀적으로 호출할 수 있음
3. Top directory가 아닌 build directory에 build metadata를 생성하는 것을 기본(희망)으로 함
  3.1 Top directory에서 'cmake .'를 실행하면 top directory에 build metadata를 생성함

Reference
1. http://www.cmake.org/cmake/help/documentation.html
  1.1 http://www.cmake.org/cmake/help/cmake_tutorial.html
  1.2 http://www.cmake.org/cmake/help/cmake-2-8-docs.html


Note

1. 한 번 cmake build 하면 CMakeCache.txt 파일에 cmake build 결과의 설정값이 저장되는데, 이를 삭제하지 않고 CMakeLists.txt 파일을 수정하고 cmake build 하면 반영되지 않으니 주의해야 함


Preparation

1. $ tar xvjf cmake_example.tar.bz2
2. $ cd make_example


Build

1. Method 0 - CMakeLists.txt의 default 옵션으로 cmake build 하고, make 까지 진행하는 shell script를 이용 할 때
  1.1 $ ./start_build.sh
2. Method 1 - CMakeLists.txt의 default 옵션으로 cmake build르 직접 할 때
  2.1 $ mkdir build ; cd build
  2.2 $ cmake ..
  2.3 $ make
3. Method 2 - interactive 방식(wizard mode)으로 CMakeLists.txt의 옵션을 변경하여 make build 할 때
  3.1 $ mkdir build ; cd build
  3.2 $ cmake -i ..
  3.3 make
4. Method 3 - Curses Interface 로 CMakeLists.txt의 옵션을 변경하여 cmake build 할 때
  4.1 $ mkdir build ; cd build
  4.2 $ ccmake ..
  4.3 $ make


Run

1. build directory에 실행파일 example과 shared library인 libshow.so 파일이 있음
2. build directory에서 아래를 실행함
  2.1 $ ./example


CMakeLists.txt 파일 설명

# project
1. cmake_minimum_required (VERSION 2.6)
  1.1 cmake의 최소 버전을 명시함, 없으면 경고 메시지가 출력됨
2. project (cmake_example)
  2.1 새 project의 이름을 명시함
# user selectable variables
1. option (ENABLE_SHARED "Select OFF to build libararies as static" ON)
   option (DEBUG "Select ON to define DEBUG" ON)
   option (DEBUG2 "Select ON to define DEBUG2" ON)
  1.1 사용자가 선택할 수 있는 옵션에 대해서 이름, 설명, 기본값 순으로 설정함
2. message ("ENABLE_SHARED - ${ENABLE_SHARED}")
   message ("DEBUG - ${DEBUG}")
   message ("DEBUG2 - ${DEBUG2}")
  2.1 사용자 편의를 위한 화면 출력용으로 사용자가 선택한 값을 화면에 출력함
# dependency check
1. include (FindPkgConfig)
2. pkg_check_modules (pkgs x11>= 1.2.2 xrender)
  2.1 pkg-config tool을 이용해서 system의 library 정보를 확인할 수 있음
  2.2 아래와 같이 REQUIRED 옵션을 추가하여 조건에 부합하지 않으면 cmake build를 중단할 수 있음
    2.2.1 pkg_check_module (pkgs REQUIRED x11>=1.2.2 xrender)
3. foreach (flag ${pkg_CFLAGS})
     set (EXTRA_LIBS ${EXTRA_LIBS} ${flag})
   endforeach (flag)
   foreach (flag ${pkg_LDFLAGS})
     set (EXTRA_LIBS ${EXTRA_LIBS} ${flag})
   endforeach (flag)
 3.1 위의 pkg-config를 통해 얻은 CFLAGS, LDFLAGS 정보를 cmake 변수에 저장함
#global CMake variables
1. if (ENABLE_SHARED)
     set (BUILD_SHARED_LIBS true)
   endif (ENABLE_SHARED)
  1.1 명시적으로 static 혹은 shared 등을 명시하지 않은 add_library 명령에 대해서 기본 값인 static이 아닌 shared로 library를 build 하도록 설정함
  1.2. 이때 if 를 통해 위의 option에서 설정항 사용자의 선택에 따라 static일 경우 적용하지 않도록 함
2. set (CMAKE_VERBOSE_MAKEFILE ture)
  2.1 make build 할 때 build command를 화면에 출력하도록 함
3. set (CMAKE_BUILDTYPE debug)
  3.1 build 옵션에 -g를 포함하도록 함
4. set (CMAKE_INSTALL_PREFIX /usr)
  4.1 make install 을 통해 설치할 directory의 기준 path를 기본값이 아닌 /usr로 설정함
# global build variables
1. include_directories ("${PROJECT_SOURCE_DIR}/include")
  1.1 make build -I 로 설정하여 header file 을 찾을 path를 추가함
  1.2 PROJECT 는 최근 project 명을 대신하며, PROJECT_SOURCE_DIR 대신 여기서는 cmake_example_SOURCE_DIR 을 사용해도 됨
  1.3 PROJECT_BINARY_DIR 변수도 있는데, 이는 cmake를 실행한 path로서 여기에서는 build directory path임
# variables to the configuration file
1. configure_file ("${PROJECT_SOURCE_DIR}/include/config.h.in" "${PROJECT_SOURCE_DIR}/include/config.h")
  1.1 Source code에서 참조할 값을 반영한 config.h 파일을 config.h.in 파일을 수정해서 생성함
# build library
1. add_library (show lib/show.c)
  1.1 libshow.so 파일을 build 함
# build source
1. add_executable (example src/main.c)
  1.1 실행 파일 example 파일을 build 함
2. target_link_libraries (example show ${EXTRA_LIBS})
  2.1 실행 파일에 link할 library를 명시함
  2.2 이때 위에서 pkg-config를 통해 찾은 system 상의 library 정보를 추가함
# install
1. install (TARGETS show DESTINATION lib)
   install (TARGETS example DESTINATION bin)
   install (FILES ${PROJECT_SOURCE_DIR}/include/show.h DESTINATION include)
  1.1 기본적으로 make install을 위한 install target이 Makefile에 기술되지 않음
  1.2 위의 CMAKE_INSTALL_PREFIX 변수를 기준으로 make install에서 복사할 실행 파일, library 파일, header 파일을 명시함

include/config.h.in 파일 설명
1. #define ENABLE_SHARED "@ENABLE_SHARED@"
  1.1 cmake 내 EANBLE_SHARED 변수를 설정하면 @ENABLE_SHARED@ 값을 ON으로 변경하고, 비설정시 OFF로 설정함
2. #cmakedefine DEBUG
  2.1 cmake 내 DEBUG 변수를 설정하면 #define DEBUG를 설정하고, 비설정시 #undef DEBUG를 설정함
3. #cmakedefine01 DEBUG2
  3.1 cmake 내 DEBUG2 변수를 설정하면 #define DEBUG2 1를 설정하고, 비설정싱 #define DEBUG2 0를 설정함

'Tool > build' 카테고리의 다른 글

Make 이용법 (함수 및 특수 타겟)  (0) 2007.12.31
Make 이용법 (재귀적 사용)  (0) 2007.12.29
Posted by neodelicious
|

git staic build

Tool/git 2010. 4. 27. 00:25
웹 호스팅 서비스를 통해서 개인 블로그를 사용하고 있는데,
여기에 개인용 git repository 를 두고 싶어졌다.

그런데 ssh로 접속해서 확인하니 git binary가 설치되어 있지 않았다.
그래서 아래와 같이 git binary를 직접 build 해서 이용하게 되었다.
이때 git binary에서 zlib과 pthread를 shared library로 이용하고 있어서,
관련 static library가 system에 설치되어 있어야 한다.

git binary를 위해 아래와 같이 소스를 다운로드 했다.
$ apt-get source git-core

그리고 Makefile을 열어 아래와 같이 ALL_LDFLAGS에 -static 옵션을 추가했다.
ALL_LDFLAGS = $(LDFLAGS) -static

다음과 같이 build 하고 build 디렉토리에 설치했다.
$ mkdir build
$ ./configure --prefix=/usr
$ make
$ make install DESTDIR=`pwd`/build

제대로 -static 하게 build 되었는지는 ldd git 와 같이 해서 확인할 수 있었다.
그리고 build/usr/bin 안의 git binary 들을 웹 호스팅 서버에 업로드하였다.

'Tool > git' 카테고리의 다른 글

git 알면 편한 기능  (0) 2010.11.13
git reference  (0) 2010.07.05
git init --bare 이용  (1) 2010.04.23
git init --bare 발단  (0) 2010.04.23
qgit  (0) 2010.04.20
Posted by neodelicious
|

git init --bare 이용

Tool/git 2010. 4. 23. 03:06
git repository에 소스가 있는데 이를 clone 해서 변경하고 push 하면 문제가 있다는 것을
이전 글에서 확인했다. (이전 글 --> http://www.neodelicious.com/entry/git-init-bare-1)

이번에는 --bare 옵션을 통해 위의 문제를 해결하는 방법을 설명하고자 한다.

글을 쓰기에 앞서 이전 글에서도 밝혔지만, 아래 웹 페이즈에서 많은 정보를 얻었음을 밝힌다.
http://stackoverflow.com/questions/738154/what-does-git-updating-currently-checked-out-branch-warning-mean

위 링크의 글 상단에 또 다른 링크 How to publish a Git repository를 출처로 bare repository 를 설명하고 있다.

이 bare repository 및 관련 내용을 간단히 번역하면,
우선 bare repository 는 git dababase 만 있고 소스 파일(working copy of code) 없는 것을 의미한다.
만약 bare repository가 아닌 소스 파일이 있는 git repository(non-bare repo)에 git push 하게 되면
HEAD가 git index, 소스 사이에  sync 문제가 발생하므로
(이게 이전 글 http://www.neodelicious.com/entry/git-init-bare-1 에서 확인한 사항이다.)
항상 bare repository에 git push 해야 한다.

그럼 위에서 권고한대로 우선 아무 것도 없는 디렉토리에서 git init --bare로 초기화해보자.
/.git 아래에 숨겨졌던 git database 파일들이 현재 디렉토리에 보이는 것을 확인했다.

jaewon@jaewon-laptop:~/work/study/tool/git$ mkdir remote_bare
jaewon@jaewon-laptop:~/work/study/tool/git$ cd remote_bare/
jaewon@jaewon-laptop:~/work/study/tool/git/remote_bare$ git init --bare
Initialized empty Git repository in /home/jaewon/work/study/tool/git/remote_bare/
jaewon@jaewon-laptop:~/work/study/tool/git/remote_bare$ ls
branches  config  description  HEAD  hooks  info  objects  refs

그 다음에 위의 bare repository를 git clone 하고 새 파일을 생성 및 수정하고 local에 git commit 했다.

jaewon@jaewon-laptop:~/work/study/tool/git/remote_bare$ cd ..
jaewon@jaewon-laptop:~/work/study/tool/git$ git clone ./remote_bare/ ./local
Initialized empty Git repository in /home/jaewon/work/study/tool/git/local/.git/
warning: You appear to have cloned an empty repository.
jaewon@jaewon-laptop:~/work/study/tool/git$ cd local/
jaewon@jaewon-laptop:~/work/study/tool/git/local$ echo "initial" > ./1.txt
jaewon@jaewon-laptop:~/work/study/tool/git/local$ git add 1.txt
jaewon@jaewon-laptop:~/work/study/tool/git/local$ git commit -a -m '1st'
[master (root-commit) 6833fa2] 1st
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 1.txt

그 다음에 bare repository에 git push를 하기 위해 git push 했는데,
다음과 같이 push의 기본 설정이 안 되어 있다고 해서 오류가 발생했다.

jaewon@jaewon-laptop:~/work/study/tool/git/local$ git push
warning: You did not specify any refspecs to push, and the current remote
warning: has not configured any push refspecs. The default action in this
warning: case is to push all matching refspecs, that is, all branches
warning: that exist both locally and remotely will be updated.  This may
warning: not necessarily be what you want to happen.
warning:
warning: You can specify what action you want to take in this case, and
warning: avoid seeing this message again, by configuring 'push.default' to:
warning:   'nothing'  : Do not push anything
warning:   'matching' : Push all matching branches (default)
warning:   'tracking' : Push the current branch to whatever it is tracking
warning:   'current'  : Push the current branch
No refs in common and none specified; doing nothing.
Perhaps you should specify a branch such as 'master'.
fatal: The remote end hung up unexpectedly
error: failed to push some refs to '/home/jaewon/work/study/tool/git/./remote_bare/'

여러 가지 설정이 있을 수 있겠지만, 나는 일단 tracking 방식을 기본으로 설정하고자
git config push.default tracking 과 같이 입력했다.
그리고 push를 정상적으로 할 수 있었다.

jaewon@jaewon-laptop:~/work/study/tool/git/local$ git config push.default tracking
jaewon@jaewon-laptop:~/work/study/tool/git/local$ git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 210 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /home/jaewon/work/study/tool/git/./remote_bare/
 * [new branch]      master -> master

참고적으로 소스 파일이 있는 git repository(non-bare repo)에 git push 해서 발생하는 문제는
이후 git 버전에서 금지될 것 이라고 한다.

또한 기존에 소스 파일이 있는 git repository(non-bare repo)을 clone 하려고 할 경우,
git clone --bare 와 같이 --bare 옵션을 주면 새 repo가 bare repo 가 된다.
git clone --bare 를 아래와 같이 확인했다.

jaewon@jaewon-laptop:~/work/study/tool/git/remote_src$ cd ..
jaewon@jaewon-laptop:~/work/study/tool/git$ git clone --bare ./remote_src/ ./remote_src_bare
Initialized empty Git repository in /home/jaewon/work/study/tool/git/remote_src_bare/
jaewon@jaewon-laptop:~/work/study/tool/git$ cd remote_src_bare/
jaewon@jaewon-laptop:~/work/study/tool/git/remote_src_bare$ ls
branches  config  description  HEAD  hooks  info  objects  packed-refs  refs
jaewon@jaewon-laptop:~/work/study/tool/git/remote_src_bare$ git log
commit 979521d7978f7a26c989047bae7806466353ad61
Author: jaewon <jaewon@jaewon-laptop.(none)>
Date:   Fri Apr 23 02:44:44 2010 +0900
    2nd
commit fc2d23fb93c972c3f48a75f9bf7be7de6a5d5ea3
Author: jaewon <jaewon@jaewon-laptop.(none)>
Date:   Fri Apr 23 02:42:48 2010 +0900
    initial

그런데 non-bare repo 에 push 하더라도 non-bare repo 의 code를 그대로 이용하지 않고
clone 한 후 pull 로 이용하면 문제가 없었다.
그래도 새로 만들 때는 bare 로 하는 게 좋겠다.

그밖에 Using Git to manage a web siteHow to publish a Git repository
hooks/post-receive 파일을 이용해서 git push 되면 자동으로 git checkout -f 되도록 하던데,
자세한 사항은 이해를 못 해서 지금은 넘어가기로 한다.


'Tool > git' 카테고리의 다른 글

git 알면 편한 기능  (0) 2010.11.13
git reference  (0) 2010.07.05
git staic build  (0) 2010.04.27
git init --bare 발단  (0) 2010.04.23
qgit  (0) 2010.04.20
Posted by neodelicious
|

git init --bare 발단

Tool/git 2010. 4. 23. 01:37
git init --bare를 사용하게 된 배경을 설명하고 하며,
우선 간단하게 아래와 같이 문제 상황을 재현했다.

참고적으로 아래 웹 페이지에서 많은 정보를 얻었다.
http://stackoverflow.com/questions/738154/what-does-git-updating-currently-checked-out-branch-warning-mean


먼저 아래와 같이 1.txt 파일 하나가 들어 있는 디렉토리 remote_src 를 git server 로 초기화했다.

jaewon@jaewon-laptop:~/work/study/tool/git$ mkdir remote_src ; cd remote_src
jaewon@jaewon-laptop:~/work/study/tool/git/remote_src$ git init
Initialized empty Git repository in /home/jaewon/work/study/tool/git/remote_src/.git/
jaewon@jaewon-laptop:~/work/study/tool/git/remote_src$ touch 1.txt
jaewon@jaewon-laptop:~/work/study/tool/git/remote_src$ git add 1.txt
jaewon@jaewon-laptop:~/work/study/tool/git/remote_src$ git commit -a -m 'initial'
[master (root-commit) fc2d23f] initial
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 1.txt


그리고 다음과 같이 디렉토리 remote_src 의 git server 를 디렉토리 local_src 로 git clone 한 다음,
1.txt 파일을 수정하고 이를 local 에서 git commit 했다.

jaewon@jaewon-laptop:~/work/study/tool/git/remote_src$ git clone . ../local_src ; cd ../local_src
Initialized empty Git repository in /home/jaewon/work/study/tool/git/local_src/.git/
jaewon@jaewon-laptop:~/work/study/tool/git/local_src$ echo "local modification" > ./1.txt
jaewon@jaewon-laptop:~/work/study/tool/git/local_src$ git commit -a -m '2nd'
[master 979521d] 2nd
 1 files changed, 1 insertions(+), 0 deletions(-)

그 다음 디레토리 remote_src 의 git server 로 소스 변경단을 반영하기 위해서 git push 했는데,
다음과 같은 경고 메시지를 확인했다.

jaewon@jaewon-laptop:~/work/study/tool/git/local_src$ git push
warning: You did not specify any refspecs to push, and the current remote
warning: has not configured any push refspecs. The default action in this
warning: case is to push all matching refspecs, that is, all branches
warning: that exist both locally and remotely will be updated.  This may
warning: not necessarily be what you want to happen.
warning:
warning: You can specify what action you want to take in this case, and
warning: avoid seeing this message again, by configuring 'push.default' to:
warning:   'nothing'  : Do not push anything
warning:   'matching' : Push all matching branches (default)
warning:   'tracking' : Push the current branch to whatever it is tracking
warning:   'current'  : Push the current branch
Counting objects: 5, done.
Writing objects: 100% (3/3), 250 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
warning: updating the current branch
warning: Updating the currently checked out branch may cause confusion,
warning: as the index and work tree do not reflect changes that are in HEAD.
warning: As a result, you may see the changes you just pushed into it
warning: reverted when you run 'git diff' over there, and you may want
warning: to run 'git reset --hard' before starting to work to recover.
warning:
warning: You can set 'receive.denyCurrentBranch' configuration variable to
warning: 'refuse' in the remote repository to forbid pushing into its
warning: current branch.
warning: To allow pushing into the current branch, you can set it to 'ignore';
warning: but this is not recommended unless you arranged to update its work
warning: tree to match what you pushed in some other way.
warning:
warning: To squelch this message, you can set it to 'warn'.
warning:
warning: Note that the default will change in a future version of git
warning: to refuse updating the current branch unless you have the
warning: configuration variable set to either 'ignore' or 'warn'.
To /home/jaewon/work/study/tool/git/remote_src/.
   fc2d23f..979521d  master -> master

위의 경고 메시지를 확인해 보니 정말 문제가 있었다.
우선 위의 경고 메시지는 2가지로서 하나는 현재 local 에서 어떤 branch 를 push 할 것이냐 하는 설정이고,
또 다른 하나는 현재 local의 branch로는 remote에 정상적으로 반영되어 보이지 않는다는 것이다.

먼저 remote에 반영 경고를 확인해 봤다.
아래처럼 local 과  remote 의 index에는 정상적으로 반영되었는데,

jaewon@jaewon-laptop:~/work/study/tool/git/local_src$ git log
commit 979521d7978f7a26c989047bae7806466353ad61
Author: jaewon <jaewon@jaewon-laptop.(none)>
Date:   Fri Apr 23 02:44:44 2010 +0900
    2nd
commit fc2d23fb93c972c3f48a75f9bf7be7de6a5d5ea3
Author: jaewon <jaewon@jaewon-laptop.(none)>
Date:   Fri Apr 23 02:42:48 2010 +0900
    initial
jaewon@jaewon-laptop:~/work/study/tool/git/local_src$ cd ../remote_src/ ; git log
commit 979521d7978f7a26c989047bae7806466353ad61
Author: jaewon <jaewon@jaewon-laptop.(none)>
Date:   Fri Apr 23 02:44:44 2010 +0900
    2nd
commit fc2d23fb93c972c3f48a75f9bf7be7de6a5d5ea3
Author: jaewon <jaewon@jaewon-laptop.(none)>
Date:   Fri Apr 23 02:42:48 2010 +0900
    initial

remote의 1.txt 파일과 git diff 정보에는 변경 사항이 반영되지 않았다.

jaewon@jaewon-laptop:~/work/study/tool/git/remote_src$ cat ./1.txt
jaewon@jaewon-laptop:~/work/study/tool/git/remote_src$ git diff
jaewon@jaewon-laptop:~/work/study/tool/git/remote_src$

그런데 위의 경고 메시지처럼 git reset --hard 로써 현재 HEAD로 회기하였을 때 실제 1.txt 에 반영되었다.

jaewon@jaewon-laptop:~/work/study/tool/git/remote_src$ git reset --hard
HEAD is now at 979521d 2nd
jaewon@jaewon-laptop:~/work/study/tool/git/remote_src$ cat ./1.txt
local modification

경고 메시지를 직접 확인했듯이,
remote_src 디렉토리의 소스 파일을 그대로 이용하는 것은 문제가 있다.
그럼 어떻게 해야 할 것인가?

'Tool > git' 카테고리의 다른 글

git 알면 편한 기능  (0) 2010.11.13
git reference  (0) 2010.07.05
git staic build  (0) 2010.04.27
git init --bare 이용  (1) 2010.04.23
qgit  (0) 2010.04.20
Posted by neodelicious
|

qgit

Tool/git 2010. 4. 20. 23:55
개발 소스 코드 관리를 주로 git 를 통해 하고 있다.

그리고 관련 GUI Tool로서 git 메뉴얼에서 봤던 gitk를 사용하고 있었다.
그런데 오늘 어쩌다가 ubuntu apt-cache 에서 qgit라는 것을 찾았다.

gitk 에서도 되었는지 모르겠지만,
qgit에서는 git commit들 중에서 특정 파일을 수정한 git commit 만을 보여줄 수도 있고,
특정 문자열을 포함하는 patch가 있는 git commit 들을 검색할 수도 있다.

관련해서 gitg, giggle 등도 설치해 봤는데, qgit가 제일 기능과 UI가 좋은 거 같다.

'Tool > git' 카테고리의 다른 글

git 알면 편한 기능  (0) 2010.11.13
git reference  (0) 2010.07.05
git staic build  (0) 2010.04.27
git init --bare 이용  (1) 2010.04.23
git init --bare 발단  (0) 2010.04.23
Posted by neodelicious
|
현재 시각을 측정하는 손쉬운 방법은 gettimeofday()를 이용하는 것으로,
이때 struct timeval 구조체를 이용하게 된다.

<API>
int gettimeofday(struct timeval *tv, struct timezone *tz);

<example>
struct timeval tv;
if (!gettimeofday(&tv, NULL)) fprintf(stderr, "%s error at %d\n", __FUNCTION__, __LINE__);


그리고 /usr/include/sys/time.h 파일을 보면 다음과 같은 편리한 macro를 제공함을 알 수 있다.
__USE_BSD 가 언제 #define 되는지 모르겟지만 이용 할 수 있었다.
stuct timeval 에 sec 부분과 usec 부분으로 분리되어 있는데 아래 3개 macro는 유용할 것이다.
timercmp(a, b, CMP)
timeradd(a, b, result)
timersub(a, b, result)
예를 들어 현재 시각을 매번 측정하여 그 차이를 위의 timersub를 통해 손쉽게 계산할 수 있고,
그 차이를 timeradd를 통해 손쉽게 계속 더해갈 수 있다.

#ifdef __USE_BSD
/* Convenience macros for operations on timevals.
   NOTE: `timercmp' does not work for >= or <=.  */
# define timerisset(tvp)        ((tvp)->tv_sec || (tvp)->tv_usec)
# define timerclear(tvp)        ((tvp)->tv_sec = (tvp)->tv_usec = 0)
# define timercmp(a, b, CMP)                                                  \
  (((a)->tv_sec == (b)->tv_sec) ?                                             \
   ((a)->tv_usec CMP (b)->tv_usec) :                                          \
   ((a)->tv_sec CMP (b)->tv_sec))
# define timeradd(a, b, result)                                               \
  do {                                                                        \
    (result)->tv_sec = (a)->tv_sec + (b)->tv_sec;                             \
    (result)->tv_usec = (a)->tv_usec + (b)->tv_usec;                          \
    if ((result)->tv_usec >= 1000000)                                         \
      {                                                                       \
        ++(result)->tv_sec;                                                   \
        (result)->tv_usec -= 1000000;                                         \
      }                                                                       \
  } while (0)
# define timersub(a, b, result)                                               \
  do {                                                                        \
    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;                             \
    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;                          \
    if ((result)->tv_usec < 0) {                                              \
      --(result)->tv_sec;                                                     \
      (result)->tv_usec += 1000000;                                           \
    }                                                                         \
  } while (0)
#endif  /* BSD */

그런데 struct timeval 을 그대로 이용할 때는 불편할 때가 있다.
예를 들어 sec을 일부와 usec의 일부만을 출력하거나
다른 일반 int type으로 저장한 시간과 비교할 때가 그럴 수 있을 것이다.

(어디까지나 선택사항이지만) 이때는 struct timeval 을 long long 으로 변환해서 저장하는 것이 편하다.
아래와 같이 long long time 에 저장하는 것이다.
time = tv.tv_sec * 1000000LL + tv.tv_usec;

참고적으로 혹시 전환 과정에서 data 손실을 우려할 수 있으나 그렇지 않다.
long long type이 보통 8byte 이고, struct timeval의 tv_sec 과 tv_usec 이 각각 4byte 인데,
실제로는 tv_usec의 값은 최대 10^6 - 1 로서, 이는 2진수 값으로 20bit 이하이다.
따라서 20bit 인 2.5byte를 shift 하더라도 데이터 손실이 없는 것이다.

아래는 관련해서 테스트한 소스 코드이며,
struct timeval : 1270047284.534099
long long      : 1270047284534099
실행결과 바로 위와 같이 두 값이 같음을 알 수 있다.

#include <stdio.h>
#include <sys/time.h>

int main(int argc, char *argv[])
{
        struct timeval tv;
        long long time;

        if (gettimeofday(&tv, NULL)) fprintf(stderr, "%s error at %d\n", __FUNCTION__, __LINE__);
        time = tv.tv_sec * 1000000LL + tv.tv_usec;

        printf("struct timeval : %d.%-6d\n", (int)tv.tv_sec, (int)tv.tv_usec);
        printf("long long      : %lld\n", time);

        return 0;
}

'Lang, Tool, Env' 카테고리의 다른 글

Ubuntu /home 옮기기  (0) 2012.08.04
struct 내 flag용으로 쓸 1bit 크기 변수 사용하기  (0) 2010.05.09
IEEE Floating-Point Format  (1) 2009.09.13
chroot  (0) 2008.04.06
임베디드 기초 교육 정리  (0) 2007.08.26
Posted by neodelicious
|
<배경>

strace를 사용하고자 했는데, 어쩌다 xtrace가 있더라.
혹시 Xserver와 관련해서 뭔가 trace 하는가 했는데, 예감이 맞았다.


<결론>

결론부터 얘기하면, Xclient와 Xserver 사이의 X11 Protocol 상의 정보를 훔쳐볼 수 있다.

즉, Xlib을 사용하는 Xclient 프로그램 혹은 Xlib를 backend로 사용하는 GTK 프로그램 등의 프로그램의 소스를 보지 않아도 내부적으로 사용하는 Xlib API의 이름을 알 수 있다.

또한 해당 API를 통해 Xserver 와 주고받는 정보도 볼 수 있는데 어느 정도까지 제공해주는지는 확인해봐야 할 것 같다. 기본 Xlib API는 되는듯 한데, 다른 X extension상의  API는 대부분 어느 API인지 그 이름조차 안 나오는 것 같다. 그래도 특정 Xclient에서 어떤 Xlib API를 사용하는지 살펴보는 용도로는 사용할 수 있을 것 같다.

그밖에 옵션을 통해 시각을 출력할 수 있는데, 이를 통해 특정 Xclient 프로그램의 Xserver 이용 비중을 측정한다거나, 특정 Xlib API에 대한 이용 비중을 측정하는 것은 좀 무리가 있어 보인다.

정확하게 하려면 역시 Xserver 내에 logging 소스를 추가하고 이를 분석하는 게 정확할 것 같다.


<추가 사항>
  1. 다양한 옵션을 제공하는데, 이중 일부를 소개한다.
  2. -D [name] : 가상으로 사용할 display 값으로,  '-D :9' 처럼 쓰면 되고 기본 적으로 :9 로 되어 있다.
  3. -d [name] : 기본 Xserver의 display 값으로 안 쓰면 기본값을 사용한다.
  4. -k : 더 이상 Xclient 가 없어도 xtrace를 종료하지 않는다.
  5. -i : Xclient가 Xserver에 보내는 매 request를 보낼지 선택할 수 있다.
  6. -o [filename] : stdout 대신에 특정 파일에 출력한다.
  7. --timestamps : 매 정보에 대한 시각을 출력한다.
  8. --relative-timestamps : 매 정보에 대한 시각을 출력하되, 첫 연결을 기준으로 상대적 시각을 출력한다.

<참고 사항>

opensource 로 소스를 받을 수 있고,
ubuntu에서는 apt-get install xtrace 로 설치할 수 있다.
http://xtrace.alioth.debian.org/ 를 참고해서 자세한 정보를 얻을 수 있는데, 설치 후 man xtrace 로 옵션에 대한 정보를 볼 수 있다.


<추력 정보 설명>

아래  <사용 예>에서 방법을 보도록 하고, 바로 아래 xtrace 의 출력 결과 예를 살펴 보자.

0.  1 000:<:0001: 20: Request(98): QueryExtension  name='BIG-REQUESTS'
0.  1 000:>:0001:32: Reply to QueryExtension: present=true(0x01) major-opcode=142 first-event=0 first-error=0


좌측 순으로 시각, 방향(<는 Xserver로, > Xclient로), data size(?) 이고, 그 이후는 해당 정보이다.
X11 protocol에는 Xclient가 보내는 request와 Xserver가 보내는 reply, error, event 가 있는데 이에 대한 정보를 보여준다. 특히 request는 어떤 request 인지 major, minor 번호와 해당 API 이름와 정보를 출력한다.

아래는 xtrace 참고 웹 페이지에서 가져온 것으로,
xtrace에서 keyboard extension에 대한 정보를 갖고 있지 않아서 152번 Major에 대한 request가 무엇인지 알 수 없어 'unknown'으로 보여주고 있다.

000:>:0x0004:32: Reply to BigReqEnable: maximum-request-length=1048575
000:<:0005: 20: Request(98): QueryExtension name='XKEYBOARD'
000:>:0x0005:32: Reply to QueryExtension: present=true(0x01) major-opcode=152 first-event=111 first-error=178
000:<:0006: 8: Request(152): unknown


<사용 예>

$ xtrace --relative-timestamps &
No display name to create specified, trying :9
$ DISPLAY=:9 xdpyinfo
Got connection from unknown(local)
0.  0 000:<: am lsb-first want 11:0 authorising with 'MIT-MAGIC-COOKIE-1' of length 16
0.  1 000:>: Success, version is 11:0-52704.
0.  1 000:<:0001: 20: Request(98): QueryExtension  name='BIG-REQUESTS'
0.  1 000:>:0001:32: Reply to QueryExtension: present=true(0x01) major-opcode=142 first-event=0 first-error=0
0.  1 000:<:0002:  4: BIG-REQUESTS-Request(142,0): BigReqEnable
0.  2 000:>:0002:32: Reply to BigReqEnable: maximum-request-length=4194303
0.  2 000:<:0003: 20: Request(55): CreateGC cid=0x04a00000 drawable=0x000000fa  values={background=0x00ffffff}
0.  2 000:<:0004: 24: Request(20): GetProperty delete=false(0x00) window=0x000000fa property=0x17("RESOURCE_MANAGER") type=0x1f("STRING") long-offset=0x00000000 long-length=0x05f5e100
0.  2 000:>:0004:208: Reply to GetProperty:  type=0x1f("STRING") bytes-after=0x00000000   data='Xcursor.size:\t18\nXcursor.theme:\tHuman\nXcursor.theme_core:\ttrue\nXft.antialias:\t1\nXft.dpi:\t96\nXft.hinting:\t1\nXft.hintstyle:\thintslight\nXft.lcdfilter:\tlcddefault\nXft.rgba:\trgb\n'
0.  2 000:<:0005: 20: Request(98): QueryExtension  name='XKEYBOARD'
0.  3 000:>:0005:32: Reply to QueryExtension: present=true(0x01) major-opcode=144 first-event=96 first-error=153
0.  3 000:<:0006:  8: XKEYBOARD-Request(144,0): UseExtension major=1 minor=0
0.  3 000:>:0006:32: Reply to UseExtension: major=1 minor=0
0.  4 000:<:0007:  4: Request(43): GetInputFocus
0.  4 000:>:0007:32: Reply to GetInputFocus: revert-to=Parent(0x02) focus=0x04600005
0.  4 000:<:0008:  4: Request(99): ListExtensions
0.  4 000:>:0008:300: Reply to ListExtensions: number of STRs in names=0x1b names={ s='MIT-SCREEN-SAVER'},{ s='XFree86-VidModeExtension'},{ s='XFree86-DGA'},{ s='DPMS'},{ s='XVideo'},{ s='X-Resource'},{ s='DOUBLE-BUFFER'},{ s='RECORD'},{ s='DRI2'},{ s='Generic Event Extension'},{ s='SHAPE'},{ s='MIT-SHM'},{ s='XInputExtension'},{ s='XTEST'},{ s='BIG-REQUESTS'},{ s='SYNC'},{ s='XKEYBOARD'},{ s='XC-MISC'},{ s='SECURITY'},{ s='XFIXES'},{ s='RENDER'},{ s='RANDR'},{ s='XINERAMA'},{ s='Composite'},{ s='DAMAGE'},{ s='GLX'},{ s='SGI-GLX'},{ s=''},{ s=''};
0.  6 000:<:0009: 12: Request(97): QueryBestSize class=Cursor(0x00) drawable=0x000000fa width=65535 height=65535
0.  6 000:>:0009:32: Reply to QueryBestSize: width=64 height=64
0. 59 000:<:000a:  8: Request(60): FreeGC gc=0x04a00000
0. 59 000:<:000b:  4: Request(43): GetInputFocus
0. 59 000:>:000b:32: Reply to GetInputFocus: revert-to=Parent(0x02) focus=0x04600005

Posted by neodelicious
|