Finding DirectX12 libraries with CMake and MinGW - c

I am trying to use CMake to find DirectX 12 and link it against an executable. What I have so far works when compiling with MSVC, but fails when compiling with GCC:
Could NOT find D3D12 (missing: D3D12_LIBRARIES).
I am using a slightly altered version of the FindD3D12.cmake:
# Find the win10 SDK path.
if ("$ENV{WIN10_SDK_PATH}$ENV{WIN10_SDK_VERSION}" STREQUAL "" )
get_filename_component(WIN10_SDK_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\v10.0;InstallationFolder]" ABSOLUTE CACHE)
get_filename_component(TEMP_WIN10_SDK_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\v10.0;ProductVersion]" ABSOLUTE CACHE)
get_filename_component(WIN10_SDK_VERSION ${TEMP_WIN10_SDK_VERSION} NAME)
elseif(TRUE)
set (WIN10_SDK_PATH $ENV{WIN10_SDK_PATH})
set (WIN10_SDK_VERSION $ENV{WIN10_SDK_VERSION})
endif ("$ENV{WIN10_SDK_PATH}$ENV{WIN10_SDK_VERSION}" STREQUAL "" )
# WIN10_SDK_PATH will be something like C:\Program Files (x86)\Windows Kits\10
# WIN10_SDK_VERSION will be something like 10.0.14393 or 10.0.14393.0; we need the
# one that matches the directory name.
if (IS_DIRECTORY "${WIN10_SDK_PATH}/Include/${WIN10_SDK_VERSION}.0")
set(WIN10_SDK_VERSION "${WIN10_SDK_VERSION}.0")
endif (IS_DIRECTORY "${WIN10_SDK_PATH}/Include/${WIN10_SDK_VERSION}.0")
# Find the d3d12 and dxgi include path, it will typically look something like this.
# C:\Program Files (x86)\Windows Kits\10\Include\10.0.10586.0\um\d3d12.h
# C:\Program Files (x86)\Windows Kits\10\Include\10.0.10586.0\shared\dxgi1_4.h
find_path(
D3D12_INCLUDE_DIR # Set variable D3D12_INCLUDE_DIR
d3d12.h # Find a path with d3d12.h
HINTS "${WIN10_SDK_PATH}/Include/${WIN10_SDK_VERSION}/um"
DOC "path to WIN10 SDK header files"
HINTS
)
find_path(
DXGI_INCLUDE_DIR # Set variable DXGI_INCLUDE_DIR
dxgi1_4.h # Find a path with dxgi1_4.h
HINTS "${WIN10_SDK_PATH}/Include/${WIN10_SDK_VERSION}/shared"
DOC "path to WIN10 SDK header files"
HINTS
)
set(D3D12_INCLUDE_DIRS ${D3D12_INCLUDE_DIR} ${DXGI_INCLUDE_DIR})
# Find D3D libraries
set(D3D12_LIB_NAMES d3d12.lib dxgi.lib d3dcompiler.lib dxguid.lib)
set(D3D12_LIBRARIES)
foreach (D3D12_LIB_NAME ${D3D12_LIB_NAMES})
find_library(${D3D12_LIB_NAME}_LOC NAMES ${D3D12_LIB_NAME} HINTS ${D3D12_HINTS_PATH})
set(D3D12_LIBRARIES ${D3D12_LIBRARIES} ${${D3D12_LIB_NAME}_LOC})
endforeach(D3D12_LIB_NAME)
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set D3D12_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(
D3D12 DEFAULT_MSG
D3D12_INCLUDE_DIRS D3D12_LIBRARIES
)
mark_as_advanced(D3D12_INCLUDE_DIRS D3D12_LIBRARIES)
And then linking it with: target_link_libraries(<name> ${D3D12_LIBRARIES}).
The D3D12_INCLUDE_DIRS variable is set to the correct value, the problem is only with the libraries.
Are the DirectX 12 libraries not compatible with GCC and CMake is smart enough to figure that out, or am I doing something wrong when trying to find them?
Edit:
As the answer mentioned, the FindD3D12.cmake module is not needed. The DirectX libraries are system libraries when compiling on Windows, so doing target_link_libraries(<name> PRIVATE d3d12.lib dxgi.lib d3dcompiler.lib dxguid.lib) works.

======================================================
Windows:
DirectX is part of the Windows SDK.
If you have are compiling on Windows there is no way you aren't using the SDK to compile. Therefor don't worry about handling the include directories and whatnot.
Therefore you can treat the Directx libraries as regular system libraries and the following command will work. That's the magic of cmake.
So most of your cmake isn't really necessary. At least if you are using visual studio.
If you aren't using visual studio you might need to write up a toolchain (https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html?highlight=cmake_cxx_compiler_id#cmake-toolchains-7)
# DX12 libraries
target_link_libraries(foobar PRIVATE
d3d12.lib
dxgi.lib
dxguid.lib
)
======================================================
Linux:
Secondly DirectX12 will have linux support:
https://devblogs.microsoft.com/directx/directx-heart-linux/
However I don't think it allows use of graphics functionality, just the compute functionality. But regardless assuming Microsoft didn't make it extremely painful the cmake should be roughly similar.
======================================================
Lastly if you wanna know what version of the SDK you are building against check out CMAKE_SYSTEM_VERSION
On windows setting this before the first project call sets the SDK version. Because that's what the SDK versions stand for. Versions of windows builds.
Also to be extra cautious add extra static_asserts in your codebase to make sure you are using a version of the SDK you intended you'll want to include "Windows.h" which you probably already have anyway. And then check for the compiler definitions that tell you what Version of the Windows OS you are compiling.
"When you use the Windows SDK, you can specify which versions of Windows your code can run on. The preprocessor macros WINVER and _WIN32_WINNT specify the minimum operating system version your code supports. Visual Studio and the Microsoft C++ compiler support targeting Windows 7 SP1 and later. Older toolsets include support for Windows XP SP2, Windows Server 2003 SP1, Vista, and Windows Server 2008. Windows 95, Windows 98, Windows ME, Windows NT, and Windows 2000 are unsupported." - Microsoft Documentation (https://learn.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-160)

Are the DirectX 12 libraries not compatible with GCC
Every compiler has its own library format, cl uses .lib libraries and gcc uses .a and .so libraries. You can't just take cl's libraries (which is what is stored in the Windows SDK) and feed them to gcc.

Related

VS2019 linux header files

I'm experimenting with developing C code for linux using VS2019.
I'm finding that whilst many Linux headers such as sys/types.h and sched.h are being found OK, others, such as sys/syscall.h and fcntl.h are not being found.
I can see that it has a local copy of many headers such as stdint.h in local linux platform directory...can I just cut and paste the missing ones from the target machine?
I rather suspect that if common headers such as unistd.h are missing there is a reason, and I don't want to mess things up!
From Microsoft's documentation:
By default, Visual Studio does not include any system-level include
files from the Linux computer. For example, items in the /usr/include
directory are not present in Visual Studio. For full IntelliSense
support, you will need to copy those files to some location on your
development computer and point Visual Studio to this location. One
option is to use scp (Secure Copy) to copy the files. On Windows 10,
you can use Bash on Windows to run scp. For previous versions of
Windows, you could use something like PSCP (PuTTY Secure Copy).
You can copy the files by using a command similar to the following:
scp -r linux_username#remote_host:/usr/include .
Of course, replace the linux_username and remote_host values above for
what's appropriate in your own environment.
Once the files are copied, use the VC++ Directories item in Project
properties to tell Visual Studio where to find the additional include
files that were just copied.

C++ Library Package Manager for Clang/LLVM

I'm using Visual Studio 2017 as my IDE. I've set the "Platform Toolset" option (right-click the project and select "Properties". Then go to Configuration Properties > General) to be "LLVM-vs2014_xp" which is Clang/LLVM. This is in-place of the standard Visual Studio 2017 toolset which uses the MSVC compiler.
Now, before I was using vcpkg to handle installing C++ libraries for the MSVC compiler, and it was quite simple. If I wanted to install Boost, msgpack, Modern JSON for C++, and a variety of other C++ libraries, I just had to type in the terminal:
vcpkg install boost
Or equivalent. And my libraries would be found if I included the appropriate header in source code.
Now that I have switched to Clang/LLVM, when building in Visual Studio the Clang compiler can't find the same libraries. I am trying to avoid manually telling the Linker where certain things are/editing the Path variables like "Include Directories" and "Library Directories".
Does anyone know of an equivalent package manager to vcpkg for Clang?
Alternatively, if you know of a way to tell Clang to look for the vcpkg libraries that is simple, that is fine as well. I have already tried setting the "Include Directories" and "Library Directories" to the same values as for when Visual Studio toolset is set, with no luck.
EDIT: It now occurs to me that it might be possible to solve this by copying all tab values from "VC++ Directories" for when Visual C++ (MSVC) is the toolset to when Clang is the toolset. I may attempt...
EDIT 2: Do not attempt the edit above i.e. copying those tab values from the Visual C++ toolset properties. It just creates a bunch of linker errors...
Set the following under Configuration Properties>VC++ Directories:
"Include Directories" to include "C:\Program Files\vcpkg\installed\x86-windows\include"
and
"Library Directories" to include "C:\Program Files\vcpkg\installed\x86-windows\lib"
This links the vcpkg libraries and header files to the Clang/LLVM toolset!
Your directories might be in different locations so just set the paths appropriately for your setup.

How to circumvent Windows Universal CRT headers dependency on vcruntime.h

In trying to evaluate Clang on Windows, utilizing the Windows Universal C Run-Time (...\Windows Kits\10\Include\10.0.15063.0\ucrt) I was immediately facing unexpected wall, in the form of an undisclosed and unexpected dependency on Microsoft's Visual Studio. Apparently even the simplest C program will not be able to compile as soon as you include any standard C header, because they all seem to end-up attempting to #include vcruntime.h (which is not part of the UCRT).
My questions are:
Is there a way to utilize the Windows Universal C RTL SDK withOUT Visual Studio?
If it is not intended or possible, why then is it not called "Windows CRT for Microsoft VC" - what am I missing?
Check out [MSDN.Blogs]: Introducing the Universal CRT (and also the other URLs that it references). Emphases are mine:
In June of last year we published a pair of articles discussing the major changes that we had made to the Visual C++ C Runtime (CRT) for Visual Studio 2015. ...
The AppCRT and DesktopCRT have been recombined into a single library, which we have named the Universal CRT. The new DLLs are named ucrtbase.dll (release) and ucrtbased.dll (debug); they do not include a version number because we’ll be servicing them in-place.
From [MS.DevBlogs]: The Great C Runtime (CRT) Refactoring
In order to unify these different CRTs, we have split the CRT into three pieces:
VCRuntime (vcruntime140.dll) ...
AppCRT (appcrt140.dll) ...
DesktopCRT (desktopcrt140.dll) ...
According to [MS.Support]: Update for Universal C Runtime in Windows:
Microsoft Visual Studio 2015 creates a dependency on the Universal CRT when applications are built by using the Windows 10 Software Development Kit (SDK).
and from [MS.Dev]: Windows 10 SDK:
Note: Windows 10 development targeting Windows 10, version 1803 (or later) requires Visual Studio 2017. This SDK will not be discovered by previous versions of Visual Studio.
So, UCRT is strictly bound to VStudio. Universal: means that it's not dependent on VStudio version (all VStudio versions will use a common one (there can be only one)).
Personal opinion: UCRT is the Win (wannabe) equivalent of Nix's libc.
I took a look in SDK include dir (e.g. "%ProgramFiles(x86)%\Windows Kits\10\Include\10.0.15063.0\ucrt"):
Every common file (e.g. stdio.h) has an #include <corecrt.h>
corecrt.h has an #include <vcruntime.h>
no #ifdefs, so there is no way (at least no easy one) to overcome this.
But, things are even clearer when reaching link phase. If your C code includes UCRT headers, it will (most likely) link to files from SDK lib dir (e.g. "%ProgramFiles(x86)%\Windows Kits\10\Lib\10.0.15063.0\ucrt\x64"), which are generated by VStudio, and there's a great chance for that to fail. Example:
code00.c:
//#include <stdio.h>
int main()
{
//printf("Dummy.... sizeof(void*): %d\n", sizeof(void*));
return 0;
}
Output:
[cfati#CFATI-5510-0:e:\Work\Dev\StackOverflow\q045340527]> sopr.bat
### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###
[prompt]> dir /b
code00.c
[prompt]> "c:\Install\x86\Microsoft\Visual Studio Community\2015\VC\bin\cl.exe" -nologo -c -Focode00.obj code00.c
code00.c
[prompt]> "c:\Install\Google\Android_SDK\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang.exe" -c -m64 -o code00.o code00.c
[prompt]> dir /b
code00.c
code00.o
code00.obj
The 2 (generated) files are incompatible:
[prompt]> "C:\Install\x86\Microsoft\Visual Studio Community\2015\VC\bin\amd64\dumpbin.exe" -nologo code00.obj
Dump of file code00.obj
File Type: COFF OBJECT
Summary
80 .debug$S
2F .drectve
7 .text$mn
[prompt]> "C:\Install\x86\Microsoft\Visual Studio Community\2015\VC\bin\amd64\dumpbin.exe" -nologo code00.o
Dump of file code00.o
code00.o : warning LNK4048: Invalid format file; ignored
Summary
[prompt]> "c:\Install\x64\Cygwin\Cygwin\AllVers\bin\readelf.exe" -d code00.o
[prompt]> "c:\Install\x64\Cygwin\Cygwin\AllVers\bin\readelf.exe" -d code00.obj
readelf: Error: Not an ELF file - it has the wrong magic bytes at the start
Now, I know that lld (I remember that I built it in the past, but I can't find it, in order to test my statement) is able to link both ELF and COFF file formats, but I doubt that it can combine them.
Conclusion
Based on the above, here are the answers (that I could come up with) to your questions:
I suppose it is - an unsupported one though (claiming that something is impossible is almost always false). But, there would be lots of restrictions (consider the above file format matching), and would most likely require some dirty tricks or (lame) workarounds (gainarii) like (some that I can think of now):
Altering it (editing its header files - to remove the unwanted #includes)
Creating a dummy vcruntime.h file (to get past the compile phase)
Adding VStudio (or anything else, as a matter of fact) in the name would automatically decrease its "universality level". And this is only the 1st step: it has been separated from VC Runtime. Think of it as of a baby. In time, it will become mature (and more stable,) and maybe other compilers / build toolchains will end up supporting it as well (no need to follow the spartan rules, and throw it off the cliff :) ... at least not right now). But, I think only MS could have an answer to this (although there's a great chance that they won't provide a clearer one)
Newer versions of mingw-w64 do support UCRT, using their own headers and LIB files, so UCRT works (with Clang or GCC) without either the Windows SDK or Visual Studio being installed. You can even compile apps to use the UCRT on other platforms such as Linux or macOS. Of course, this scenario is unlikely to ever be "officially supported" by Microsoft, but many projects now rely on it, and Microsoft employees have (unofficially) given the mingw-w64 project feedback validating their approach.
If you are using the MSYS2 distribution of mingw-w64, Clang uses UCRT by default (for both 32-bit and 64-bit x86, and for 64-bit ARM); for 64-bit x86, GCC comes in two different distributions, one UCRT-based and the other MSVCRT-based; GCC for 32-bit x86 is MSVCRT-only. See MSYS2 Environments.

Missing sal.h while compling a win32 project via mingw

Error message:
fatal error: sal.h: No such file or directory cstudy line 11, external
location: C:\Program Files\Microsoft
SDKs\Windows\v7.0A\Include\specstrings.h C/C++ Problem.
But when I add VC/include to this project,I received a ton of error messages. It seems VC/include/sal.h is not a standard header file for GCC.
The source code is very simple:
#include "windows.h"
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
return 0;
}
Environment:
Windows 7.0A SDK
VC 2010
MINGW
CDT/ECLIPSE.
Thanks.
No, the sal.h header is not part of GCC / MinGW, however you can add your VC/include/ as an include directory to eclipse.
alternative: move all (!) requried headers to your mingw or project include directory. The one from MinGw is: <mingw path>/include).
Anyway. sal.h, if you install the Windows SDK then it isn't going to
be in the SDK directory, but you should find that if you select to
install the compiler and tools it will get installed along with that.
This is because sal.h is needed in the CRT headers as well as the
Windows headers. So you NEED to install the VS compilers and tools
along with the SDK. You will then find that the compiler will be
installed by default under %ProgramFiles%\Microsoft Visual Studio
2010\VC and sal.h will be in include under that path. On 64 bit
systems it will be under %ProgramFiles(x86)% by default.
source: http://social.msdn.microsoft.com/Forums/eu/windowssdk/thread/0e166050-99f1-436b-bd94-b39e2910f43d
See:
can't find sal.h (!)
Windows SDK header files question
I just ran into this problem. I can't seem to get the sal.h header file through the MS Windows version of mingw, but "yum whatprovides \*/sal.h" on my Fedora Core 18 machine brought up the mingw-headers package. I downloaded the source package (i.e. yumdownloader --source mingw-headers), opened up the .tar.gz file in file-roller, grabbed the sal.h file, and put it in /c/MinGW/include on my MS Windows machine.
The same package had dsound.h, which was the next missing header file.
I've never tried to use mingw under Fedora Core to cross-compile MS Windows apps, but maybe it's time... :-)

How to build gnu `libiconv` on & for windows?

I want to build a static library (*.LIB file) GNU libiconv on windows to be used with other libraries in Visual C++. Other libraries I'm using are built with "MultiThreaded DLL" (/MD) Runtime option. So, I need to build libiconv with the same option.
Problem is the libiconv uses GNU build system and I want to compile with /MD option. You can see the source structure of libiconv here:
http://cvs.savannah.gnu.org/viewvc/libiconv/?root=libiconv
Mr. Zlatkovic maintains the windows port of GNU libiconv for libxml2
you can see them here:
ftp://xmlsoft.org/libxml2/win32/iconv-1.9.2.win32.zip
I cannot use his port. I need to build from the latest version of libiconv-1.13. I wonder how this guy has ported it? Can some one please tell me how to build *.lib from this and compile it using MSVC?
EDIT:
Actually, I need to build few more gnu libraries with same settings. So, if I get solution for one library. I can do the same for all others.
I found PARK Youngho's How to Build libiconv with Microsoft Visual Studio over at The Code Project to be complete and clean (for VS2010 and GNU libiconv 1.14).
A little addition to your answer.
I had the same issue and found that the MinGW + MSYS solution was perfect.
Though, I needed to go a little further and generate also the .lib file in order to be able to link with the resulting dll.
This is what I found:
generate a .def file from the dll with dumpbin (a Visual Studio tool).
generate the .lib file from the .def with the lib program (Visual Studio tool too)
This allows you to specify some link flags if appropriate.
Everything detailed here (I'm not the author of this method):
http://wiki.videolan.org/GenerateLibFromDll
I also realized that this lib/dll couple can be linked with both MD and MDd libraries.
Hope that can help people that find this post, like it helped me.
-David
I'm the OP. MSYS is the exact thing what I was looking for.
Just install MinGW & MSYS which contains shell sh.exe & make.exewith which you can configure and generate a Makefile after that you can use make.exe to run it.
Its as simple as that.
compile them using MinGW using Msys for the environment if needed. MinGW's .a files are apparently, according to the mailing list, the same format as .lib files (just do a rename). You might want to check first to see if the iconv static library is included already in the MinGW download / filesystem.
Edit: it's in msys (C:\msys\1.0\lib), along with:
libiconv.a
libiconv.dll.a
libiconv.la
and additionally
libiconv-2.dll (in C:\msys\1.0\local\bin)
Edit: is it in here, the libiconv you need? these versions seem to have MSVC makefiles :) http://www.opensource.apple.com/source/libiconv/

Resources