Search code examples
c++windowsvisual-studiobuildnmake

Visual Studio NMake build fails with: fatal error U1052: file 'win32.mak' not found


[MS.Docs]: Sample Makefile (for VStudio 2022 (17) at question creation time) contains the following (Makefile.mak):

# Sample makefile

!include <win32.mak>

all: simple.exe challeng.exe

.c.obj:
  $(cc) $(cdebug) $(cflags) $(cvars) $*.c

simple.exe: simple.obj
  $(link) $(ldebug) $(conflags) -out:simple.exe simple.obj $(conlibs) lsapi32.lib

challeng.exe: challeng.obj md4c.obj
  $(link) $(ldebug) $(conflags) -out:challeng.exe $** $(conlibs) lsapi32.lib

which doesn't work OOTB:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q073159159]> sopr.bat
### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###

[prompt]> "c:\Install\pc032\Microsoft\VisualStudioCommunity\2019\VC\Auxiliary\Build\vcvarsall.bat" x64 > nul

[prompt]> nmake /f Makefile.mak

Microsoft (R) Program Maintenance Utility Version 14.29.30146.0
Copyright (C) Microsoft Corporation.  All rights reserved.

Makefile.mak(3) : fatal error U1052: file 'win32.mak' not found
Stop.

Results on the web (especially SO) are a lot scarcer than I expected:


Solution

  • The 2 files (Win32.mak - and its wrapper NtWin32.mak) are part of Microsoft Windows SDK for Windows 7 and .NET Framework 4.
    It's the SDK version pairing VStudio 2010 (10) and VStudio 2012 (11) according to (unofficial) [Wikipedia]: Microsoft Windows SDK. For some reason their presence has been discontinued in newer SDK versions. One possible reason (as stated by one of the URLs in the question) is that MS is encouraging MSBuild usage.

    There are 2 steps required in order to make things work.

    1. Get the files locally

    There are a couple of ways to achieve this:

    1. They might already be present. If any of the 2 VStudio versions mentioned at the beginning is installed, then this SDK version was most likely automatically installed as well. Since both VStudio versions are pc032 (032bit), then the SDK is expected to be pc032 as well. As a consequence, files location is typically: C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include.
      Note that version might also be v7.0A, but I'll use the former one as it's newer (and the 2 files are identical in these 2 versions).

      Note: since I have 9 different VStudio versions installed (v2010 and v2012 among them), I have these files as well

    2. Download and install the SDK manually

      Note: check [MS.Developer]: Windows SDK and emulator archive for SDK versions.

      Installation of the (old) version might be a bit problematic on Win10+ versions. For example, in my case just after launching the (pc064) installer, I got:

      Img0

      Since I already had the files, didn't go through with the installer. But the topic is discussed on [MS.MSDN.Social]: Windows SDK 7.1 on Windows 10.

    3. Get the files from [GitHub]: CristiFati/MSSDKFiles - (v7.1A_w10) Microsoft Windows SDK for Windows 7 and .NET Framework 4. Since none of the 2 ways above is very user friendly (not to mention that installing requires Administrator privileges), I uploaded them in this repository, where they can be downloaded from (using browser, Git, ...).
      Note: Some of the files contain modifications (to accommodate (some) macro values corresponding to newer Win versions: Win 8, Win 10, ...).

    2. Add them to NMake system

    At the end of previous section, the 2 files should exist somewhere locally. For simplicity's sake, I'll be using as a test file:

    Makefile.mak:

    # Dummy Makefile
    
    !include <win32.mak>
    
    all:
        @echo Executing target: $@ ($(MAKEDIR))
    

    For building on Win examples, might want to check:

    I'll be working with VStudio 2019 (and reuse the same Cmd console):

    [cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q073159159]> sopr.bat
    ### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###
    
    [prompt]> "c:\Install\pc032\Microsoft\VisualStudioCommunity\2019\VC\Auxiliary\Build\vcvarsall.bat" x64 > nul
    
    [prompt]> nmake /nologo /f Makefile.mak
    Makefile.mak(3) : fatal error U1052: file 'win32.mak' not found
    Stop.
    
    [prompt]> echo %INCLUDE%
    c:\Install\pc032\Microsoft\VisualStudioCommunity\2019\VC\Tools\MSVC\14.29.30133\ATLMFC\include;c:\Install\pc032\Microsoft\VisualStudioCommunity\2019\VC\Tools\MSVC\14.29.30133\include;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um;C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\ucrt;C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\shared;C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\um;C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\winrt;C:\Program Files (x86)\Windows Kits\10\include\10.0.22000.0\cppwinrt
    
    [prompt]>
    
    1. Copy files in VStudio's Include dir (as instructed by some of the URLs in the question)

      It doesn't work OOTB, as newer VStudio versions no longer have a generic "Include" dir, but they rather "delegate this task" to a subcomponent (and dir) called Tools

      • The advantage is that it only needs to be done once (per VStudio version and VStudio Tools version)

      • The disadvantage: don't do it unless you really know what you're doing (in which case required administrative privileges shouldn't be a problem). Messing up with system files repeatedly, might become a habit, and there's a great chance of overwriting (or deleting) something at one point, and therefore corrupting program installations (or even the OS)

      Example:

      [prompt]> :: @TODO - cfati: DON'T DO THIS! (Demo purposes only)
      [prompt]> echo %VCToolsInstallDir%
      c:\Install\pc032\Microsoft\VisualStudioCommunity\2019\VC\Tools\MSVC\14.29.30133\
      
      [prompt]> copy "e:\Work\Dev\GitHub\CristiFati\MSSDKFiles\src\Include\Win32.mak" "%VCToolsInstallDir%\include"
              1 file(s) copied.
      
      [prompt]> nmake /nologo /f Makefile.mak
      Executing target: all (e:\Work\Dev\StackOverflow\q073159159)
      
      [prompt]> :: Cleanup
      [prompt]> del /f "%VCToolsInstallDir%\include\Win32.mak"
      
      [prompt]> nmake /nologo /f Makefile.mak
      Makefile.mak(3) : fatal error U1052: file 'win32.mak' not found
      Stop.
      
      [prompt]>
      
    2. Add files location (dir) to %INCLUDE% env var (the other way around)

      if defined INCLUDE (set INCLUDE=%INCLUDE%;${Win32Mak_Directory}) else (set INCLUDE=${Win32Mak_Directory})
      

      ${Win32Mak_Directory} is a placeholder for the actual path.

      Safe, it can't do any damage (at least not a permanent one, worst thing that could happen is messing up the environment in the current Cmd console, starting another would fix it). The problem is that it would have to be done every time building is required (after calling VCVarsAll), which (if happens often) can become annoying. To get rid of the "monkey work", change the (current user's) env vars (once) from either:

      • GUI (Control Panel -> System and Security - >Advanced system settings (sysdm.cpl) -> System Properties -> Environment Variables -> New)

        Img1

        If the variable is already defined, append ${Win32Mak_Directory} to the existing value, separated by a SemiColon (;)

      • CmdLine ([MS.Docs]: setx)

        if defined INCLUDE (setx INCLUDE %INCLUDE%;${Win32Mak_Directory}) else (setx INCLUDE ${Win32Mak_Directory})
        if defined INCLUDE (set INCLUDE=%INCLUDE%;${Win32Mak_Directory}) else (set INCLUDE=${Win32Mak_Directory})
        

        Note: The if defined part (which seems odd - and a bit too complex) is required to work in Cmd (Win 10 - check behavior below):

        [prompt]> set _UNSET=
        
        [prompt]> echo %_UNSET% ??? WTH ???
        %_UNSET% ??? WTH ???
        

        When placed in a .bat file, everything is normal (only the contents in the 1st parentheses is enough)

      Of course, there's the option of doing it directly from the registry, but I'm not going to insist on it.

      Example:

      [prompt]> set _INCLUDE=%INCLUDE%
      
      [prompt]> set INCLUDE=%INCLUDE%;e:\Work\Dev\GitHub\CristiFati\MSSDKFiles\src\Include
      
      [prompt]> nmake /nologo /f Makefile.mak
      Executing target: all (e:\Work\Dev\StackOverflow\q073159159)
      
      [prompt]> :: Cleanup
      [prompt]> set INCLUDE=%_INCLUDE%
      
      [prompt]> nmake /nologo /f Makefile.mak
      Makefile.mak(3) : fatal error U1052: file 'win32.mak' not found
      Stop.
      
      [prompt]>
      
    3. Create a wrapper over VCVarsAll and call that one instead

      The wrapper would:

      • Call VCVarsAll

      • Adjust the %INCLUDE% env var (check previous item (#2.))

      (in any order), but I'm not going to go into more details



    Summary

    The simplest step sequence (only required once) to get things going:

    1. Get files from [GitHub]: CristiFati/MSSDKFiles - (v7.1A_w10) Microsoft Windows SDK for Windows 7 and .NET Framework 4 (tag v7.1A_original contains the files got from MS)

      1. The (green) button (combo-box) Code -> Download ZIP

      2. Unpack the downloaded archive contents in a folder. Let's refer to it by ${MS71SDK} (whenever seen in a command, replace it with the actual path). The files will be located in ${MS71SDK}\Include

    2. Add their location to %INCLUDE% env var (from Cmd)

      set MS71SDKINC=${MS71SDK}\Include
      if defined INCLUDE (setx INCLUDE %INCLUDE%;%MS71SDKINC%) else (setx INCLUDE %MS71SDKINC%)
      if defined INCLUDE (set INCLUDE=%INCLUDE%;%MS71SDKINC%) else (set INCLUDE=%MS71SDKINC%)
      
    3. Build normally. NMake will pick the changes up