C++ Boost 라이브러리를 Windows XP 에서 동작하도록 빌드하기
C++ , Boost , Windows-XP
안녕하세요~ 반갑습니다!
C++ 개발자 여러분~ boost 많이 쓰시죠?? 저도 boost 참 좋아합니다 ㅎㅎ
이렇게 좋은 boost 를 Windows XP/2003 환경에서 사용할 때는 그냥 일반적인 방법으로는 사용이 불가능한데요. 그래서 오늘은 Windows XP 환경에서 동작하도록 boost 를 빌드하는 방법에 대해서 알아보도록 하겠습니다!
참고로 제가 설명할 방법은 100% 완벽하게 검증된 방법은 아니며, 제가 조사/연구를 통해 알아낸 방법입니다. 따라서 문제가 있을 수도 있으므로 참고자료정도로만 사용해주시면 감사하겠습니다. 그리고 이 포스팅에서는 Visual C++ 2015 Update 3 를 사용한다고 가정하고 설명하겠습니다. 또한, 이 포스팅에서 말하는 Windows XP 는 정확히 말하면 XP Service Pack 3 를 뜻합니다.
1단계) 사용하려는 라이브러리가 XP 를 지원하는 지 확인한다.
일단 첫 번째 단계는 사용하려는 라이브러리가 Windows XP 를 지원하는 지 확인하는 과정입니다. 다행히도 Boost 의 대부분 라이브러리는 XP 환경에서 잘 돌아갈텐데, 경우에 따라서 XP에서는 기능이 제한되거나 오동작을 일으킬 수 도 있으니, 라이브러리가 XP 를 지원하는 지 여부를 검토할 필요성이 있습니다.
근데 아쉽게도 라이브러리들이 XP 를 지원하는 지 여부가 명백하게 정리된 글같은 건 없어 보입니다 ㅜㅜ 그리고, 각 라이브러리의 레퍼런스를 봐도 잘 안나오는 경우가 많죠. 결국, 부스트 커뮤니티 혹은 스택오버플로우의 글들을 뒤지거나 직접 질문을 해서 도움을 얻어야 합니다. 그리고 직접 라이브러리 내부 소스코드를 까서 XP 지원 여부를 파악해야 할 수도 있습니다. 그리고, 무엇보다 실제로 라이브러리를 사용하는 프로그램을 XP에서 동작시켜서 잘 동작하는지 직접 확인하는 과정도 꼭 필요합니다.
이 글은 2015년도에 부스트 커뮤니티에 올라왔던 Windows XP 지원 관련 설문인데 한번 읽어보셔도 좋을 것 같습니다.
XP 호환 여부를 파악할 때 신경쓸 점
그러면 이제 부터 XP 지원 여부를 파악할 때 신경쓸 점들에 대해 알아보겠습니다.
- XP 에서 지원하는 windows API 만을 사용해야만 합니다.
- 암시적 TLS 사용 금지
- XP 에서는 암시적 TLS에 관련된 known bug 가 있습니다. 따라서, 암시적 TLS 에 관련된 기능을 사용하면 안되고,
__declspec(thread)
, C++11thread_local
또한 사용하면 안됩니다. - 좀 더 자세한 내용을 알고 싶으신 분은 이 글을 참고하시면 좋을 것 같습니다.
- XP 에서는 암시적 TLS에 관련된 known bug 가 있습니다. 따라서, 암시적 TLS 에 관련된 기능을 사용하면 안되고,
- C++11 Magic Statics 에 의존하면 안됩니다.
- VC++2015 의 Magic Statics 구현은 내부적으로 암시적 TLS 를 사용합니다. 따라서, Magic Statics 에 의존하는 코드가 존재해서는 안됩니다.
- 좀 더 자세한 내용을 알고 싶으신 분은 이 글을 읽어보시는 걸 추천드립니다.
std::shared_mutex
를 사용하면 안됩니다.- VC++2015 표준라이브러리의
std::shared_mutex
구현은SRWLOCK
에 관련된 WinAPI 를 사용합니다. 근데,SRWLOCK
관련 WinAPI 는 Vista 이상에서 추가되었습니다. 따라서, XP 에서는std::shared_mutex
가 동작할 수 가 없습니다. 관련된 내용은 이 글을 참고하면 좋을 것 같습니다. - 뒤쪽에서 다룰 내용인데, 라이브러리를 빌드할 때,
_USING_V110_SDK71_
매크로를 정의하게 됩니다. 이 매크로를 정의하면 C++ 표준라이브러리에서std::shared_mutex
가 애초에 정의되지 않습니다.
- VC++2015 표준라이브러리의
2단계) Boost 가 XP 를 지원하도록 빌드하자.
일단, 이 포스팅에서는 빌드를 할 때 VC++2015 Update 3 를 사용할 것이므로, 이 것을 기반으로 설명을 드리도록 하겠습니다. 또한 기본적인 Boost 빌드 방법을 알고있다는 가정하에 설명을 진행하겠습니다.
VC++2015 Update 3 에서는 플랫폼 도구 집합으로 v140
(default), v140_xp
가 있습니다. XP 를 지원하는 소프트웨어를 개발할 때는 v140_xp
를 사용해야만 합니다.
Boost 를 빌드할 때는 b2.exe
를 사용하여 빌드를 수행하게 되는데 이때 toolset 으로 비주얼스튜디오의 버전을 넣어주게 됩니다. 예를 들어, VC++2015 의 경우 b2.exe --toolset=msvc-14.0 ...
와 같은 식이 되는데, 문제는 이것은 비주얼 스튜디오에서의 플랫폼 도구 집합으로 치면 v140
을 의미하고, v140_xp
를 의미하도록 명시하는 방법이 b2.exe
에는 없다는 것입니다.
따라서, v140
과 v140_xp
의 차이점을 일일히 알고서 b2.exe
의 다른 파라미터를 통해서 그 차이점을 적용시켜야만 합니다. v140
과 v140_xp
의 차이점에 대해서는 제가 과거에 작성했던 글을 참고하시길 바랍니다.
또한, Boost 가 XP 를 지원하도록 빌드하기 위해서는 여러가지 매크로들과 C++ Flag 를 설정해야만 합니다. 이제부터 그 매크로와 C++ Flag 를 하나씩 알아보겠습니다.
_WIN32_WINNT=0X0501
, _NTDDI_VERSION=0X05010300
매크로 정의
Windows 헤더 파일 (windows.h
등) 은 내부적으로 타겟 윈도우 버전을 의미하는 _WIN32_WINNT
, _NTDDI_VERSION
등 매크로들의 값을 바탕으로 조건부 선언을 하고있습니다. 예를 들면, Vista 에서 추가된 InitializeSRWLock
WinAPI 의 경우 _WIN32_WINNT >= 0x0600
일 경우에만 선언되도록 되어있습니다.
타겟 윈도우 버전을 의미하는 매크로들이 어떤 게 있고 어떤 값들이 가능한 지는 이 링크를 보면 잘 나와있습니다.
우리는 XP SP3 를 타겟으로 해야하므로, _WIN32_WINNT
는 0x0501, _NTDDI_VERSION
는 0x05010300 으로 정의해야합니다.
BOOST_USE_WINAPI_VERSION=0X0501
, BOOST_USE_NTDDI_VERSION=0X05010300
매크로 정의
이 두 매크로가 어떤 역할을 하는 지에 대해서는 이 링크를 참고하시길 바랍니다. 이 링크에 설명된 내용에 따르면, BOOST_USE_WINAPI_VERSION
, BOOST_USE_NTDDI_VERSION
가 정의되어 있지 않으면 기본적으로 _WIN32_WINNT
, _NTDDI_VERSION
의 값을 따라간다고 되어있긴합니다. 하지만 저는 그냥 명시적으로 정의를 해주었습니다.
BOOST_NO_CXX11_THREAD_LOCAL
매크로 정의
포스팅의 1단계에서 말했듯이 XP 에서는 C++11 thread_local 키워드를 사용하면 안되므로, thread_local 키워드를 쓰는걸 막기위해 이 매크로를 정의하였습니다.
USING_V110_SDK71
매크로 정의
플랫폼 도구 집합 v140
과 v140_xp
의 차이점들중에 하나가 이 매크로의 유무입니다. v140_xp
에서 이 매크로가 정의되므로 똑같이 정의해주도록 합니다.
/Zc:threadSafeInit-
컴파일 플래그 설정
포스팅의 1단계에서 말했듯이 VC++2015 의 Magic Statics 구현은 XP 환경에서 문제가 있습니다. 따라서 Magic Statics 기능을 disable 해야만 하는데, /Zc:threadSafeInit-
플래그가 그러한 역할을 수행합니다.
그러면, 이제부터 XP 를 지원하도록 Boost.FileSystem 를 빌드해보도록 하겠습니다. (부스트 1.69.0 기준으로 테스트되었습니다.)
- 부스트 소스코드를 다운받아서 로컬에 압축을 풉니다.
bootstrap.bat
을 실행시킵니다. 이러면b2.exe
가 생성됩니다.- 아래 명령어를 통해 빌드를 수행하면 됩니다.
32bit / 64bit 빌드 시, 공통으로 먼저 수행해야하는 명령어
set ORG_PATH=%PATH%
set INCLUDE=^
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include;^
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\include;^
C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt;^
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\include
set BUILD_CMD_COMMON= ^
b2 -a -j4 --stagedir=./stage/boost-xp ^
--with-filesystem ^
--reconfigure ^
toolset=msvc-14.0 variant=debug,release threading=multi runtime-link=static,shared link=static,shared ^
define="_WIN32_WINNT=0x0501" ^
define="NTDDI_VERSION=0x05010300" ^
define="BOOST_USE_WINAPI_VERSION=0x0501" ^
define="BOOST_USE_NTDDI_VERSION=0x05010300" ^
define="BOOST_NO_CXX11_THREAD_LOCAL" ^
define="USING_V110_SDK71" ^
cxxflags="/Zc:threadSafeInit- "
32bit 빌드 시 수행해야 하는 명령어
set PATH=^
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\bin;^
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin;^
%ORG_PATH%
set LIBPATH=^
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\lib;^
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib
set LIB=^
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib;^
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\lib;^
C:\Program Files (x86)\Windows Kits\10\lib\10.0.10240.0\ucrt\x86;^
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\lib
%BUILD_CMD_COMMON% ^
address-model=32 ^
linkflags="/SUBSYSTEM:WINDOWS,5.01"
64bit 빌드 시 수행해야 하는 명령어
set PATH=^
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\bin;^
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\x86_amd64;^
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin;^
%ORG_PATH%
set LIBPATH=^
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\lib\amd64;^
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib\amd64
set LIB=^
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib\amd64;^
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\lib\amd64;^
C:\Program Files (x86)\Windows Kits\10\lib\10.0.10240.0\ucrt\x64;^
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\lib\x64
%BUILD_CMD_COMMON% ^
address-model=64 ^
linkflags="/SUBSYSTEM:WINDOWS,5.02"
마무으리
Boost 를 XP 에서 사용하려면 상당히 까다롭죠?? ㅠㅠ 저도 작년 초에 XP 환경에서 boost 를 사용해야하는 상황에 처해서 많이 삽질을 했던 기억이 납니다. 이 포스팅은 그러한 저의 삽질/연구를 바탕으로 한 포스팅인데요. 완벽하게 검증된 방법은 아닙니다. (여러분이 보기에도 뭔가 꼼수같은 느낌이 많이 들죠??)
따라서 이 방법대로만 하면 XP 환경에서 아무런 문제없이 boost 를 사용할 수 있다! 라고 제가 말씀드리기는 어려울 것 같고, 참고정도는 가능하지 않을까 싶습니다.
잘못된 점 혹은 개선할 점 혹은 더 좋은 방법이 설명되어있는 자료링크 같은 것은 언제나 환영입니다!
지금까지 읽어주셔서 감사합니다~