Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

Visual C++ 컴파일 오류 - error C2220: warning treated as error - no 'object' file generated

얼마 전에 공개된 윈도우 계산기의 소스 코드를,

Microsoft/calculator
; https://github.com/Microsoft/calculator

내려받아,

E:\git_clone> git clone https://github.com/Microsoft/calculator.git
Cloning into 'calculator'...
remote: Enumerating objects: 2939, done.
remote: Total 2939 (delta 0), reused 0 (delta 0), pack-reused 2939
Receiving objects: 100% (2939/2939), 20.09 MiB | 5.45 MiB/s, done.
Resolving deltas: 100% (1715/1715), done.

빌드하려면 Visual Studio 2019를 설치하고 다음의 구성 요소를 함께 선택해야 합니다.

Universal Windows Platform Development
	- C++ (v141) Universal Windows Platform tools
	- Windows 10 SDK (최신 버전)

이후 E:\git_clone\calculator\src\Calculator.sln 파일을 Visual Studio 2019에서 열어 툴바의 ARM64로 맞춰진 플랫폼을 x64로 바꿔줍니다.

src_encode_1.png

자... 이제 솔루션 빌드를 하면, 다음과 같은 에러 및 경고를 볼 수 있습니다.

1>------ Rebuild All started: Project: CalcManager, Configuration: Debug x64 ------
1>pch.cpp
...[생략]...
2>CalculatorButtonPressedEventArgs.cpp
2>CalculatorDisplay.cpp
2>ConversionResultTaskHelper.cpp
2>CopyPasteManager.cpp
2>e:\git_clone\calculator\src\calcviewmodel\common\copypastemanager.cpp(1): error C2220: warning treated as error - no 'object' file generated
2>e:\git_clone\calculator\src\calcviewmodel\common\copypastemanager.cpp(1): warning C4819: The file contains a character that cannot be represented in the current code page (949). Save the file in Unicode format to prevent data loss
...[생략]...
4>HistoryTests.cpp
4>e:\git_clone\calculator\src\calculatorunittests\currencyconverterunittests.cpp(1): error C2220: warning treated as error - no 'object' file generated
4>e:\git_clone\calculator\src\calculatorunittests\copypastemanagertest.cpp(1): error C2220: warning treated as error - no 'object' file generated
4>e:\git_clone\calculator\src\calculatorunittests\currencyconverterunittests.cpp(1): warning C4819: The file contains a character that cannot be represented in the current code page (949). Save the file in Unicode format to prevent data loss
4>e:\git_clone\calculator\src\calculatorunittests\copypastemanagertest.cpp(1): warning C4819: The file contains a character that cannot be represented in the current code page (949). Save the file in Unicode format to prevent data loss
4>e:\git_clone\calculator\src\calculatorunittests\copypastemanagertest.cpp(5): fatal error C1083: Cannot open include file: 'CppUnitTest.h': No such file or directory
4>e:\git_clone\calculator\src\calculatorunittests\currencyconverterunittests.cpp(5): fatal error C1083: Cannot open include file: 'CppUnitTest.h': No such file or directory
4>e:\git_clone\calculator\src\calculatorunittests\historytests.cpp(5): fatal error C1083: Cannot open include file: 'CppUnitTest.h': No such file or directory
4>e:\git_clone\calculator\src\calculatorunittests\calcenginetests.cpp(5): fatal error C1083: Cannot open include file: 'CppUnitTest.h': No such file or directory
4>e:\git_clone\calculator\src\calculatorunittests\calcinputtest.cpp(5): fatal error C1083: Cannot open include file: 'CppUnitTest.h': No such file or directory
4>CurrencyHttpClient.cpp
...[생략]...
4>StandardViewModelUnitTests.cpp
4>e:\git_clone\calculator\src\calculatorunittests\datecalculatorunittests.cpp(5): fatal error C1083: Cannot open include file: 'CppUnitTest.h': No such file or directory
4>e:\git_clone\calculator\src\calculatorunittests\calculatormanagertest.cpp(6): fatal error C1083: Cannot open include file: 'CppUnitTest.h': No such file or directory
4>UnitConverterTest.cpp
4>UnitConverterViewModelUnitTests.cpp
4>e:\git_clone\calculator\src\calculatorunittests\module.cpp(5): fatal error C1083: Cannot open include file: 'CppUnitTest.h': No such file or directory
4>UnitTestApp.xaml.cpp
4>e:\git_clone\calculator\src\calculatorunittests\standardviewmodelunittests.cpp(5): fatal error C1083: Cannot open include file: 'CppUnitTest.h': No such file or directory
4>UtilsTests.cpp
4>e:\git_clone\calculator\src\calculatorunittests\navcategoryunittests.cpp(5): fatal error C1083: Cannot open include file: 'CppUnitTest.h': No such file or directory
4>XamlTypeInfo.Impl.g.cpp
4>e:\git_clone\calculator\src\calculatorunittests\multiwindowunittests.cpp(5): fatal error C1083: Cannot open include file: 'CppUnitTest.h': No such file or directory
4>e:\git_clone\calculator\src\calculatorunittests\unitconverterviewmodelunittests.cpp(5): fatal error C1083: Cannot open include file: 'CppUnitTest.h': No such file or directory
4>e:\git_clone\calculator\src\calculatorunittests\unitconvertertest.cpp(6): fatal error C1083: Cannot open include file: 'CppUnitTest.h': No such file or directory
4>e:\git_clone\calculator\src\calculatorunittests\utilstests.cpp(5): fatal error C1083: Cannot open include file: 'CppUnitTest.h': No such file or directory
4>Done building project "CalculatorUnitTests.vcxproj" -- FAILED.
...[생략]...

항목이 많은데 대체로 다음의 2가지로 나뉩니다.

error C2220: warning treated as error - no 'object' file generated
warning C4819: The file contains a character that cannot be represented in the current code page (949). Save the file in Unicode format to prevent data loss

fatal error C1083: Cannot open include file: 'CppUnitTest.h': No such file or directory

하나씩 해결해 볼까요? ^^




우선 가장 많이 나타나는 C1083 오류를 먼저 해결해 보겠습니다. 이 오류는 Visual Studio 2019만 설치했을 때 발생하는 오류인데요, CppUnitTest.h 파일은 실제로 다음과 같은 경로에 존재합니다.

[Visual Studio 2019 Community 버전인 경우]
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\VS\UnitTest\include\UWP

하지만 CalculatorUnitTests 프로젝트의 Platform Toolset 값이 "Visual Studio 2017 (v141)"로 되어 있기 때문에 CppUnitTest.h 파일을 2017을 기준으로,

C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\VS\UnitTest\include\UWP

찾게 됩니다. 따라서 이런 경우에는 "CalculatorUnitTests" 프로젝트의 속성 창에서 "General" 범주의 "Platform Toolset" 값을 "Visual Studio 2019 (v142)"로 맞춘 후 빌드하면 됩니다.




그다음 C2220 오류는 C4819 경고 때문에 발생하는 것으로 Calculator 관련 프로젝트들은 모두 경고가 발생한 경우 오류로 취급하라고 설정되어 있기 때문입니다. 따라서 해당 프로젝트의 속성 창에서 "C/C++" / "General" 범주의 "Treat Warnings As Errors" 옵션을 "No (/WX-)"로 바꾸면 오류는 없앨 수 있습니다.

물론, 그렇다고 해서 C4819 경고가 사라지는 것은 아닙니다. (Rebuild하면 C4819 경고가 발생합니다.) 이 경고는 해당 소스 코드 파일에 시스템의 Locale 설정으로는 표현할 수 없는 문자가 들어 있기 때문에 이를 알려주는 것인데요. 근본적인 원인은 해당 소스 코드를 만든 개발자가 파일의 Locale을 유니코드 처리를 하지 않았기 때문입니다. 예를 들어 위의 오류를 보면,

warning C4819: The file contains a character that cannot be represented in the current code page (949). Save the file in Unicode format to prevent data loss

현재 Visual Studio가 실행되고 있는 윈도우 환경에서는 949 (확장 완성형) 코드 페이지로 설정되어 있지만 소스 코드 파일에는 949 코드 페이지에 속하지 않은 문자를 포함하고 있다는 것입니다. 그리고 해결책도 함께 알려주고 있는데요, 유니코드 포맷으로 변경해 저장하라는 것입니다.

여기서 문제라면, 유니코드 포맷으로 저장하는 것 자체가 좀 애매하다는 것이 문제입니다. 실제로 해당 경고가 발생한 "CopyPasteManagerTest.cpp" 파일은 UTF-8 포맷으로 저장된 상태이기 때문에 원래는 오류가 발생해서는 안 됩니다. 하지만 그 파일이 UTF-8 포맷으로 저장한 것인지 직접적으로 알 수 있는 방법이 없습니다. 윈도우 환경에서는 그동안 이 문제를 해결하기 위해 BOM을 명시적으로 파일의 선두에 쓰는 방법을 선호했는데, 따라서 UTF-8로 저장되었다는 것을 알리는 "ef, bb, bf" 바이트가 있어야 합니다.

그렇다면 왜 그 파일에는 BOM 바이트가 없을까요? 그 이유는, UTF-8의 경우 관행적으로 BOM을 표시하지 않는다는 데에 있습니다. 이 현상은 리눅스 진영에서 더 심한데, 리눅스 플랫폼에서는 UTF-8에 대해 BOM을 표시하지 않고 있으며 근래 마이크로소프트가 Linux 친화적인 환경을 도입하면서 이에 따라 마찬가지로 UTF-8에 대해 BOM을 표시하지 않는 문화로 점차 바뀐 것 같습니다.

어쩔 수 없이 이제 공은 비주얼 스튜디오의 편집기를 작성한 개발자에게 넘어갑니다. 편집기 개발자는 BOM도 없는 파일이 어떤 인코딩을 따르도록 작성된 것인지 유추를 해야 합니다. 당연히 이 유추 코드는 완벽할 수는 없으며 CopyPasteManagerTest.cpp 파일처럼 대부분의 문자가 영문으로 작성된 경우 그냥 윈도우 시스템의 로케일 설정을 따르는 것으로 판단을 하게 만든 듯합니다.

이쯤 되면 근본적인 해결책이 나옵니다. 해당 파일을 (한 예로 메모장으로) 열어서 명시적으로 "UTF-8"로 저장하면 됩니다.




간혹, 너무 많은 파일이 C4819 경고가 발생하면 저렇게 일일이 UTF-8로 저장하는 것도 여간 귀찮은 작업이 아닐 수 없습니다. 그런 경우에는 해당 폴더의 소스 코드 파일을 전부 읽어서 UTF-8로 저장하는 프로그램을 간단하게 만들어 사용하면 됩니다. 혹은 다른 방법도 있습니다. 결국 편집기 개발자가 파일을 유추해서 적당한 경우 시스템의 Locale 설정을 따른다는 점을 해결하면 됩니다. 즉, 시스템의 Locale을 UTF-8로 바꾸면 되는 것입니다. 다행히 이에 대한 옵션이 윈도우 10부터 (2019-04-05 기준) 베타 딱지를 달고 배포된 상태입니다.

영문 설정의 Windows 10 명령행 창(cmd.exe)의 한글 지원
; https://www.sysnet.pe.kr/2/0/11559

따라서 "Beta: Use Unicode UTF-8 for worldwide language support" 옵션을 켜 두면 UTF-8로 인한 C4819 경고는 없앨 수 있습니다.




참고로 Visual Studio에서 제공하는,

Visual Studio 의 '새 파일'을 UTF-8 인코딩으로 지정하는 방법
; https://www.sysnet.pe.kr/2/0/1349

"Save documents as Unicode when data cannot be saved in codepage" 옵션은 파일 자체의 인코딩을 UTF-8로 바꿔는 주는데 BOM은 붙이지 않습니다. (아마도 Microsoft의 개발자들이 이 옵션을 사용하고 있는 것이 아닌가 예상합니다.)




마지막으로, 간혹 운이 안 좋다면 C4819 경고는 엉뚱하게 컴파일 문법을 발생시킵니다. 아래의 경우가 그 사례입니다.

이번에 오픈소스로 공개된 계산기 엡에 관한 질문입니다.
; https://social.msdn.microsoft.com/Forums/ko-KR/be42cd32-47ec-4084-bdab-de7ea4a6372d/510604826450640-5072454536495484982847196-442774406046108?forum=vsko

중간에 보면 다음과 같은 경고가 나오는데요.

3>c:\users\c0001\source\repos\calculator-master\calculator-master\src\calculatorunittests\currencyconverterunittests.cpp(1): warning C4819: 현재 코드 페이지(949)에서 표시할 수 없는 문자가 파일에 들어 있습니다. 데이터가 손실되지 않게 하려면 해당 파일을 유니코드 형식으로 저장하십시오.
3>c:\users\c0001\source\repos\calculator-master\calculator-master\src\calculatorunittests\currencyconverterunittests.cpp(92): fatal error C1075: '{': 일치하는 토큰을 찾을 수 없습니다.

949 코드 페이지에서 표현할 수 없는 문자가 들어있는데, 하필 그것이 2바이트 이상의 UTF-8 인코딩의 조합과 엮이게 되면 그다음 바이트와 합쳐져서 한 글자를 이루게 되는 것입니다. 즉, 위의 경우에는 "}" 글자와 합쳐진 선행 문자가 있는 것입니다. 다행히 이번 경우에는 파일 자체가 UTF-8로 인코딩되어 있기 때문에 명시적으로 UTF-8 BOM이 있는 파일로 저장해 주면 해당 문제는 사라질 것입니다.




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]


donaricano-btn



[최초 등록일: ]
[최종 수정일: 11/24/2020 ]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 쓴 사람
 




[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
12688정성태6/24/202138.NET Framework: 1073. C# - JSON 역/직렬화 시 리플렉션 손실을 없애는 JsonSrcGen파일 다운로드1
12687정성태6/22/202136오류 유형: 729. Invalid data: Invalid artifact, java se app service only supports .jar artifact
12686정성태6/21/202152Java: 22. Azure - 자바(Java)로 만드는 Web App Service
12685정성태6/21/202158Java: 21. Azure Web App Service에 배포된 Java 프로세스의 메모리 및 힙(Heap) 덤프 뜨는 방법
12684정성태6/19/202148오류 유형: 728. Visual Studio 2022부터 DTE.get_Properties 속성 접근 시 System.MissingMethodException 예외 발생
12683정성태6/18/202165VS.NET IDE: 166. Visual Studio 2022 - Windows Forms 프로젝트의 x86 DLL 컨트롤이 Designer에서 오류가 발생하는 문제파일 다운로드1
12682정성태6/18/202180VS.NET IDE: 165. Visual Studio 2022를 위한 Extension 마이그레이션
12681정성태6/18/202154오류 유형: 727. .NET 2.0 ~ 3.5 + x64 환경에서 System.EnterpriseServices 참조 시 CS8012 경고
12680정성태6/18/202140오류 유형: 726. python2.7.exe 실행 시 0xc000007b 오류
12679정성태6/18/202197COM 개체 관련: 23. CoInitializeSecurity의 전역 설정을 재정의하는 CoSetProxyBlanket 함수 사용법파일 다운로드1
12678정성태6/17/202182.NET Framework: 1072. C# - CoCreateInstance 관련 Inteop 오류 정리파일 다운로드1
12677정성태6/17/202176VC++: 144. 역공학을 통한 lxssmanager.dll의 ILxssSession 사용법 분석파일 다운로드1
12676정성태6/16/2021108VC++: 143. ionescu007/lxss github repo에 공개된 lxssmanager.dll의 CLSID_LxssUserSession/IID_ILxssSession 사용법파일 다운로드1
12675정성태6/16/202154Java: 20. maven package 명령어 결과물로 (war가 아닌) jar 생성 방법
12674정성태6/15/202194VC++: 142. DEFINE_GUID 사용법
12673정성태6/15/202157Java: 19. IntelliJ - 자바(Java)로 만드는 Web App을 Tomcat에서 실행하는 방법
12672정성태6/15/202148오류 유형: 725. IntelliJ에서 Java webapp 실행 시 "Address localhost:1099 is already in use" 오류
12671정성태6/15/202164오류 유형: 724. Tomcat 실행 시 Failed to initialize connector [Connector[HTTP/1.1-8080]] 오류
12670정성태6/13/202169.NET Framework: 1071. DLL Surrogate를 이용한 Out-of-process COM 개체에서의 CoInitializeSecurity 문제파일 다운로드1
12669정성태6/11/2021160.NET Framework: 1070. 사용자 정의 GetHashCode 메서드 구현은 C# 9.0의 record 또는 리팩터링에 맡기세요.
12668정성태6/11/2021175.NET Framework: 1069. C# - DLL Surrogate를 이용한 Out-of-process COM 개체 제작파일 다운로드2
12667정성태6/10/202199.NET Framework: 1068. COM+ 서버 응용 프로그램을 이용해 CoInitializeSecurity 제약 해결파일 다운로드1
12666정성태6/10/202178.NET Framework: 1067. 별도 DLL에 포함된 타입을 STAThread Main 메서드에서 사용하는 경우 CoInitializeSecurity 자동 호출파일 다운로드1
12665정성태6/9/2021146.NET Framework: 1066. Wslhub.Sdk 사용으로 알아보는 CoInitializeSecurity 사용 제약파일 다운로드1
12664정성태6/9/2021102오류 유형: 723. COM+ PIA 참조 시 "This operation failed because the QueryInterface call on the COM component" 오류
[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...