Search code examples
visual-studionmake

MSVC nmake how to run nmake on makefile in subdirectory with consistent environment


I am trying to duplicate GNU make -C functionality of running nmake in a sub-directory working in a command-line environment (e.g. Developer PowerShell for VS 2022). The sub-directory contains a test suite and independent makefile that I would like to invoke for the test target in the root-level makefile. Searching for solutions I found most of them are variations on these answers:

MSVS2012 c++ nmake how do run nmake on a makefile in a subdirectory?

Setting NMake Makefile directory

but those solutions result in a fatal error:

LINK : fatal error LNK1104: cannot open file 'uuid.lib'
NMAKE : fatal error U1077: ...

How to make this sub-make call complete the build of test code properly?

More information:

  1. The Makefile.win in the sub-directory works fine when invoked directly.
  2. Tested with both VS2019 and VS2022.
  3. The root-level Makefile.win:
NODEBUG=1

INCS = -I.
OPTS = /O2 /D_CRT_SECURE_NO_WARNINGS
LIB = myio.lib
DLL = myio.dll

OBJS = myread.obj mywrite.obj

all: lib

lib: $(OBJS)
    link.exe /lib /nologo /out:$(LIB) $(OBJS)

dll: $(OBJS)
    link.exe /dll /nologo /out:$(DLL) $(OBJS)

.c.obj:
    $(CC) /nologo $(CFLAGS) $(INCS) $(OPTS) /c $<

# Run test suite
test: lib
    pushd $@ && $(MAKE) /NOLOGO /f Makefile.win /$(MAKEFLAGS) & popd
  1. The test\Makefile.win:
NODEBUG=1

INCS = -I. -I..
LIBS = ..\myio.lib
OPTS = /O2 /D_CRT_SECURE_NO_WARNINGS /nologo

TEST_RUNNER = test-runner.exe

test: $(TEST_RUNNER)
    $(TEST_RUNNER)

$(TEST_RUNNER): test-*.c
    $(CC) $(CFLAGS) $(INCS) $(OPTS) $** $(LIBS) /Fe: $@

A full run in Developer PowerShell for VS 2022:

> nmake -f Makefile.win test

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

        cl /nologo  -I. /O2 /D_CRT_SECURE_NO_WARNINGS /c myread.c
myread.c
        cl /nologo  -I. /O2 /D_CRT_SECURE_NO_WARNINGS /c mywrite.c
mywrite.c

        link.exe /lib /nologo /out:myio.lib myread.obj    mywrite.obj

        pushd test && "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.36.32532\bin\HostX86\x86\nmake.exe" /NOLOGO /f Makefile.win /                   & popd
        cl  -I. -I.. /O2 /D_CRT_SECURE_NO_WARNINGS /nologo test-read.c test-write.c ..\myio.lib /Fe: test-runner.exe
test-read.c
test-write.c
Generating Code...
LINK : fatal error LNK1104: cannot open file 'uuid.lib'
NMAKE : fatal error U1077: 'cl  -I. -I.. /O2 /D_CRT_SECURE_NO_WARNINGS /nologo test-read.c  test-write.c ..\myio.lib /Fe: test-runner.exe' : return code '0x2'
Stop.

Solution

  • Answering my own question for those that find this. Found the answer here: C: LINK.EXE fails from Makefile but not from the Command line

    The issue is that the root-level Makefile.win was setting LIB, which is used by the build environment.

    Change the root LIB and DLL declarations (and later usage) fixed the issue:

    MY_LIB = myio.lib
    MY_DLL = myio.dll