Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)

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이 있는 파일로 저장해 주면 해당 문제는 사라질 것입니다.




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

[연관 글]






[최초 등록일: ]
[최종 수정일: 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)
13348정성태5/10/20233570.NET Framework: 2119. C# - Semantic Kernel의 "Basic Loading of the Kernel" 예제
13347정성태5/10/20233936.NET Framework: 2118. C# - Semantic Kernel의 Prompt chaining 예제파일 다운로드1
13346정성태5/10/20233781오류 유형: 858. RDP 원격 환경과 로컬 PC 간의 Ctrl+C, Ctrl+V 복사가 안 되는 문제
13345정성태5/9/20235084.NET Framework: 2117. C# - (OpenAI 기반의) Microsoft Semantic Kernel을 이용한 자연어 처리 [1]파일 다운로드1
13344정성태5/9/20236334.NET Framework: 2116. C# - OpenAI API 사용 - 지원 모델 목록 [1]파일 다운로드1
13343정성태5/9/20234202디버깅 기술: 192. Windbg - Hyper-V VM으로 이더넷 원격 디버깅 연결하는 방법
13342정성태5/8/20234141.NET Framework: 2115. System.Text.Json의 역직렬화 시 필드/속성 주의
13341정성태5/8/20233914닷넷: 2114. C# 12 - 모든 형식의 별칭(Using aliases for any type)
13340정성태5/8/20233952오류 유형: 857. Microsoft.Data.SqlClient.SqlException - 0x80131904
13339정성태5/6/20234636닷넷: 2113. C# 12 - 기본 생성자(Primary Constructors)
13338정성태5/6/20234125닷넷: 2112. C# 12 - 기본 람다 매개 변수파일 다운로드1
13337정성태5/5/20234632Linux: 59. dockerfile - docker exec로 container에 접속 시 자동으로 실행되는 코드 적용
13336정성태5/4/20234398.NET Framework: 2111. C# - 바이너리 출력 디렉터리와 연관된 csproj 설정
13335정성태4/30/20234516.NET Framework: 2110. C# - FFmpeg.AutoGen 라이브러리를 이용한 기본 프로젝트 구성 - Windows Forms파일 다운로드1
13334정성태4/29/20234171Windows: 250. Win32 C/C++ - Modal 메시지 루프 내에서 SetWindowsHookEx를 이용한 Thread 메시지 처리 방법
13333정성태4/28/20233626Windows: 249. Win32 C/C++ - 대화창 템플릿을 런타임에 코딩해서 사용파일 다운로드1
13332정성태4/27/20233721Windows: 248. Win32 C/C++ - 대화창을 위한 메시지 루프 사용자 정의파일 다운로드1
13331정성태4/27/20233744오류 유형: 856. dockerfile - 구 버전의 .NET Core 이미지 사용 시 apt update 오류
13330정성태4/26/20233414Windows: 247. Win32 C/C++ - CS_GLOBALCLASS 설명
13329정성태4/24/20233622Windows: 246. Win32 C/C++ - 직접 띄운 대화창 템플릿을 위한 Modal 메시지 루프 생성파일 다운로드1
13328정성태4/19/20233262VS.NET IDE: 184. Visual Studio - Fine Code Coverage에서 동작하지 않는 Fake/Shim 테스트
13327정성태4/19/20233686VS.NET IDE: 183. C# - .NET Core/5+ 환경에서 Fakes를 이용한 단위 테스트 방법
13326정성태4/18/20235060.NET Framework: 2109. C# - 닷넷 응용 프로그램에서 SQLite 사용 (System.Data.SQLite) [1]파일 다운로드1
13325정성태4/18/20234407스크립트: 48. 파이썬 - PostgreSQL의 with 문을 사용한 경우 연결 개체 누수
13324정성태4/17/20234239.NET Framework: 2108. C# - Octave의 "save -binary ..."로 생성한 바이너리 파일 분석파일 다운로드1
13323정성태4/16/20234143개발 환경 구성: 677. Octave에서 Excel read/write를 위한 io 패키지 설치
1  2  3  4  5  6  7  8  9  10  [11]  12  13  14  15  ...