KhronosGroup / Vulkan-Hpp

Open-Source Vulkan C++ API

Repository from Github https://github.comKhronosGroup/Vulkan-HppRepository from Github https://github.comKhronosGroup/Vulkan-Hpp

Can't compile c++20 module with std module

otreblan opened this issue · comments

OS: Arch linux

  • cmake=4.1.1-1
  • clang=20.1.8-1
  • ninja=1.12.1-2
  • vulkan-headers=1.4.321.0-1
find_package(Vulkan REQUIRED)

# set up Vulkan C++ module as a library
add_library(VulkanHppModule)
target_sources(VulkanHppModule PUBLIC
	FILE_SET CXX_MODULES
	BASE_DIRS ${Vulkan_INCLUDE_DIR}
	FILES ${Vulkan_INCLUDE_DIR}/vulkan/vulkan.cppm
)
set_target_properties(VulkanHppModule
	PROPERTIES
		CXX_STANDARD 23
)


target_compile_definitions(VulkanHppModule
	PRIVATE
		$<$<NOT:$<CONFIG:DEBUG>>:NDEBUG>
	PUBLIC
		$<$<CONFIG:DEBUG>:VK_DEBUG>
		VULKAN_HPP_ENABLE_STD_MODULE
		VULKAN_HPP_STD_MODULE=std
)

target_link_libraries(VulkanHppModule PUBLIC Vulkan::Vulkan)
[37/44] Building CXX object deps/CMakeFiles/VulkanHppModule.dir/usr/include/vulkan/vulkan.cppm.o
FAILED: deps/CMakeFiles/VulkanHppModule.dir/usr/include/vulkan/vulkan.cppm.o deps/CMakeFiles/VulkanHppModule.dir/vulkan_hpp.pcm
/usr/bin/clang++ -DVK_DEBUG -DVULKAN_HPP_ENABLE_STD_MODULE -DVULKAN_HPP_STD_MODULE=std  -g -std=gnu++23 -D_GLIBCXX_DEBUG -MD -MT deps/CMakeFiles/VulkanHppModule.dir/usr/include/vulkan/vulkan.cppm.o -MF deps/CMakeFiles/VulkanHppModule.dir/usr/include/vulkan/vulkan.cppm.o.d @deps/CMakeFiles/VulkanHppModule.dir/usr/include/vulkan/vulkan.cppm.o.modmap -o deps/CMakeFiles/VulkanHppModule.dir/usr/include/vulkan/vulkan.cppm.o -c /usr/include/vulkan/vulkan.cppm
In file included from /usr/include/vulkan/vulkan.cppm:19:
In file included from /usr/include/vulkan/vulkan.hpp:9366:
/usr/include/vulkan/vulkan_structs.hpp:37811:7: error: missing '#include <stdlib.h>'; 'free' must be declared before it is used
 37811 |       free( pAddressInfos );
       |       ^
/usr/include/stdlib.h:687:13: note: declaration here is not visible
  687 | extern void free (void *__ptr) __THROW;
      |             ^
In file included from /usr/include/vulkan/vulkan.cppm:19:
In file included from /usr/include/vulkan/vulkan.hpp:9366:
/usr/include/vulkan/vulkan_structs.hpp:37812:7: error: missing '#include <stdlib.h>'; 'free' must be declared before it is used
 37812 |       free( pVendorInfos );
       |       ^
/usr/include/stdlib.h:687:13: note: declaration here is not visible
  687 | extern void free (void *__ptr) __THROW;
      |             ^
In file included from /usr/include/vulkan/vulkan.cppm:19:
In file included from /usr/include/vulkan/vulkan.hpp:9366:
/usr/include/vulkan/vulkan_structs.hpp:37813:7: error: missing '#include <stdlib.h>'; 'free' must be declared before it is used
 37813 |       free( pVendorBinaryData );
       |       ^
/usr/include/stdlib.h:687:13: note: declaration here is not visible
  687 | extern void free (void *__ptr) __THROW;
      |             ^
In file included from /usr/include/vulkan/vulkan.cppm:19:
In file included from /usr/include/vulkan/vulkan.hpp:9366:
/usr/include/vulkan/vulkan_structs.hpp:37832:7: error: missing '#include <stdlib.h>'; 'free' must be declared before it is used
 37832 |       free( pAddressInfos );
       |       ^
/usr/include/stdlib.h:687:13: note: declaration here is not visible
  687 | extern void free (void *__ptr) __THROW;
      |             ^
In file included from /usr/include/vulkan/vulkan.cppm:19:
In file included from /usr/include/vulkan/vulkan.hpp:9366:
/usr/include/vulkan/vulkan_structs.hpp:37833:7: error: missing '#include <stdlib.h>'; 'free' must be declared before it is used
 37833 |       free( pVendorInfos );
       |       ^
/usr/include/stdlib.h:687:13: note: declaration here is not visible
  687 | extern void free (void *__ptr) __THROW;
      |             ^
In file included from /usr/include/vulkan/vulkan.cppm:19:
In file included from /usr/include/vulkan/vulkan.hpp:9366:
/usr/include/vulkan/vulkan_structs.hpp:37834:7: error: missing '#include <stdlib.h>'; 'free' must be declared before it is used
 37834 |       free( pVendorBinaryData );
       |       ^
/usr/include/stdlib.h:687:13: note: declaration here is not visible
  687 | extern void free (void *__ptr) __THROW;
      |             ^
6 errors generated.
ninja: build stopped: subcommand failed.

The module implementation has not been touched much since conception, as CI can't really test it yet. Since module tests are currently being improved anyways, I might as well try and see if I can get import std working somehow and fix this issue meanwhile. There are a bunch of things that currently aren't exactly optimal (like forced #includes despite using import std).

Could you share what parameters you run your CMake with? Last time I tried it with CMake, I had issues trying to force it to use the clang stdlib.

On Linux with Clang I suspect the solution will be -stdlib=libc++, as the different std module libraries are not yet compatible with the opposite compiler.

As an aside, the module works for me on MSVC—I suspect (as always) a tooling problem rather than a compiler problem.

@sharadhr do you know whether C library headers are supposed to also be included with the std module? From what I can see, it only includes stuff from the std namespace (makes sense), so things like free() that are part of stdlib.h would not be included (as per the spec at least, implementations seem to differ).

One option would be to just use the C++ variants new and delete for these operations, but I don't have a full overview of how de-/allocations are handled here. @asuessenbach would it be feasible to get rid of C functions here?

Otherwise, C headers would need to be explictly included alongside import std when these functions are used. Or just add it to vulkan.hpp like the other exception headers written there:

#if defined( VULKAN_HPP_ENABLE_STD_MODULE ) && defined( VULKAN_HPP_STD_MODULE )
# include <cassert>
# include <string.h>
import VULKAN_HPP_STD_MODULE;
#else

@sharadhr do you know whether C library headers are supposed to also be included with the std module?

Ahh, I remember this. Sadly no, C headers are not exported by std. Cpplang Slack link. Using new/delete would be the solution.

@otreblan Would you please verify if #2269 actually resolves your issue?

@otreblan Would you please verify if #2269 actually resolves your issue?

I tried to override my local vulkan-headers with FetchContent but it still uses /usr/include/vulkan/vulkan_core.h.
Also I found out that the module compiles with std if it has VULKAN_HPP_NO_STRUCT_CONSTRUCTORS=1 defined.

....
FetchContent_Declare(
	vulkan
	GIT_REPOSITORY https://github.com/M2-TE/Vulkan-Hpp
	GIT_TAG        origin/add-cstdlib-to-module
	GIT_SHALLOW    ON
	GIT_PROGRESS   ON
	OVERRIDE_FIND_PACKAGE
)
FetchContent_MakeAvailable(imgui VulkanMemoryAllocator-Hpp vkfw vulkan)
find_package(Vulkan REQUIRED)
# set up Vulkan C++ module as a library
add_library(VulkanHppModule)

target_include_directories(VulkanHppModule
	INTERFACE
		${vulkan_SOURCE_DIR}
)

target_sources(VulkanHppModule PUBLIC
	FILE_SET CXX_MODULES
	BASE_DIRS ${vulkan_SOURCE_DIR}
	FILES ${vulkan_SOURCE_DIR}/vulkan/vulkan.cppm
)
set_target_properties(VulkanHppModule
	PROPERTIES
		CXX_STANDARD 26
)


target_compile_definitions(VulkanHppModule
	PRIVATE
		$<$<NOT:$<CONFIG:DEBUG>>:NDEBUG>
	PUBLIC
	#VULKAN_HPP_NO_STRUCT_CONSTRUCTORS=1
		VULKAN_HPP_ENABLE_STD_MODULE
		VULKAN_HPP_STD_MODULE=std
)

target_link_libraries(VulkanHppModule PUBLIC Vulkan::Hpp)
$ time cmake --build .
[9/37] Building CXX object deps/CMakeFiles/VulkanHppModule.dir/__/_deps/vulkan-src/vulkan/vulkan.cppm.o
FAILED: deps/CMakeFiles/VulkanHppModule.dir/__/_deps/vulkan-src/vulkan/vulkan.cppm.o deps/CMakeFiles/VulkanHppModule.dir/vulkan_hpp.pcm
/usr/bin/clang++ -DVULKAN_HPP_ENABLE_STD_MODULE -DVULKAN_HPP_STD_MODULE=std -I/home/aru/code/fdtd-vulkan/build/_deps/vulkan-src -g -std=gnu++26 -D_GLIBCXX_DEBUG -Wp,-D_FORTIFY_SOURCE=0 -Wno-macro-redefined -MD -MT deps/CMakeFiles/VulkanHppModule.dir/__/_deps/vulkan-src/vulkan/vulkan.cppm.o -MF deps/CMakeFiles/VulkanHppModule.dir/__/_deps/vulkan-src/vulkan/vulkan.cppm.o.d @deps/CMakeFiles/VulkanHppModule.dir/__/_deps/vulkan-src/vulkan/vulkan.cppm.o.modmap -o deps/CMakeFiles/VulkanHppModule.dir/__/_deps/vulkan-src/vulkan/vulkan.cppm.o -c /home/aru/code/fdtd-vulkan/build/_deps/vulkan-src/vulkan/vulkan.cppm
In file included from /home/aru/code/fdtd-vulkan/build/_deps/vulkan-src/vulkan/vulkan.cppm:19:
/home/aru/code/fdtd-vulkan/build/_deps/vulkan-src/vulkan/vulkan.hpp:60:16: error: static assertion failed due to requirement '321 == 326': Wrong VK_HEADER_VERSION!
   60 | static_assert( VK_HEADER_VERSION == 326, "Wrong VK_HEADER_VERSION!" );
      |                ^~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/vulkan/vulkan_core.h:72:27: note: expanded from macro 'VK_HEADER_VERSION'
   72 | #define VK_HEADER_VERSION 321
      |                           ^

You could manually symlink /usr/include/vulkan/vulkan_core.h to your own Vulkan-Headers package include directory. I would probably symlink the entire directory /usr/include/vulkan to your Vulkan-Headers dir.

It works. I added the local vulkan headers to the module target.

target_include_directories(VulkanHppModule
	PUBLIC
		${vulkan_SOURCE_DIR}
		${vulkan_SOURCE_DIR}/Vulkan-Headers/include
)

Also I found out that the module compiles with std if it has VULKAN_HPP_NO_STRUCT_CONSTRUCTORS=1 defined

Could you open a separate issue about this? That doesn't seem right..

It works.

Assuming, this is related to my question, whether #2269 resolves your issue, I'll merge that.

Thanks a lot for reporting this issue!