Visual C++을 위한 지속적인 통합 빌드 서버

그 동안 R&D 센터에서 고민만 해오던 빌드 서버를 내가 프로젝트에 본격적으로 참여하기 전에 설치하기로 마음 먹고 어제, 오늘 대공사를 치렀다. 축복받은 관리되는 환경(.NET Framework나 Java 같은)과 달리 네이티브 C++의 세계는 항상 어둠이 가득했다. 이 참에 손전등이라도 달아줄 생각이었다. 결국 인프라스트럭처가 잘 갖춰져 있어도 사람들이 적극적으로 써야 그 값어치를 다 하는 거지만, 나 혼자 생각으로 뚝딱 만든 게 아니니 잘 되리라 생각한다. R&D 센터에는 믿음직한 사람이 가득하니까.

웹 서버 설치

상황: Windows Server 2003에 Microsoft SQL Server 2005가 설치되어 있다. IIS 웹 서버는 설치 하지 않았다. CruiseControl .NET의 대시보드(Dashboard)를 설치하려면 IIS 웹 서버부터 설치해야 한다.

  1. IIS 웹 서버를 설치한다.

    [Control Panel – Add or Remove Programs – Add/Remove Windows Components – Application Server – Internet Information Services]
  2. 대시보드(http://localhost/ccnet/)에 접속하니 오류 메시지가 뜬다.

    If IIS was installed after the .NET framework, you will need to either run aspnet_regiis.exe or open IIS manager, right-click the ccnet website, select properties and then the ASP.NET tab. Make sure the ASP.NET version has something displayed in the dropdown (eg. .NET 2.0, 2.0.50727) and click OK.

    이렇게 해결했다.

    1. ASP.NET 설치한다.

      C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\aspnet_regiis.exe -I

    2. [IIS 관리자 – Web Service Extensions]에서 ASP.NET 활성화시킨다.

    3. IIS 관리자에서 ASP.NET 버전 선택해준다. 여기선 2.0을 골랐다.

소스 코드 관리 시스템 설치

CruiseControl .NET이 서브버전 저장소에 접근하려면 svn.exe가 필요하다. 그러니 윈도우용 서브버전을 설치했다. 물론 시스템 환경변수에 서브버전 바이너리 폴더가 등록되어 있는지 확인했다.

CruiseControl .NET 돌려보기

일단 서버에 깔려 있는 VS 2005로 컴파일하기로 한다. (원래는 SDK를 따로 다운로드 받아서, 그 안에 있는 컴파일러를 쓰는 게 정석이다.) 빌드 스크립트는 나중에 도입하고, 일단 CruiseControl .NET 설정 파일(ccnet.config)만 쓰자.

<cruisecontrol>
  <project>
   <name>Project Name</name>
    <webURL>http://domain/ccnet-</webURL>
	<workingDirectory>c:\src\project_name</workingDirectory>
    <triggers>
    	<intervalTrigger seconds="60"/>
    </triggers>
    <modificationDelaySeconds>2</modificationDelaySeconds>
    <sourcecontrol type="svn">
      <trunkUrl>http://domain/svn/project_name/trunk</trunkUrl>
	  <username>username</username>
	  <password>password</password>
    </sourcecontrol>
    <tasks>
		<devenv>
			<solutionfile>C:\src\project_name\vs2005_solution.sln</solutionfile>
			<configuration>Debug</configuration>
			<buildtype>Build</buildtype>
			<executable>C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\devenv.exe</executable>
		</devenv>
    </tasks>
  </project>
</cruisecontrol>

일단 빌드 잘 되고, 대시보드에 결과가 잘 나온다. CCTray 역시 훌륭히 작동하는 걸 확인했다.

빌드 스크립트는 보류한다.

NAnt를 써서 좀 더 복잡한 빌드 작업을 해 볼 때이다. 하지만 NAnt의 최신 출시 버전이 1년 전에 나온 거라 께름칙하다. Visual Studio 2005의 솔루션 파일(*.sln)을 지원 못하는 문제도 여전하고 일단 NAnt의 도입은 보류한다. 잠깐 MSBuild를 사용해볼까 고민하다가 관두기로 한다. 당장은 CruiseControl .NET을 돌아가게 만드는 일에 집중해야 한다. 빌드 스크립트가 제공하는 고급 기능은 추후에 요구 사항이 생기면 도입하자.

단위 테스트 라이브러리 선정

VC++ 단위 테스트로는 UnitTest++을 사용하기로 한다. 처음엔 CppUnit을 도입할까 했지만, 곧 생각을 바꿨다. 예전 기억을 되살려보면 CppUnit은 너무 불편하다. 세팅하고 테스트하는 과정이 무척 까다롭기 때문에 결국 테스트를 하는 사람이 없어지게 된다. 그래서 Boost Library의 단위 테스트 기능이나 여러 대안을 모색해봤다. 그러고 나서 낙점한 것이 바로 UnitTest++이다.

CruiseControl .NET과 UnitTest++의 연동

UnitTest++ 사이트에서 제공하는 Money 프로젝트를 사용해 실험해보기로 한다. 이번엔 CruiseControl .NET의 설정 파일(ccnet.config) 뿐만 아니라 단위 테스트 프로젝트의 main() 함수도 고쳐야 한다.

<cruisecontrol>
	<project>
		<name>Money</name>
		<webURL>http://domain/ccnet</webURL>
		<workingDirectory>c:\src\Money</workingDirectory>
		<triggers>
			<intervalTrigger seconds="60"/>
		</triggers>
		<modificationDelaySeconds>2</modificationDelaySeconds>
		<sourcecontrol type="nullSourceControl">
		</sourcecontrol>
		<tasks>
			<devenv>
				<solutionfile>C:\src\Money\MoneyTestApp.sln</solutionfile>
				<configuration>Debug</configuration>
				<buildtype>Build</buildtype>
				<executable>C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\devenv.exe</executable>
			</devenv>
			<exec>
				<executable>MoneyTestApp.exe</executable>
				<buildArgs>C:\src\Results.xml</buildArgs>
				<baseDirectory>C:\src\Money\bin\</baseDirectory>
				<buildTimeoutSeconds>10</buildTimeoutSeconds>
			</exec>
		</tasks>
		<publishers>
			<merge>
				<files>
					<file>C:\src\Results.xml</file>
				</files>
			</merge>
			<xmllogger/>
			<statistics/>
		</publishers>
	</project>
</cruisecontrol>

테스트이니 소스 코드 관리 시스템은 쓰지 않는다고 치자. CruiseControl .NET이 UnitTest++을 지원하지 않기 때문에 exec 태스크를 사용해서 테스트를 실행시킨다. (CruiseControl .NET 사이트에 CppUnit을 연동하는 방법이 적혀 있는데, 이것을 참고 삼았다.) 이때 테스트 코드의 main() 함수는 다음과 같다. 출력 결과를 저장할 파일 이름이 인자로 들어오면 XML로 보고하고, 아니면 콘솔에 출력한다. 이렇게 하면 VS 2005와 연동하고 동시에 CruiseControl .NET과도 연동할 수 있다. (참고 자료. UnitTest++: Reports)

#include "UnitTest++.h"
#include "TestReporterStdout.h"
#include "XmlTestReporter.h"
#include <fstream>
#include <vector>
#include <string>

int main(int argc, char const ** argv)
{
	std::vector<std::string> args;
	if(argv)
	{
		while(*argv != NULL)
		{
			args.push_back(*argv);
			argv ++;
		}
	}

	if(args.size() == 1)
	{
		UnitTest::TestReporterStdout reporter;
		return UnitTest::RunAllTests(reporter, UnitTest::Test::GetTestList(), 0);
	}

	std::ofstream f(args[1].c_str());
	UnitTest::XmlTestReporter reporter(f);
	return UnitTest::RunAllTests(reporter, UnitTest::Test::GetTestList(), NULL, 0);
}

대시보드 손보기

CruiseControl .NET이 UnitTest++을 지원하지 않기 때문에 테스트 결과를 제대로 출력하려면 C:\Program Files\CruiseControl.NET\webdashboard\xsl\unittests.xml파일을 수정해야 한다. 250줄 가량 되기 때문에 파일은 첨부한다. 여기서 unittest__가 들어간 곳이 수정된 부분이다.

결과 보기

참고. 혹시나 싶어 프로젝트 이름은 스크린샷에서 지워버렸다.

CCTray

CCTray

CCTray가 빌드 오류, 정확히 말해 테스트 실패를 개발자에게 알려준다. 무슨 일인가 싶어 대시보드를 확인하러 간다.

대시보드

대시보드

Money 프로젝트의 테스트 코드 중 일부를 일부러 고쳐놓아서 오류가 발생한다. 문제가 된 프로젝트를 클릭해서 무슨 일인지 확인한다.

빌드 결과

빌드 결과

어떤 테스트가 문제인지 바로 확인할 수 있다.

참고 자료

소감. 우와, 이거 하느라 엄청 고생했는데, 글로 쓰고 나니 분량이 얼마 안 된다.

최 재훈

블로그, 페이스북, 트위터 고성능 서버 엔진, 데이터베이스, 지속적인 통합 등 다양한 주제에 관심이 많다.
Close Menu