그 동안 빌드하는 데 시간이 오래 걸려서 여러 번 손을 봤지만, 근본적인 문제는 건드리지 않아서 그리 효과적인 조치를 취했다고는 할 수 없었다. 빌드 서버를 도입하기 전에 각자 애플리케이션을 하나씩 맡아서 작업했기 때문에 프로젝트 구조 자체가 효율적이지 않았다고 할 수 있다. 애플리케이션마다 이런 식으로 솔루션 파일이 구성되어 있었다.
App1.sln = Shared.vcproj + App1.vcproj App2.sln = Shared.vcproj + App2.vcproj App3.sln = Shared.vcproj + App3.vcproj
이런 식으로 구성되어 있다보니 Rebuild할 때 Shared 프로젝트를 여러 번 빌드하는 문제가 발생했다.
첫 시도 – 실패
전체 빌드 시간의 절반 이상을 공유 라이브러리가 먹어버리는 문제를 해결하려고 빌드 스크립트를 고쳤다.
<ItemGroup> <SharedProjectReferences Include="SharedAgent.vcproj" /> <AppProjectReferences Include="App1.vcproj" /> <AppProjectReferences Include="App2.vcproj" /> <AppProjectReferences Include="App3.vcproj" /> </ItemGroup> <Target Name="Build"> <MSBuild Projects = "@(SharedProjectReferences)" Properties = "Configuration=Debug;Platform=Win32" Targets = "Rebuild"> </MSBuild> <MSBuild Projects = "@(AppProjectReferences)" Properties = "Configuration=Debug;Platform=Win32" Targets = "Rebuild"> </MSBuild> </Target>
하지만 이 방식은 실패했다. 솔루션 파일 Sln엔 SolutionDir 같은 프로젝트 매크로가 들어 있는데, 이렇게 프로젝트를 분리해놓으니 매크로를 쓴 설정값이 적용되지 않았다.
다시 시도 – 성공
고민 끝에 공유 라이브러리를 쓰는 모든 프로젝트를 하나의 솔루션 파일에 묶기로 결정했다. 이런 식이다.
Projects.sln = Shared.vcproj + App1.vcproj + App2.vcproj + App3.vcproj
새 솔루션 파일을 구성하는 일은 비교적 쉬웠다. 프로젝트를 추가한 후 프로젝트 의존성만 설정해주면 됐다. 이렇게 설정하고 나니 프로젝트 매크로도 제대로 작동했고 큰 문제는 없는 듯 했다.
하지만 CruiseControl .NET 웹 대시보드에서 문제가 발생했다. 솔루션 파일 하나로 묶다 보니 로그가 이상하게 나왔다. Improved MSBuild Logger를 쓰는데 종전엔 로그가 이런 식으로 출력됐다.
Project: App1.Sln 오류 메시지... Project: App2.Sln 오류 메시지... Project: App3.Sln 오류 메시지...
프로젝트 별로 오류 메시지를 볼 수 있어 편했는데, 하나의 솔루션 파일을 쓰다 보니 오류 메시지가 하나로 뭉쳐서 출력됐다. 이를 해결하려고 MSBuild용 Logger의 소스 코드를 수정하는 건 지나친 반응이었고, 좀더 쉬운 해결책을 찾아봤다.
우선 Improved MSBuild Logger 대신 MSBduil XmlLogger를 사용하고, CCNet.config 파일을 수정해서 로그를 최소한(quiet)으로 남기는 대신 좀더 많이(minimal) 남기게 고쳤다. minimal로 설정하면 오류 메시지 뿐만 아니라 중요도가 높은(high) 메시지(Message)도 로그로 남긴다는 점을 활용했다.
<msbuild> <executable>C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\msbuild.exe</executable> <workingDirectory>C:\src\</workingDirectory> <projectFile>build.msbuild</projectFile> <buildArgs>/noconsolelogger /p:Configuration=Debug /v:m</buildArgs> <targets>Build</targets> <timeout>12000</timeout> <logger>C:\Program Files (x86)\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MSBuild.dll</logger> </msbuild>
이렇게 고치고 나니 쓸만한 로그를 볼 수 있었다.
Project "C:\src\build.msbuild" (Build target(s)): Project "C:\src\Projects.sln" (Build target(s)): VCBuild.exe C:\src\Shared\Shared.vcproj "Debug|Win32" 오류 메시지... VCBuild.exe C:\src\App1\App1.vcproj "Debug|Win32" 오류 메시지... VCBuild.exe C:\src\App2\App2.vcproj "Debug|Win32" 오류 메시지... VCBuild.exe C:\src\App3\App3.vcproj "Debug|Win32" 오류 메시지... Done building project "Projects.sln" -- FAILED. Done building project "build.msbuild" -- FAILED.