64비트 MSBuild로 64비트 빌드하기

  • Post author:
  • Post category:
  • Post comments:0 Comments
  • Post last modified:January 22, 2020

왜 64비트 MSBuild인가?

64비트 운영체제엔 두 개의 MSBuild가 있다. C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\msbuild.exeC:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\msbuild.exe인데, 자세히 보면 64란 숫자가 붙어있다. 한 마디로 말해 32비트용 MSBuild이냐, 64비트용 MSBuild이냐라는 차이가 있다.

논의를 좀더 진행하기에 앞서 비주얼 스튜디오 2005를 잠시 살펴보자. Visual Studio 2005 x64란 키워드로 구글링해봐야 64비트용 비주얼 스튜디오를 찾을 수는 없다. 32비트용 비주얼 스튜디오만 있는데, 32비트용이라고 해도 32비트와 64비트 컴파일 모두 지원한다.

이와 마찬가지로 32비트용 MSBuild를 사용해도 64비트 VC++ 프로젝트를 빌드하는 데 아무런 문제도 없다. 그렇다면 왜 64비트용을 굳이 써야 하는가?

32비트용 MSBuild로 64비트 VC 프로젝트와 64비트 .NET 프로젝트를 함께 빌드하려고 하면 문제가 발생한다. VC 프로젝트는 빌드가 되지만, 닷넷 프로젝트는 빌드가 안 된다. 곰곰히 생각해보면 뭔가 이상하다. 32비트용인 비주얼 스튜디오로 64비트 닷넷 프로젝트를 빌드할 수 있는데, MSBuild만 왜 난리를 치는가? 고민해봤지만 결국 원인을 파악하지 못했다. 환경 설정을 바꿔가며 테스트해봤지만 결과는 같았다.

결론 1. 64비트 빌드를 하려면 64비트 MSBuild를 사용하라.

64비트 MSBuild에 문제는 없는가?

64비트용 MSBuild로 VC 프로젝트를 빌드하다가 괴상한 오류와 마주쳤다.

C2259: "cannot instantiate abstract class"

이 오류는 Visual Studio 2005의 버그였는데, 서비스 팩 1에서 고쳐졌다. 하지만 64비트용 vcbuild.exe는 깜박 잊고 손보지 않았는지, 이 오류 메시지가 출력됐다. 역시나 환경 설정을 잘못했나 살펴봤지만, 그다지 이상한 점이 눈에 띄지는 않았다.

다행히 이 오류는 컴파일러 파서가 삽질할 때 나기 때문에 원래 소스 코드에 의미상 아무런 차이도 없는 캐스팅을 붙여줌으로써 문제를 해결했다. 물론 32비트 빌드할 때와 64비트 빌드할 때, 서로 다른 버전의 컴파일러를 쓴다는 점이 마음에 걸리긴 한다.

결론 2. 32비트 vcbuild.exe에 적용된 핫픽스가 64비트 vcbuild에는 적용 안 됐다.

환경 설정 불러내기

비주얼 스튜디오 2005가 깔려 있다고 가정하고 이야기를 진행하자. 보통 32비트 빌드를 할 때는 이런 식으로 배치 파일을 만든다.

call "%VS80COMNTOOLS%"\vsvars32.bat
msbuild buildall.msbuild /t:Build

64비트 빌드할 때는 이렇게 하면 된다.

@echo off
call "C:\Program Files (x86)\Microsoft Visual Studio 8\VC\vcvarsall.bat" x64
call "C:\Program Files\Microsoft.NET\SDK\v2.0 64bit\Bin\sdkvars.bat"
"C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\msbuild.exe" /t:Build

CruiseControl .NET 연동하기

<msbuild>
    <executable>C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\msbuild.exe</executable>
    <workingDirectory>C:\src\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>

일반적인 CCNet.config 설정은 위와 같다. 하지만 환경 설정 값을 불러내야 하기 때문에 곧바로 msbuild.exe를 호출해선 안 된다. 우선 MsBuild_x64_ForCI.bat 란 배치 파일을 만든다.

@echo off
call "C:\Program Files (x86)\Microsoft Visual Studio 8\VC\vcvarsall.bat" x64
call "C:\Program Files\Microsoft.NET\SDK\v2.0 64bit\Bin\sdkvars.bat" >>
"C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\msbuild.exe" %*

그러고 나서 CCNet.config 파일을 수정해주면 된다.

<msbuild>
    <executable>MsBuild_x64_ForCI.bat</executable>
    <workingDirectory>C:\src\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>

개선하기

여기서 모든 게 끝났다고 생각하면 오산이다. CruiseControl .NET 빌드 파일을 보면 뭐가 문제인지 알 수 있다.

<cruisecontrol>
<msbuild startTime="10/30/2007 16:43:39" elapsedTime="00:00:12" success="true">
  <project name="Build" file="C:\src\build.msbuild" success="true">
    <project name="Rebuild" file="C:\src\Projects.sln" success="true">
        <message level="high"><![CDATA[MockClientForMaster -> C:\src\cuckoo-x64-release\server\src\TestServices\MockClientForMaster\bin\x64\Release\MockClientForMaster.exe]]></message>
    </project>
  </project>
</msbuild>Setting environment for using Microsoft Visual Studio 2005 x64 tools.
Setting environment to use Microsoft .NET Framework v2.0 SDK tools.
For a list of SDK tools, see the 'StartTools.htm' file in the bin folder.
</cruisecontrol>

환경 설정을 불러내면서 콘솔에 메시지가 출력되는 바람에 CCNet 로그가 엉망이 되어 버렸다. 이 문제는 MsBuild_x64_ForCI.bat 배치 파일을 조금만 손보면 해결할 수 있다.

@echo off
call "C:\Program Files (x86)\Microsoft Visual Studio 8\VC\vcvarsall.bat" x64
> _temp.txt
call "C:\Program Files\Microsoft.NET\SDK\v2.0 64bit\Bin\sdkvars.bat" >> _temp.txt
"C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\msbuild.exe" %*

콘솔 출력을 텍스트 파일로 리다이렉트시켰다. 이로써 모든 게 끝났다.

새로운 정보

2007.11.08. 64비트 빌드하다가 괴상한 오류 메시지와 마주쳤다.

error C1900: Il mismatch between ‘P1’ version ‘20060201’ and ‘P2’ version ‘20050411’

구글링해보니 경로 설정이 꼬여서 빌드 도구(컴파일러나 링커)가 엉뚱한 DLL을 불러내서 발생한 문제 같다. MsBuild_x64_ForCI.bat 배치 파일에 환경 변수를 불러내는데, 사실 이렇게 설정한 값이 비주얼 스튜디오가 쓰는 환경 변수와 일치하지 않기 때문에 이런 문제가 생길 수 있다는 생각은 진작에 했었다. 다만, 환경 변수를 하나하나 설정해주기 귀찮아서 가장 쉬운 길을 찾았던 것인데, 역시나 머피의 법칙은 이번에도 빗나가지 않았다.

비주얼 스튜디오에서 [tools-options-projects and solutions-vc++ project settings dialog] 메뉴를 찾으면 show environment in build log 옵션이 있다. 이 옵션을 켜고 빌드하면 비주얼 스튜디오가 사용하는 환경 변수 값을 알 수 있다. 이제 배치 파일을 살짝 고치면 재빨리 임시 조치할 수가 있다.

@echo off
SET PATH_SAVED=%PATH %gt; _temp.txt
call "C:\Program Files (x86)\Microsoft Visual Studio 8\VC\vcvarsall.bat" x64
>> _temp.txt
call "C:\Program Files\Microsoft.NET\SDK\v2.0 64bit\Bin\sdkvars.bat" >> _temp.txt
SET PATH='비주얼 스튜디오 빌드 로그에서 찾아낸 경로';%PATH% >> _temp.txt
"C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\msbuild.exe" %*
SET PATH=PATH_SAVED >> _temp.txt
SET PATH_SAVED=>> _temp.txt

물론 어디까지나 임시 조치일 뿐이다. 여력이 될 때 빌드 로그를 보고 제대로 된 환경 설정 값을 넣어줄 생각이다.

참고로 이 코드에는 임시 조치성 코드 뿐만 아니라 배치 파일 실행 전과 실행 후에 환경 변수 값이 달라지지 않게 해주는 코드도 추가됐다. SET PATH 명령 부분은 특히 주의해야 하는데, 공백 하나라도 틀렸다간 제대로 동작 안 할지도 모른다.

Author Details
Kubernetes, DevSecOps, AWS, 클라우드 보안, 클라우드 비용관리, SaaS 의 활용과 내재화 등 소프트웨어 개발 전반에 도움이 필요하다면 도움을 요청하세요. 지인이라면 가볍게 도와드리겠습니다. 전문적인 도움이 필요하다면 저의 현업에 방해가 되지 않는 선에서 협의가능합니다.
0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments