다음을 통해 공유


연습: Microsoft Visual C++에서 헤더 단위 빌드 및 가져오기

이 문서에서는 Visual Studio 2022를 사용하여 헤더 단위를 빌드하고 가져오는 방법에 대해 알아봅니다. C++ 표준 라이브러리 헤더를 헤더 단위로 가져오는 방법을 알아보려면 연습: STL 라이브러리를 헤더 단위로 가져오기를 참조하세요. 표준 라이브러리를 가져오는 더 빠르고 강력한 방법은 자습서: 모듈을 사용하여 C++ 표준 라이브러리 가져오기를 참조 하세요.

헤더 단위는 PCH(미리 컴파일된 헤더) 파일 대신 사용하는 것이 좋습니다. 헤더 단위는 설정하고 사용하기 쉽고, 디스크에서 훨씬 더 작고, 비슷한 성능 이점을 제공하며, 공유 PCH보다 더 유연합니다.

헤더 단위를 프로그램에 기능을 포함하는 다른 방법과 대조하려면 헤더 단위, 모듈 및 미리 컴파일된 헤더 비교를 참조 하세요.

필수 조건

헤더 단위를 사용하려면 Visual Studio 2019 16.10 이상이 필요합니다.

헤더 단위 정의

헤더 단위는 헤더 파일의 이진 표현입니다. 헤더 단위는 .ifc 확장명으로 끝납니다. 명명된 모듈에 동일한 형식이 사용됩니다.

헤더 단위와 헤더 파일 간의 중요한 차이점은 헤더 단위가 헤더 단위 외부의 매크로 정의에 영향을 받지 않는다는 것입니다. 즉, 헤더 단위가 다르게 동작하도록 하는 전처리기 기호를 정의할 수 없습니다. 헤더 단위를 가져올 때 헤더 단위는 이미 컴파일되어 있습니다. 이는 파일이 처리되는 방식과 #include 다릅니다. 헤더 파일이 포함된 원본 파일을 컴파일할 때 헤더 파일이 전처리기를 통과하기 때문에 포함된 파일은 헤더 파일 외부의 매크로 정의에 의해 영향을 받을 수 있습니다.

헤더 단위는 헤더 파일의 true가 아닌 순서대로 가져올 수 있습니다. 헤더 파일 순서는 한 헤더 파일에 정의된 매크로 정의가 후속 헤더 파일에 영향을 줄 수 있기 때문에 중요합니다. 한 헤더 단위의 매크로 정의는 다른 헤더 단위에 영향을 줄 수 없습니다.

헤더 파일에서 볼 수 있는 모든 항목은 헤더 단위 내에 정의된 매크로를 포함하여 헤더 단위에서도 볼 수 있습니다.

헤더 파일을 가져오려면 먼저 헤더 단위로 변환해야 합니다. 미리 컴파일된 PCH(헤더 파일)에 비해 헤더 단위의 장점은 분산 빌드에서 사용할 수 있다는 것입니다. 동일한 컴파일러를 사용하여 가져오는 프로그램 및 컴파일을 컴파일 .ifc 하고 동일한 플랫폼 및 아키텍처를 대상으로 지정하는 한, 한 컴퓨터에서 생성된 헤더 단위를 다른 컴퓨터에서 사용할 수 있습니다. PCH와 달리 헤더 단위가 변경되면 헤더 단위와 그에 따라 달라지는 항목만 다시 작성됩니다. 헤더 단위는 크기가 1보다 .pch작을 수 있습니다.

헤더 단위는 헤더 단위를 만들고 PCH보다 사용하는 코드를 컴파일하는 데 사용되는 컴파일러 스위치 조합의 필수 유사성에 더 적은 제약 조건을 적용합니다. 그러나 일부 스위치 조합 및 매크로 정의는 다양한 변환 단위 간에 ODR(단일 정의 규칙)을 위반할 수 있습니다.

마지막으로 헤더 단위는 PCH보다 더 유연합니다. PCH를 사용하면 PCH의 헤더 중 하나만 가져오도록 선택할 수 없습니다. 컴파일러는 모든 헤더를 처리합니다. 헤더 단위를 사용하여 함께 정적 라이브러리로 컴파일하는 경우에도 가져오는 헤더 단위의 내용만 애플리케이션으로 가져옵니다.

헤더 단위는 헤더 파일과 C++20 모듈 간의 단계입니다. 모듈의 이점 중 일부를 제공합니다. 외부 매크로 정의는 영향을 주지 않으므로 어떤 순서로든 가져올 수 있으므로 더 강력합니다. 또한 컴파일러는 헤더 파일보다 더 빠르게 처리할 수 있습니다. 그러나 헤더 단위는 모듈 내에 정의된 매크로를 노출하므로 모듈의 장점이 모두 없습니다(모듈은 그렇지 않음). 모듈과 달리 헤더 단위에서 프라이빗 구현을 숨길 수 있는 방법은 없습니다. 헤더 파일을 사용하여 프라이빗 구현을 나타내기 위해 이름에 선행 밑줄을 추가하거나 구현 네임스페이스에 항목을 배치하는 것과 같은 다양한 기술이 사용됩니다. 모듈은 어떤 형식으로도 프라이빗 구현을 노출하지 않으므로 그렇게 할 필요가 없습니다.

미리 컴파일된 헤더를 헤더 단위로 바꾸는 것이 좋습니다. 동일한 속도 이점을 얻을 수 있지만 다른 코드 위생 및 유연성 이점도 있습니다.

헤더 단위를 컴파일하는 방법

파일을 헤더 단위로 컴파일하는 방법에는 여러 가지가 있습니다.

  • 공유 헤더 단위 프로젝트 빌드. 이 방법은 조직에 대한 제어를 더 많이 제공하고 가져온 헤더 단위를 다시 사용할 수 있기 때문에 권장됩니다. 원하는 헤더 단위가 포함된 정적 라이브러리 프로젝트를 만든 다음 참조하여 헤더 단위를 가져옵니다. 이 방법의 연습은 헤더 단위에 대한 헤더 단위 정적 라이브러리 프로젝트 빌드를 참조 하세요.

  • 머리글 단위로 변환할 개별 파일을 선택합니다. 이 방법을 사용하면 헤더 단위로 처리되는 항목을 파일별로 제어할 수 있습니다. 기본 확장명(, , , .h.hpp).ixx.cppm이 없으므로 일반적으로 헤더 단위로 컴파일되지 않는 헤더 단위로 파일을 컴파일해야 하는 경우에도 유용합니다. 이 방법은 이 연습에서 보여 줍니다. 시작하려면 방법 1: 특정 파일을 헤더 단위로 변환을 참조하세요.

  • 헤더 단위를 자동으로 검색하고 빌드합니다. 이 방법은 편리하지만 최적의 빌드 처리량을 보장하지 않으므로 소규모 프로젝트에 가장 적합합니다. 이 방법에 대한 자세한 내용은 방법 2: 헤더 단위를 자동으로 검색하는 방법을 참조 하세요.

  • 소개에서 멘션 STL 헤더 파일을 빌드 및 헤더 단위로 가져오고 코드를 다시 작성하지 않고 STL 라이브러리 헤더를 import 자동으로 처리 #include 할 수 있습니다. 방법을 보려면 연습: STL 라이브러리를 헤더 단위로 가져옵니다.

방법 1: 특정 파일을 헤더 단위로 변환

이 섹션에서는 헤더 단위로 변환할 특정 파일을 선택하는 방법을 보여줍니다. Visual Studio에서 다음 단계를 사용하여 헤더 파일을 헤더 단위로 컴파일합니다.

  1. 새 C++ 콘솔 앱 프로젝트를 만듭니다.

  2. 원본 파일 내용을 다음과 같이 바꿉니다.

    #include "Pythagorean.h"
    
    int main()
    {
        PrintPythagoreanTriple(2,3);
        return 0;
    }
    
  3. 호출 Pythagorean.h 된 헤더 파일을 추가한 다음 해당 콘텐츠를 다음 코드로 대체합니다.

    #ifndef PYTHAGOREAN
    #define PYTHAGOREAN
    
    #include <iostream>
    
    inline void PrintPythagoreanTriple(int a, int b)
    {
        std::cout << "Pythagorean triple a:" << a << " b:" << b << " c:" << a*a + b*b << std::endl;
    }
    #endif
    

프로젝트 속성 설정

헤더 단위를 사용하도록 설정하려면 먼저 다음 단계를 사용하여 C++ 언어 표준 /std:c++20 이상을 설정합니다.

  1. 솔루션 탐색기 프로젝트 이름을 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다.
  2. 프로젝트 속성 페이지 창의 왼쪽 창에서 구성 속성>일반을 선택합니다.
  3. C++ 언어 표준 드롭다운에서 ISO C++20 표준(/std:c++20) 이상을 선택합니다. 확인을 선택하여 대화 상자를 닫습니다.

헤더 파일을 헤더 단위로 컴파일합니다.

  1. 솔루션 탐색기 헤더 단위로 컴파일할 파일을 선택합니다(이 경우Pythagorean.h). 파일을 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다.

  2. 구성 속성>일반>항목 유형 드롭다운을 C/C++ 컴파일러로 설정하고 확인을 선택합니다.

    Screenshot that shows changing the item type to C/C++ compiler.

이 연습 Pythagorean.h 의 뒷부분에서 이 프로젝트를 빌드하면 헤더 단위로 변환됩니다. 이 헤더 파일의 항목 형식이 C/C++ 컴파일러로 설정되고, 이러한 방식으로 설정된 파일에 대한 .h .hpp 기본 작업은 파일을 헤더 단위로 변환하기 때문에 헤더 단위로 변환됩니다.

참고 항목

이 연습에는 필요하지 않지만 사용자 정보를 위해 제공됩니다. 예를 들어 기본 헤더 단위 파일 확장 .cpp 명이 없는 헤더 단위로 파일을 컴파일하려면 C/C++>고급>컴파일을 C++ 헤더 단위(/exportHeader)로 컴파일하도록 구성 속성을>설정합니다.Screenshot that shows changing Configuration properties > C/C++ > Advanced > Compile As to Compile as C++ Header Unit (/exportHeader).

헤더 단위를 가져오도록 코드 변경

  1. 예제 프로젝트의 원본 파일에서 후행 세미콜론을 import "Pythagorean.h"; 잊지 마세요.로 변경 #include "Pythagorean.h" 합니다. 문에 import 필요합니다. 프로젝트의 로컬 디렉터리에 있는 헤더 파일이므로 다음 문import "file";과 함께 import 따옴표를 사용했습니다. 사용자 고유의 프로젝트에서 시스템 헤더에서 헤더 단위를 컴파일하려면 꺾쇠 괄호를 사용합니다. import <file>;

  2. 주 메뉴에서 빌드>솔루션 빌드를 선택하여 솔루션을 빌드합니다. 실행하여 예상 출력을 생성하는지 확인합니다. Pythagorean triple a:2 b:3 c:13

사용자 고유의 프로젝트에서 이 프로세스를 반복하여 헤더 단위로 가져올 헤더 파일을 컴파일합니다.

몇 가지 헤더 파일만 헤더 단위로 변환하려는 경우 이 방법이 좋습니다. 그러나 컴파일하려는 헤더 파일이 많고 빌드 시스템이 자동으로 처리하도록 하는 편의상 빌드 성능 손실 가능성이 더 큰 경우 다음 섹션을 참조하세요.

STL 라이브러리 헤더를 헤더 단위로 특별히 가져오려면 연습: STL 라이브러리를 헤더 단위로 가져오기를 참조하세요.

방법 2: 헤더 단위를 자동으로 검색 및 빌드

모든 원본 파일에서 헤더 단위를 검사하는 데 시간이 걸리고 이를 빌드하는 데 시간이 걸리기 때문에 다음 방법은 소규모 프로젝트에 가장 적합합니다. 최적의 빌드 처리량을 보장하지는 않습니다.

이 방법은 두 Visual Studio 프로젝트 설정을 결합합니다.

  • 모듈 종속성에 대한 원본 검색을 수행하면 빌드 시스템에서 컴파일러를 호출하여 가져온 모든 모듈 및 헤더 단위가 종속된 파일을 컴파일하기 전에 빌드되었는지 확인합니다. Import에 포함 변환과 결합하면 헤더 파일과 동일한 디렉터리에 있는 파일에 지정된 원본에 header-units.json 포함된 모든 헤더 파일이 헤더 단위로 컴파일됩니다.
  • Import에 포함 변환은 헤더 파일을 헤더 단위로 import 컴파일할 수 있는 헤더 파일을 참조하는 것처럼 #include 처리하고(파일에 지정된 header-units.json 대로) 헤더 파일에 컴파일된 헤더 단위를 사용할 수 있습니다. 그렇지 않으면 헤더 파일이 일반 #include파일로 처리됩니다. 이 header-units.json 파일은 기호 중복 없이 각각 #include에 대한 헤더 단위를 자동으로 빌드하는 데 사용됩니다.

프로젝트의 속성에서 이러한 설정을 켤 수 있습니다. 이렇게 하려면 솔루션 탐색기 프로젝트를 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다. 그런 다음, 구성 속성>C/C++>일반을 선택합니다.

Screenshot that shows the project properties screen with Configuration highlighted and All Configurations selected. Under C/C++ > General, Scan Sources for Module Dependencies is highlighted and set to yes, and Translate Includes to Imports is highlighted and set to Yes (/translateInclude)

모듈 종속성에 대한 검사 원본은 여기에 표시된 대로 프로젝트 속성의 프로젝트에 있는 모든 파일 또는 파일 속성 의 개별 파일에 대해 설정할 수 있습니다. 모듈 및 헤더 단위는 항상 검사됩니다. 자동으로 빌드하고 아직 빌드되지 않을 수 있는 헤더 단위를 가져오는 파일이 있는 경우 .cpp 이 옵션을 설정합니다.

이러한 설정은 다음과 같은 조건에서 헤더 단위를 자동으로 빌드하고 가져오기 위해 함께 작동합니다.

  • 모듈 종속성에 대한 원본 검색은 원본에서 헤더 단위로 처리할 수 있는 파일 및 해당 종속성을 검색합니다. 확장.ixx명이 있는 파일과 파일 속성>C/C++>Compile As 속성이 C++ 헤더 단위(/export)로 컴파일로 설정된 파일은 이 설정에 관계없이 항상 검색됩니다. 또한 컴파일러는 헤더 단위 종속성을 식별하는 문을 찾 import 습니다. 지정된 경우 /translateInclude 컴파일러는 파일에 지정된 header-units.json 지시문도 검색 #include 하여 헤더 단위로 처리합니다. 종속성 그래프 프로젝트의 모든 모듈 및 헤더 단위로 빌드됩니다.
  • 컴파일러에서 문이 발견 #include 되고 지정된 헤더 파일에 대해 일치하는 헤더 단위 파일(.ifc)이 있는 경우 Import to Imports로 변환하면 컴파일러는 헤더 파일을 처리하지 않고 헤더 단위를 #include가져옵니다. 종속성 검사와 결합하면 컴파일러는 헤더 단위로 컴파일할 수 있는 모든 헤더 파일을 찾습니다. 허용 목록은 컴파일러에서 참조하여 헤더 단위로 컴파일할 수 있는 헤더 파일을 결정합니다. 이 목록은 포함된 파일과 header-units.json 동일한 디렉터리에 있어야 하는 파일에 저장됩니다. Visual Studio의 설치 디렉터리 아래에서 파일의 header-units.json 예를 볼 수 있습니다. 예를 들어 %ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.30.30705\include\header-units.json 컴파일러에서 표준 템플릿 라이브러리 헤더를 헤더 단위로 컴파일할 수 있는지 여부를 결정하는 데 사용됩니다. 이 기능은 헤더 단위의 몇 가지 이점을 얻기 위해 레거시 코드가 있는 브리지 역할을 하기 위해 존재합니다.

이 파일은 header-units.json 두 가지 용도로 사용됩니다. 헤더 단위로 컴파일할 수 있는 헤더 파일을 지정하는 것 외에도 중복된 기호를 최소화하여 빌드 처리량을 높입니다. 기호 중복 에 대한 자세한 내용은 C++ header-units.json 참조를 참조하세요.

이러한 스위치와 header-unit.json 헤더 단위의 몇 가지 이점을 제공합니다. 편의는 빌드 처리량의 비용으로 제공됩니다. 이 방법은 최적의 빌드 시간을 보장하지 않으므로 대규모 프로젝트에 적합하지 않을 수 있습니다. 또한 동일한 헤더 파일을 반복적으로 다시 처리하여 빌드 시간을 늘릴 수 있습니다. 그러나 프로젝트에 따라 편리함이 가치가 있을 수 있습니다.

이러한 기능은 레거시 코드를 위해 설계되었습니다. 새 코드의 경우 헤더 단위 또는 #include 파일 대신 모듈로 이동합니다. 모듈 사용에 대한 자습서는 이름 모듈 자습서(C++)를 참조하세요.

이 기술을 사용하여 STL 헤더 파일을 헤더 단위로 가져오는 방법에 대한 예제는 연습: STL 라이브러리를 헤더 단위로 가져오기를 참조하세요.

전처리기 의미

헤더 단위를 만들고 사용하려면 표준 C99/C++11 준수 전처리기가 필요합니다. 컴파일러는 모든 형식 /exportHeader 이 사용될 때마다 명령줄에 암시적으로 추가하여 /Zc:preprocessor 헤더 단위를 컴파일할 때 새 C99/C++11이 전처리기를 준수하도록 설정합니다. 끄려고 하면 컴파일 오류가 발생합니다.

새 전처리기를 사용하도록 설정하면 variadic 매크로 처리에 영향을 줍니다. 자세한 내용은 Variadic 매크로 설명 섹션을 참조하세요.

참고 항목

/translateInclude
/exportHeader
/headerUnit
header-units.json
헤더 단위, 모듈 및 미리 컴파일된 헤더 비교
C++에서의 모듈 개요
자습서: 모듈을 사용하여 C++ 표준 라이브러리 가져오기
연습: STL 라이브러리를 헤더 단위로 가져오기