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

비밀번호

댓글 작성자
 




... 31  32  33  [34]  35  36  37  38  39  40  41  42  43  44  45  ...
NoWriterDateCnt.TitleFile(s)
12769정성태8/11/20216404오류 유형: 752. Python - ImportError: No module named pip._internal.cli.main 두 번째 이야기
12768정성태8/10/20217422.NET Framework: 1085. .NET 6에 포함된 신규 BCL API [1]파일 다운로드1
12767정성태8/10/20218473오류 유형: 752. Python - ImportError: No module named pip._internal.cli.main
12766정성태8/9/20217009Java: 32. closing inbound before receiving peer's close_notify
12765정성태8/9/20216325Java: 31. Cannot load JDBC driver class 'org.mysql.jdbc.Driver'
12764정성태8/9/202144787Java: 30. XML document from ServletContext resource [/WEB-INF/applicationContext.xml] is invalid
12763정성태8/9/20217782Java: 29. java.lang.NullPointerException - com.mysql.jdbc.ConnectionImpl.getServerCharset
12762정성태8/8/202111281Java: 28. IntelliJ - Unable to open debugger port 오류
12761정성태8/8/20218523Java: 27. IntelliJ - java: package javax.inject does not exist [2]
12760정성태8/8/20215939개발 환경 구성: 594. 전용 "Command Prompt for ..." 단축 아이콘 만들기
12759정성태8/8/20219068Java: 26. IntelliJ + Spring Framework + 새로운 Controller 추가 [2]파일 다운로드1
12758정성태8/7/20218409오류 유형: 751. Error assembling WAR: webxml attribute is required (or pre-existing WEB-INF/web.xml if executing in update mode)
12757정성태8/7/20219091Java: 25. IntelliJ + Spring Framework 프로젝트 생성
12756정성태8/6/20217911.NET Framework: 1084. C# - .NET Core Web API 단위 테스트 방법 [1]파일 다운로드1
12755정성태8/5/20217051개발 환경 구성: 593. MSTest - 단위 테스트에 static/instance 유형의 private 멤버 접근 방법파일 다운로드1
12754정성태8/5/20217986오류 유형: 750. manage.py - Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
12753정성태8/5/20218193오류 유형: 749. PyCharm - Error: Django is not importable in this environment
12752정성태8/4/20216309개발 환경 구성: 592. JetBrains의 IDE(예를 들어, PyCharm)에서 Visual Studio 키보드 매핑 적용
12751정성태8/4/20219344개발 환경 구성: 591. Windows 10 WSL2 환경에서 docker-compose 빌드하는 방법
12750정성태8/3/20216147디버깅 기술: 181. windbg - 콜 스택의 "Call Site" 오프셋 값이 가리키는 위치
12749정성태8/2/20215569개발 환경 구성: 590. Visual Studio 2017부터 단위 테스트에 DataRow 특성 지원
12748정성태8/2/20216182개발 환경 구성: 589. Azure Active Directory - tenant의 관리자(admin) 계정 로그인 방법
12747정성태8/1/20216784오류 유형: 748. 오류 기록 - MICROSOFT GRAPH – HOW TO IMPLEMENT IAUTHENTICATIONPROVIDER파일 다운로드1
12746정성태7/31/20218762개발 환경 구성: 588. 네트워크 장비 환경을 시뮬레이션하는 Packet Tracer 프로그램 소개
12745정성태7/31/20216616개발 환경 구성: 587. Azure Active Directory - tenant의 관리자 계정 로그인 방법
12744정성태7/30/20217229개발 환경 구성: 586. Azure Active Directory에 연결된 App 목록을 확인하는 방법?
... 31  32  33  [34]  35  36  37  38  39  40  41  42  43  44  45  ...