noloader / cryptopp-cmake

CMake files for Crypto++ project
BSD 3-Clause "New" or "Revised" License
92 stars 68 forks source link

winapifamily.h fix #38

Closed Wunkolo closed 3 years ago

Wunkolo commented 5 years ago

For some reason this file is being force-included into windows builds and causes plenty of '"winapifamily.h"': No such file or directory errors while building. Commenting the line seems to solve the issue for me(Visual studio 2017 Enterprise).

Though with my shallow understanding of how Windows SDKs are organized, I think you meant to do this:

if (MSVC)
  if (CMAKE_SYSTEM_VERSION MATCHES "10\\.0.*")
    list(APPEND CRYPTOPP_COMPILE_DEFINITIONS "_WIN32_WINNT=0x0A00")
  else ()
    list(APPEND CRYPTOPP_COMPILE_OPTIONS "/FI\"winapifamily.h\"")
  endif ()
endif ()

As the newer Windows 10 SDKs don't have winapifamily.h, but the older Windows 8-and-below sdks have winapifamily.h in their shared directory. I think SDL ran into a similar issue with the newer SDKs.

noloader commented 5 years ago

Thanks @Wunkolo,

Forgive my ignorance... Would it be possible to have CMake test for the availability of winapifamily.h and include the header if found? Something like:

if (EXISTS winapifamily.h)
    list(APPEND CRYPTOPP_COMPILE_OPTIONS "/FI\"winapifamily.h\"")
endif ()

The tricky part seems to be, CMake must use the dev environment [include?] paths, and not just cwd. I don't know how to ask CMake to use a potential SDK path during its search.

Ping @jcfr, @abdes, @MarcelRaad

MarcelRaad commented 5 years ago

My Windows 10 SDK does have winapifamily.h. It's in C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\shared.

noloader commented 5 years ago

Maybe we should try a test compile using CheckCompilerOption, with the option being /FI "winapifamily.h". It looks like something needs to be plumbed in for MSVC:

function(CheckCompilerOption opt var)

  if (MSVC)

    # CMake does not provide a generic shell/terminal mechanism
    #  and Microsoft environments don't know what 'sh' is.
    set(${var} 0 PARENT_SCOPE)

  elseif (CMAKE_CXX_COMPILER_ID MATCHES "SunPro")

    message(STATUS "Performing Test ${var}")
    execute_process(
      COMMAND sh -c "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} ${opt} -c ${TEST_SOURCE_FILE} 2>&1"
      COMMAND ${GREP_CMD} -i -c -E "illegal value ignored"
      RESULT_VARIABLE COMMAND_RESULT
      OUTPUT_VARIABLE COMMAND_OUTPUT
      OUTPUT_STRIP_TRAILING_WHITESPACE)
      ...

endfunction(CheckCompilerOption)

I'm guessing execute_process(COMMAND cmd.exe /c ...) will produce incorrect results because we will use a new Command Prompt, and not the existing Developer Prompt.

Does anyone know how to use the current shell in the MSVC path?

noloader commented 5 years ago

This looks relevant from Stack Overflow: How to check in cmake whether a given header file is available for C++ project. @Wunkolo, can you test this change:

if (MSVC)
  if (CMAKE_SYSTEM_VERSION MATCHES "10\\.0.*")
    list(APPEND CRYPTOPP_COMPILE_DEFINITIONS "_WIN32_WINNT=0x0A00")
  endif ()
  CHECK_INCLUDE_FILE_CXX("winapifamily.h" HAVE_WINAPIFAMILY)
  if (HAVE_WINAPIFAMILY)
    list(APPEND CRYPTOPP_COMPILE_OPTIONS "/FI\"winapifamily.h\"")
  endif ()
endif ()
noloader commented 5 years ago

OK, so I tried to test the CHECK_INCLUDE_FILE_CXX change as described above in a VS 2015 x86 Developer Prompt. It looks like something went sideways. CMakeLists.txt:36 sets the Crypto++ version number via project(cryptopp VERSION 7.0.0).

I don't see where MSBuild factors into things. Our CMakeLists.txt does not use MSBuild. It relies upon command line gear, like g++ and cl.exe. The Developer Prompt has the environment set:

C:\Users\Test\Desktop\cryptopp\cmake_build>echo %INCLUDE%
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE;C:\Program Files
(x86)\Microsoft Visual Studio 14.0\VC\ATLMFC\INCLUDE;C:\Program Files (x86)\Wind
ows Kits\10\include\10.0.16299.0\ucrt;C:\Program Files (x86)\Windows Kits\NETFXS
DK\4.6.1\include\um;C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\
shared;C:\Program Files (x86)\Windows Kits\10\include\10.0.16299.0\um;C:\Program
 Files (x86)\Windows Kits\10\include\10.0.16299.0\winrt;

And the tools are on-path:

C:\Users\Test\Desktop\cryptopp\cmake_build>cl.exe
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24210 for x86

Maybe someone more experienced with CMake on Windows can test it.


C:\Users\Test\Desktop\cryptopp\cmake_build>"c:\Program Files (x86)\CMake\bin\cma
ke.exe" ..
-- Building for: Visual Studio 15 2017
-- *************************************************************************
The Crypto++ library does not officially support CMake. CMake support is a
community effort, and the library works with the folks using CMake to help
improve it. If you find an issue then please fix it or report it at
https://github.com/noloader/cryptopp-cmake.
-- *************************************************************************
-- Selecting Windows SDK version 10.0.16299.0 to target Windows 6.3.9600.
CMake Error at CMakeLists.txt:36 (project):
  Failed to run MSBuild command:

    C:/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools/MSBuild/15.0/
Bin/MSBuild.exe

  to get the value of VCTargetsPath:

    Microsoft (R) Build Engine version 15.6.85.37198 for .NET Framework
    Copyright (C) Microsoft Corporation. All rights reserved.

    Build started 10/29/2018 5:46:37 AM.
    Project "C:\Users\Test\Desktop\cryptopp\cmake_build\CMakeFiles\3.12.3\VCTarg
etsPath.vcxproj" on node 1 (default targets).
    C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\v140\Microsoft.Cpp.Platfor
m.targets(57,5): error MSB8020: The build tools for v141 (Platform Toolset = 'v1
41') cannot be found. To build using the v141 build tools, please install v141 b
uild tools.  Alternatively, you may upgrade to the current Visual Studio tools b
y selecting the Project menu or right-click the solution, and then selecting "Re
target solution". [C:\Users\Test\Desktop\cryptopp\cmake_build\CMakeFiles\3.12.3\
VCTargetsPath.vcxproj]
    Done Building Project "C:\Users\Test\Desktop\cryptopp\cmake_build\CMakeFiles
\3.12.3\VCTargetsPath.vcxproj" (default targets) -- FAILED.

    Build FAILED.

    "C:\Users\Test\Desktop\cryptopp\cmake_build\CMakeFiles\3.12.3\VCTargetsPath.
vcxproj" (default target) (1) ->
    (PlatformPrepareForBuild target) ->
      C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\v140\Microsoft.Cpp.Platf
orm.targets(57,5): error MSB8020: The build tools for v141 (Platform Toolset = '
v141') cannot be found. To build using the v141 build tools, please install v141
 build tools.  Alternatively, you may upgrade to the current Visual Studio tools
 by selecting the Project menu or right-click the solution, and then selecting "
Retarget solution". [C:\Users\Test\Desktop\cryptopp\cmake_build\CMakeFiles\3.12.
3\VCTargetsPath.vcxproj]

        0 Warning(s)
        1 Error(s)

    Time Elapsed 00:00:07.60

  Exit code: 1

-- Configuring incomplete, errors occurred!
See also "C:/Users/Test/Desktop/cryptopp/cmake_build/CMakeFiles/CMakeOutput.log"
LonghronShen commented 5 years ago

The above solution doesn't work for me... But I found another solution: According to the answer here: https://stackoverflow.com/questions/40577415/detect-availablility-of-sdkddkver-h-and-winapifamily-h-from-developer-comman The CMakeList.txt can be modified like this:

if (MSVC)
  if (CMAKE_SYSTEM_VERSION MATCHES "10\\.0.*")
    list(APPEND CRYPTOPP_COMPILE_DEFINITIONS "_WIN32_WINNT=0x0A00")
  endif ()
  if (WINDOWSPHONEKITDIR OR UNIVERSALCRTSDKDIR OR UCRTVERSION)
    list(APPEND CRYPTOPP_COMPILE_OPTIONS "/FI\"winapifamily.h\"")
  endif ()
endif ()

I have created another pull request #39