Nmake (Command Line)

From Crypto++ Wiki
Jump to navigation Jump to search

The Crypto++ library includes a Nmake makefile to build the library and test program from the command line. The Nmake makefile is more versatile than the Visual Studio solution or the MSBuild procedure because Nmake builds ARM and ARM64 versions of the library, too. In fact the Nmake makefile is the only way to build the library for ARM and ARM64 due to problems in the Visual Studio tooling.

Building the library using Nmake takes three steps and they are shown below. The output artifacts, object files, library files and cryptest.exe executable are placed in the Crypto++ directory. You can clean the artifacts with the clean target in the makefile.

The procedure below uses Visual Studio 2017 and its ARM64 Developer Command Prompt to demonstrate the Microsoft ARM64 toolchain. ARM, Win32 (x86) and Win64 (x86_64) are just as simple as ARM64. You should ensure you have the ARM64 build tools installed. They are part of the latest Windows Kit SDKs. If you need an Windows Kit or SDK then download it from Microsoft.

The Nmake makefile does not include notelemetry.obj. The object file is needed to suppress collection and sending user, device and application information to Microsoft. Microsoft surreptitiously added it to Visual Studio 2015, and claimed the failure to disclose was an oversight. Yeah, right...

Related wiki articles are MSBuild (Command Line), MinGW (Command Line), Visual Studio, FIPS DLL and Wrapper DLL.

Command Prompt

ARM64 Cross Tools Command Prompt

The first step is to open an ARM64 Developer Command Prompt. Navigate to StartProgramsVisual Studio 2017Visual Studio ToolsVCARM64_x86 Cross Tools Command Prompt.

If the shortcut is missing, you can create a new shortcut and make its Target %comspec% /k "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsamd64_arm64.bat".

Once you open the Developer Command Prompt you should see a message [vcvarsall.bat] Environment initialized for: 'x64_arm64'. You can verify the compiler by executing cl.exe. You should see a message similar to Compiler Version 19.16 for ARM64.

C:\Users\Test>cl.exe
Microsoft (R) C/C++ Optimizing Compiler Version 19.16.27025.1 for ARM64
Copyright (C) Microsoft Corporation.  All rights reserved.
...

Nmake Options

The second step to building the library using Nmake is tune cryptest.nmake. The Nmake makefile should be OK out of the box and correctly detect x86, x64, ARM and ARM64 environments. If not then you should tune the makefile.

By default cryptest.nmake builds a release version of the library. The debug/release options are around line 150 of the Nmake makefile.

# Compiler debug build.
# CXXFLAGS = $(CXXFLAGS) /DDEBUG /D_DEBUG /Oi /Oy- /Od /MTd
# Compiler release build.
CXXFLAGS = $(CXXFLAGS) /DNDEBUG /D_NDEBUG /Oi /Oy /O2 /MT

# Linker debug build.
# LDFLAGS = $(LDFLAGS) /DEBUG
# Linker release build.
LDFLAGS = $(LDFLAGS) /DEBUG /OPT:REF

The Nmake makefile uses the static C++ runtime linking by default. Static C++ runtime linking sometimes requires the changes from Visual Studio Runtime Linking. If you want to use dynamic runtime linking then change from /MTd and /MT to /MDd and /MD.

Other options include the Metro app settings. For ARM and ARM64 the library is configured for WINAPI_FAMILY_PHONE_APP. You can change the Metro app settings to one of the following by adding the appropriate define to CXXFLAGS:

# To test Desktop app, use the following CXXFLAGS:
#   - /DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP
# To test Windows Store app, use the following CXXFLAGS:
#   - /DWINAPI_FAMILY=WINAPI_FAMILY_APP
# To test Windows Phone, use the following CXXFLAGS:
#   - /DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP
# To test Surface RT (ARM tablet), use the following CXXFLAGS:
#   - /D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1 /DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP

Running Nmake

Running Nmake for ARM64

The third step in building the library is running Nmake. To run Nmake issue nmake /f cryptest.nmake. You should see output similar to below.

C:\Users\Test\cryptopp>nmake /f cryptest.nmake

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

******************************
Platform is arm64
******************************

        cl.exe /nologo /W4 /wd4231 /wd4511 /wd4156 /D_MBCS /Zi /TP /GR /EHsc /DN
DEBUG /D_NDEBUG /Oi /Oy /O2 /MT /FI sdkddkver.h /FI winapifamily.h /DWINAPI_FAMI
LY=WINAPI_FAMILY_PHONE_APP /c cryptlib.cpp
cryptlib.cpp
        cl.exe /nologo /W4 /wd4231 /wd4511 /wd4156 /D_MBCS /Zi /TP /GR /EHsc /DN
DEBUG /D_NDEBUG /Oi /Oy /O2 /MT /FI sdkddkver.h /FI winapifamily.h /DWINAPI_FAMI
LY=WINAPI_FAMILY_PHONE_APP /c cpu.cpp
cpu.cpp
        cl.exe /nologo /W4 /wd4231 /wd4511 /wd4156 /D_MBCS /Zi /TP /GR /EHsc /DN
DEBUG /D_NDEBUG /Oi /Oy /O2 /MT /FI sdkddkver.h /FI winapifamily.h /DWINAPI_FAMI
LY=WINAPI_FAMILY_PHONE_APP /c integer.cpp
integer.cpp
...

The build stage should finish by linking cryptest.exe.

        link.exe /nologo /SUBSYSTEM:CONSOLE /DEBUG /DEBUG /OPT:REF test.obj benc
h1.obj bench2.obj bench3.obj datatest.obj  dlltest.obj fipsalgt.obj validat0.obj
 validat1.obj validat2.obj  validat3.obj validat4.obj validat5.obj validat6.obj
validat7.obj  validat8.obj validat9.obj validat10.obj regtest1.obj regtest2.obj
 regtest3.obj regtest4.obj cryptlib.lib  /out:cryptest.exe

Test Program

If you build for Win32 (x86) or Win64 (x86_64) then you can run the test program. Run the test program from the command line by issuing .\cryptest.exe v. You should see output similar to below.

C:\Users\Test\cryptopp>.\cryptest.exe v
Using seed: 1571534358

Testing Settings...

passed:  Your machine is little endian.
passed:  Aligned data access.
passed:  sizeof(byte) == 1
passed:  sizeof(word16) == 2
passed:  sizeof(word32) == 4
passed:  sizeof(word64) == 8
passed:  sizeof(hword) == 4, sizeof(word) == 8
passed:  cacheLineSize == 64
hasSSE2 == 1, hasSSSE3 == 1, hasSSE4.1 == 1, hasSSE4.2 == 1, hasAVX == 1, hasAVX2
 == 0, hasAESNI == 1, hasCLMUL == 1, hasRDRAND == 0, hasRDSEED == 0, hasSHA == 0
...

We don't know how to test an ARM or AMR64 build. Microsoft appears to lack a command line tool to push a program to a device or obtain a remote shell, like Android's adb.

When finished you can clean with nmake /f cryptest.nmake clean.