페이지

2011년 1월 25일 화요일

Quickbuild proof build

Quickbuild 3.0 대에 보면 proof build라는 기능이 있다. 변경된 코드를 체크인 하기전에 build grid에서 빌드해서 일정 조건-빌드 성공 혹은 테스트까지 성공-을 만족하면 서브밋되게 하는 기능이 되겠다.

빌드에러는 작은 규모의 프로젝트에서는 뭐 그리 문제가 될게 있나 쉽겠지만 큰 규모의 소프트웨어를 개발할때는 충분히 문제가 될 수 있다. 몇백명의 개발자들이 하루에 한번 이상 체크인을 한다고 하면 여러 디펜던시 혹은 실수로 빌드에러를 유발할 수 있기 때문이다. 그래서 CI에서 계속 빌드에러가 나는 현상이 반복되고 장기화 될때 proof build를 적용하는 것도 한 방법이 될 수 있다.

실제 우리팀의 경우도 빌드에러가 좀처럼 잡기 힘든 것이 되어버려서 이번에 이것을 도입하게 되었다.

how to 는 이미 user guide에 잘 나와 있으니 여기서 별도로 설명은 안해도 될것 같고 어떻게 proof build가 이루어지는 그 흐름을 보면 도움이 된다.

  1. 로컬에서 변경한 파일(델타)들을 build agent로 전달. 개발자가 설치한 User Agent가 이기능을 한다.

  2. build agent에서는 latest sync후 델타를 적용 빌드를 한후 그 결과를 User Agent에게 전달한다.

  3. 성공이면 user agent에서 델타를 submit한다.

  4. 실패면 피드백을 준후 submit하지 않는다.

2011년 1월 5일 수요일

emacs server mode in Windows

Emacs wiki에는 복잡하게 설명되어 있지만 실제로 최신버전의 이맥스-GNU Emacs 23.2.1-에서는 server mode는 별도의 해킹없이 동작한다. 그러니 괜히 시간 낭비 하지 마시라고..
server mode란 것은 하나의 emacs 프로그램이 오직 하나의 instance만 뜨게 제한 하는 방법이다. server mode가 아닐때는 모두 각각의 instance로 실행이 된다.
실제로 파일 하나 오픈했는데 새로운 emacs window가 떠버리면 더 불편할다. 초기화 하는데 시간이 걸리고 버퍼등이 공유가 되지 않기때문이다. 그래서 대부분  server mode를 default로 사용한다.
.emacs에
(server-start)
를 추가해 주고 최초 실행시는 runemacs.exe를 사용하고 이후에는 emacsclientw.exe FILE_NAME 이런식으로 실행하면 된다.
또 emacsclientw.exe로 오픈된 버퍼는 C-c #으로 종료하면 된다. 물론 C-x k 로 해도 되지만 client를 죽일 것인지 한번더 물어본다. 나의 경우는 이 컨펌 메세지를 없애기 위해서 (server-start) 의 아래 줄에,꼭 아래 줄이어야 함, 아래 lisp코드를 적어주면 그냥 깨끗하게 죽는다.
(remove-hook 'kill-buffer-query-functions 'server-kill-buffer-query-function)

2010년 12월 27일 월요일

find.exe conflicts on Windows emacs

emacs를 사용할때 내부적으로 unix 툴인 find.exe를 사용하는데 이것은 Windows에 기본으로 내장되어 있는 find.exe프로그램과 이름이 같다. 따라서 emacs에서 unix의 find.exe를 call하고 싶어도 할 방법이 없다.

이것에 대한 해결책은 다음과 같다. 간단한 솔루션이지만 정말 많은 시간을 소비했다. --;;

Copy grep.exe and find.exe to Emacs’ own bin directory

2010년 12월 21일 화요일

Quickbuild script examples

Quickbuild를 잘~ 사용하려면 built-in script(OGNL)를 많이 사용해야 한다. script reference가 있음에도 친절한 수준은 아니라서 reference만 보고 하기에는 시간 낭비가 만만치 않다. 그래서 내가 사용했던 script snippet을 공유하면 도움이 되지 않을까 하는 생각에서 정리해 본다.

to use Quickbuild effectively, you should know how to use built-in script(OGNL). Though there is complete script reference, it's not easy to use it at first time. so It would be helpful for Quickbuild newbie to share these script snippet.


based on Quickbuild V3.x
+ Getting workspace directory of 'root/dev' on specific node.
${system.getConfigurationManager().get("root/dev").getWorkspaceDir()}
or
${system.getConfiguration("root/dev").getWorkspaceDir()}

+ Getting revision of last successful build of 'root/dev'
${system.getConfiguration("root/dev").getLatestSuccessfulBuild().getRepository("repo").getRevision()}

If TXT variable is equal to node's attribute value of 'CAP_GCC' returns true. otherwise returns false. This can be used at 'node match condition'.
node.getAttribute("CAP_GCC").equals("${vars.get("TXT")}")

check if this node is Windows OS
grid.getNode(params.get("nodes")).getAttribute("WRAPPER_OS").equals("windows")

+ return true if all specified step is successful
steps.get("master>sync").isSuccessful()&&steps.get("master>sdk").isSuccessful()&&steps.get("master>publish").isSuccessful()
+ select a build agent which doesn't have any job. this can be used at 'node match condition'
node.isBuildAgent() && (node.getJobCount()==0)
+ previous step is successful and check specific variable
current.getPreviousSibling().isSuccessful()&&vars.get("isPrevent").value=="no" 
+ add -c option when clean option checked
${vars.getValue("clean")=="yes"?"-c":""}


2010년 12월 6일 월요일

link again with another link option in cmake build tree

cmake를 사용하다 보면 다른 link option으로 같은 바이너리를 여러벌 만들어야 할 경우가 생길 수 있다. 손쉽게는 debug 혹은 release와 같이 configuration을 나눠서 여러번 빌드해서 원하는 것을 이룰 수 있다. 하지만 rebuild 없이 현재까지 빌드된 object파일들을 가지고 할 수 있는 방법이 있다면 더 효율적일 것이다.

그래서 고민한 끝에 얻은 결론은 link.txt를 이용하는 것이었다.  전체 적인 sequence는 :

  • "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${this_target}.dir/link.txt" 에 link command가 들어가 있다. 역시나 link할때 cmake -E로 이 파일을 이용해서 링크를 하고 있다.

  • 따라서 FILE(READ ...)로 link.txt을 read한 다음 내 입맛에 맞게 link option을 수정한다. STRING(REPLACE ...) 혹은 STRING계열 함수를 이용하면 쉽게 요리가 가능하다

  • 새로운 link command를 link2.txt로 저장한다.

  • 그 후 cmake -E로 해당 link command를 불러주면 된다.


나의 경우 한번은 --no_deubg 옵션이 들어가게 링크하고 또 다른 한번은 이 옵션 없이 link를 해야  할 필요가 있었다. 이것을 cmake macro로 단순화 하면 다음과 같다.

새삼 느끼는 거지만 cmake 참 좋다. ㅎ

[sourcecode]
MACRO(LINK_WITH_ANOTHER_OPTION _target)
FILE(READ "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_target}.dir/link.txt" _link)
STRING(REPLACE "--no_debug" "" _link2 ${_link})
FILE(WRITE "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_target}.dir/link2.txt" ${_link2})
# message(status ${_link})
# message(status ${_link2})
ADD_CUSTOM_COMMAND(TARGET ${_target}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E cmake_link_script "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${this_target}.dir/link2.txt" --verbose=$(VERBOSE)
COMMENT "link with different option ${_target}"
)
ENDMACRO(LINK_WITH_ANOTHER_OPTION)
[/sourcecode]

2010년 12월 3일 금요일

SidebySide(WinSxS) problem

Windows 계열에서 Dll hell문제를 해결하기 위한 하나의 방법으로 고안한것이 Side-by-Side tech 이다. dll 생성시 manifest파일을 만들고 그곳에 사용하는 버전의 crt버전을 적고 런타임시에 그 crt를 사용하는 기술이다.

최근에 겪었던 문제가 좀 복잡한 케이스 인데 상황을 설명하면 이렇다. Win7환경에서 Egg.dll을 빌드하자 아래와 같은 manifest.xml이 생성되었다.

[sourcecode language="xml"]
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC80.DebugCRT" version="8.0.50727.4053" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC80.DebugCRT" version="8.0.50727.762" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
</dependentAssembly>
</dependency>
</assembly>
[/sourcecode]

우선 위 manifest에서 이상한 것이 debugCRT가 2개라는 것이다.

  1. 8.0.50727.4053

  2. 8.0.50727.762


더구나 1번의 8.0.50727.4053버전은 내컴에 존재하지도 않는다. 내 컴에서 빌드를 했음에도 4053이 있다!  그래서 실행하면 side by side error를 낸다.

이것은 무엇을 의미하느냐 Egg.dll이 link하는 3rt party lib중의 하나가 분명 4053버전으로 컴파일이 되었단 이야기다.  그래서 결과적으로 4053과 762버전 둘다 manifest에 들어가게 된것이고. 빌드는 이렇게 되었으나 runtime시에 해당 dll을 찾을 수 없다고 에러가 뜬다. 더구나 4053버전은 Win7을 support하지 않는다.

여기까지 왜 이런 문제가 생겼는지 까지는 이해가 되었다. 그럼 해결하는 방법은 msdn forum에 언급되었다. 발췌하면 아래와 같다.
The fact that both 762 and 4053 are listed in the same manifest is a big red flag.  This should never happen.  The only way it could possibly happen is that you are still linking to static libraries that have not been rebuilt to refer to 762 instead of 4053.  You should rebuild those static libraries.

If it's not possible to rebuild those static libraries i.e. they are third party libraries that you don't have access to, I suggest you follow instructions in the link below (a blog entry that I wrote over a year ago) to make your manifests show 762 only, not 4053.  Don't worry, this won't make your app less secure, if the appropriate 4053 DLLs have been installed on the user's machine, they'll still be loaded, through the power of policy redirection).  see:

http://tedwvc.wordpress.com/2009/08/10/avoiding-problems-with-vc2005-sp1-security-update-kb971090/

이와 별개로 manifest를 생성하지 않는것도 한 방법이다. 다소 risky 하긴 하지만..

2010년 11월 29일 월요일

Extracting VS2005 sln dependencies information

I have 220+ projects in my VS2005 solution file. My task is to create a new solution file by cutting some features. New one have 160+ projects and i need to set up dependencies between the projects.

To simplify these process i made Powershell script printing dependencies information. It worked as i expected. It will certainly ease your setting dependency work.

this script prints something like this:

projectA: projectB, base
projectB: base
...



Save the following script as Extract-VS2005Dependency.ps1
[sourcecode language="powershell"]
# usage
# powershell .Extract-VS2005Dependency -slnFile c:my.sln
param(
[string] $slnFile = $(throw 'need slnFile path')
)

$projects = @{}
switch -regex -file $slnFile
{
"^Project.*= ""(w+)"",.*vcproj"", ""(.*)""" {
#$_ ;
$projects[$Matches[2]] = $Matches[1]
}

}
#$projects
#$projects.count

switch -regex -file $slnFile
{
"^Project.*= ""(w+)"",.*vcproj"", ""(.*)""" {
#$_ ;
$curProject = $Matches[1]
""
write-host "$($curProject):" -nonewline
}
"({[A-Fa-f0-9-]+}) = 1" {
# $_
# $Matches[1]
write-host $projects[$Matches[1]]"," -nonewline
}

}
[/sourcecode]