Microsoft MVP성태의 닷넷 이야기
글쓴 사람
홈페이지
첨부 파일
 

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




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





[최초 등록일: ]
[최종 수정일: 4/5/2019 ]

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

비밀번호

댓글 쓴 사람
 




1  2  3  4  5  [6]  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
11900정성태5/18/2019482오류 유형: 537. "sfc /scannow" 실행 중 시스템이 부팅되는 현상
11899정성태5/17/2019711Linux: 9. Linux에서 윈도우의 OutputDebugString 대신 사용할 수 있는 syslog [1]
11898정성태5/20/2019584VC++: 130. C++ string의 c_str과 data 함수의 차이점 [3]
11897정성태5/16/2019905오류 유형: 536. Visual Studio - "Developer Pack"을 설치했는데도 "대상 프레임워크" 목록에 나오지 않는 경우
11896정성태5/15/2019580개발 환경 구성: 440. C#, C++ - double의 Infinity, NaN 표현 방식파일 다운로드1
11895정성태5/12/2019682.NET Framework: 832. ML.NET Model Builder - 회귀(Regression), 다중 분류(Multi-class classification) 예제파일 다운로드1
11894정성태5/12/2019812VS.NET IDE: 135. Visual Studio - ML.NET Model Builder 소개 [1]
11893정성태5/10/2019606오류 유형: 535. C# 6.0 이상의 문법을 컴파일 시 오류가 발생한다면?
11892정성태5/10/2019491웹: 38. HTTP Cookie의 expires 시간 형식(RFC7231)
11891정성태5/9/2019592.NET Framework: 831. (번역글) .NET Internals Cookbook Part 12 - Memory structure, attributes, handles
11890정성태5/8/2019496개발 환경 구성: 439. "Visual Studio Enterprise is required to execute the test." 메시지와 관련된 코드 기록
11889정성태5/8/2019468개발 환경 구성: 438. mstest, QTAgent의 로그 파일 설정 방법
11888정성태5/8/2019609.NET Framework: 830. C# - 비동기 호출을 취소하는 CancellationToken의 간단한 예제 코드파일 다운로드1
11887정성태5/8/2019720.NET Framework: 829. C# - yield 문을 사용할 수 있는 메서드의 조건
11886정성태5/8/2019677오류 유형: 534. mstest.exe 실행 시 "Visual Studio Enterprise is required to execute the test." 오류 [1]
11885정성태5/7/2019397오류 유형: 533. mstest.exe 실행 시 "File extension specified '.loadtest' is not a valid test extension." 오류 발생
11884정성태5/5/2019709.NET Framework: 828. C# DLL에서 Win32 C/C++처럼 dllexport 함수를 제공하는 방법 - 두 번째 이야기
11883정성태5/3/2019730.NET Framework: 827. C# - 인터넷 시간 서버로부터 받은 시간을 윈도우에 적용하는 방법파일 다운로드1
11882정성태5/9/2019557.NET Framework: 826. (번역글) .NET Internals Cookbook Part 11 - Various C# riddles파일 다운로드1
11881정성태4/28/2019677오류 유형: 532. .NET Core 프로젝트로 마이그레이션 시 "CS0579 Duplicate 'System.Reflection.AssemblyCompanyAttribute' attribute" 오류 발생
11880정성태4/25/2019471오류 유형: 531. 이벤트 로그 오류 - Task Scheduling Error: m->NextScheduledSPRetry 1547, m->NextScheduledEvent 1547
11879정성태5/9/2019622.NET Framework: 825. (번역글) .NET Internals Cookbook Part 10 - Threads, Tasks, asynchronous code and others파일 다운로드1
11878정성태5/9/2019610.NET Framework: 824. (번역글) .NET Internals Cookbook Part 9 - Finalizers, queues, card tables and other GC stuff파일 다운로드1
11877정성태5/9/2019596.NET Framework: 823. (번역글) .NET Internals Cookbook Part 8 - C# gotchas파일 다운로드1
11876정성태5/9/2019524.NET Framework: 822. (번역글) .NET Internals Cookbook Part 7 - Word tearing, locking and others파일 다운로드1
11875정성태4/21/2019429오류 유형: 530. Visual Studo에서 .NET Core 프로젝트를 열 때 "One or more errors occurred." 오류 발생
1  2  3  4  5  [6]  7  8  9  10  11  12  13  14  15  ...