How do I use Header Units with the Windows Desktop Application default template and resolve conflicts with headers?

CDev-8220 385 Reputation points
2024-12-13T23:41:21.97+00:00

I am trying to use Header Units in a Desktop Application, but am getting problems with headers, and the .ifc file.

  1. Problems with gdi, and DirectX header includes : C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\um\GdiplusEnums.h(27,13): warning C5260: the constant variable 'Gdiplus::FlatnessDefault' has internal linkage in an included header file context, but external linkage in imported header unit context; consider declaring it 'inline' as well if it will be shared across translation units, or 'static' to express intent to use it local to this translation unit; Multiple DirectX header includes with the same error.

I removed these includes, and was able to build the project.

Now, when I use

import "header.h";

I get

Error LNK1000 Internal error during IncrBuildImage

I am using the guide from cpp-build-msvc-170 p. 211-218

I took note of this:

Header units are a step in between header files and C++ 20 modules. They provide some of the benefits of modules. They're more robust because outside macro definitions don't affect them--so you can import them in any order. And the compiler can process them faster than header files. But header units don't have all of the advantages of modules because header units expose the macros defined within them (modules don't). Unlike modules, there's no way to hide private implementation in a header unit. To indicate private implementation with header files, different techniques are employed like adding leading underscores to names, or putting things in an implementation namespace. A module doesn't expose private implementation in any form, so you don't need to do that. Consider replacing your precompiled headers with header units. You get the same speed advantage, but with other code hygiene and flexibility benefits as well.

I tried using namespace, but I am not sure if I am going about it correctly, because when using namespace name in the main .cpp file the program crashes.

What is the correct way to do this, and what other techniques are they beside using underscores?

Thanks.

Windows for business | Windows Client for IT Pros | User experience | Other
Developer technologies | C++
{count} votes

2 answers

Sort by: Most helpful
  1. Darran Rowe 1,991 Reputation points
    2024-12-15T23:54:54.1366667+00:00

    Unfortunately, this is one of those circumstances where if you have to ask this question then you are not ready to do this.

    If you really wish to try this though, I seriously suggest that digging deep into winnt.h and trying to make a coherant view of that file is the first stop. The reason why I mention trying to work with winnt.h is because it perfectly highlights all of the problems with the Windows headers. If an example of what I mean is required, find the definitions of the CONTEXT structure. For the current Windows headers, CONTEXT will be defined as one of four incompatible definitions based upon the predefined macros.

    But I also feel that just rewriting these headers to be more C++ and module friendly will be a much easier task overall.


  2. CDev-8220 385 Reputation points
    2024-12-26T11:02:11.77+00:00

    Okay, so the problem is not related to incompatibility or conflict issues, directly, but rather, the arrangement and order, in which headers are included.

    The compiler complains and reports an error, when certain headers precede others, or follow others.

    So, I had to include headers either before, or after, particular headers.

    In the end, my code is arranged like this:

    #pragma once
    
    #include <SDKDDKVer.h>
    
    #pragma region Base Headers
    
    #define WIN32_LEAN_AND_MEAN             
    // Windows Header Files
    #include <windows.h>
    // C RunTime Header Files
    #include <stdlib.h>
    #include <malloc.h>
    #include <memory.h>
    #include <tchar.h>
    #include "resource.h"
    
    #pragma endregion // Base Headers
    
    #pragma region Project Headers
    
    #include <Winuser.h>
    #pragma comment(lib, "User32.lib")
    
    /* for use with ntohl function (winsock.h) */
    #include <winsock.h>
    #pragma comment(lib, "Ws2_32.lib")
    
    /* for use with Windows::Foundation::Initialize  */
    #include <roapi.h>        
    #pragma comment(lib, "runtimeobject.lib")
    
    #include <cstdlib>
    #include <ctime>
    
    #include <vector>
    
    #include <string> 
    #include <stdio.h>
    //#include <stdlib.h>
    #include <fstream>
    #include <sstream>
    #include <iostream>
    
    /* The contents of <filesystem> are available only
    with C++17 or later */
    #include <filesystem>
    
    #include <dxgitype.h>
    #include <thread>
    #include <shellapi.h> // drag n drop
    
    #include <d3d11.h> 
    #pragma comment(lib, "D3D11") 
    //#include <d3d11_1.h> 
    //#pragma comment(lib, "D3D11_1") 
    #include <d2d1.h> 
    #pragma comment(lib, "D2d1") 
    #include <d2d1_1.h> 
    #include <d2d1_2.h> 
    #include <d2d1_3.h> 
    //#include <dxgi.h>
    #include <dxgi1_2.h> 
    #pragma comment(lib, "DXGI")
    #include <d2d1helper.h>
    //#include <dwrite.h>
    #include <d3d10_1.h> 
    #pragma comment (lib, "D3D10_1") 
    //#include <d3d10.h> 
    ////#pragma comment (lib, "D3D10") 
    //#include <D3DX10math.h>
    
    #include <dcomp.h>  
    #pragma comment(lib, "dcomp") 
    
    #include <d3dcompiler.h>
    #pragma comment(lib, "d3dcompiler") 
    
    #include <Shobjidl.h>
    #include <strsafe.h>
    
    /* for use with PathCchRemoveFileSpec */
    #include <pathcch.h>
    #pragma comment(lib, "Pathcch.lib")
    
    #include <DirectXMath.h>
    #include <DirectXPackedVector.h>
    #include <DirectXCollision.h>
    
    #include <WindowsX.h> // GET_X_LPARAM; GET_Y_LPARAM
    
    /* use with WIC */
    #include <wincodec.h>
    #pragma comment(lib, "Windowscodecs.lib")
    
    #include <dwrite.h> //dwrite
    #pragma comment(lib, "dwrite.lib")
    
    #include <debugapi.h> // OutputDebugStringA
    
    #pragma endregion // Project Headers
    
    

    Shifting the position of some of these headers, will result in an error:

    Error LNK1000 Internal error during IncrBuildImage

    Or, I could be wrong, and the compiler is generating the error randomly.

    Once I inlined the variables in the DirectXMath header file, that fixed the errors with the DirectX headers.

        inline constexpr float XM_PI = 3.141592654f;
        inline constexpr float XM_2PI = 6.283185307f;
        inline constexpr float XM_1DIVPI = 0.318309886f;
        inline constexpr float XM_1DIV2PI = 0.159154943f;
        inline constexpr float XM_PIDIV2 = 1.570796327f;
        inline constexpr float XM_PIDIV4 = 0.785398163f;
        inline constexpr uint32_t XM_SELECT_0 = 0x00000000;
        inline constexpr uint32_t XM_SELECT_1 = 0xFFFFFFFF;
        inline constexpr uint32_t XM_PERMUTE_0X = 0;
        inline constexpr uint32_t XM_PERMUTE_0Y = 1;
        inline constexpr uint32_t XM_PERMUTE_0Z = 2;
        inline constexpr uint32_t XM_PERMUTE_0W = 3;
        inline constexpr uint32_t XM_PERMUTE_1X = 4;
        inline constexpr uint32_t XM_PERMUTE_1Y = 5;
        inline constexpr uint32_t XM_PERMUTE_1Z = 6;
        inline constexpr uint32_t XM_PERMUTE_1W = 7;
        inline constexpr uint32_t XM_SWIZZLE_X = 0;
        inline constexpr uint32_t XM_SWIZZLE_Y = 1;
        inline constexpr uint32_t XM_SWIZZLE_Z = 2;
        inline constexpr uint32_t XM_SWIZZLE_W = 3;
        inline constexpr uint32_t XM_CRMASK_CR6 = 0x000000F0;
        inline constexpr uint32_t XM_CRMASK_CR6TRUE = 0x00000080;
        inline constexpr uint32_t XM_CRMASK_CR6FALSE = 0x00000020;
        inline constexpr uint32_t XM_CRMASK_CR6BOUNDS = XM_CRMASK_CR6FALSE;
        inline constexpr size_t XM_CACHE_LINE_SIZE = 64;
    

    I probably don't need gdi headers, so I haven't tried fixing those errors, but everything works fine now.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.