1

I'm using VulkanMemoryAllocation, which is a header only library. I want to compile it into a static library using cmake, but I end up with an empty - 8 bytes sized - library file, and a lot of undefined symbols when linking.

Here is the relevant part of the CMakeList.txt

# The header with the implementation
add_library(VulkanMemoryAllocator STATIC VulkanMemoryAllocator-Hpp/vk_mem_alloc.h)
# The include path for a wrapper which uses above mentionned header
target_include_directories(VulkanMemoryAllocator PUBLIC VulkanMemoryAllocator-Hpp/)
# enable the actual implementation
target_compile_options(VulkanMemoryAllocator PRIVATE VMA_IMPLEMENTATION)
# consider this file as a C++ file
set_target_properties(VulkanMemoryAllocator PROPERTIES LINKER_LANGUAGE CXX)

EDIT : I want to do the equivalent of this :

clang++ -c -DVMA_IMPLEMENTATION -x c++ -o vk_mem_alloc.o  ../lib/VulkanMemoryAllocator-Hpp/vk_mem_alloc.h && ar rc libvma.a vk_mem_alloc.o

but using CMake

dorfen_
  • 75
  • 1
  • 7
  • 3
    A static library is an indexed archive of object files. A header only library has no.c* files, thus has no object files compiled from .c* files, thus the static library is 8 bytes, an empty archive. – 273K Aug 24 '21 at 18:17
  • CMakeList.txt above does not invoke the linker. You got the errors somewhere you did not show. – 273K Aug 24 '21 at 18:20
  • 1
    Does this answer your question? [How to build static library from header-only library](https://stackoverflow.com/questions/52927351/how-to-build-static-library-from-header-only-library) – fabian Aug 24 '21 at 18:30
  • I don't have any error in CMake log. I know that a header-only does not have any .c file. What I want to do, is to compile the library implementation (in the header file) into an object file. – dorfen_ Aug 24 '21 at 18:30
  • `clang++ -c -DVMA_IMPLEMENTATION -x c++ -o vk_mem_alloc.o ./VulkanMemoryAllocator-Hpp/vk_mem_alloc.h` I want to do that, but using cmake – dorfen_ Aug 24 '21 at 18:32
  • 1
    A header-only library typically has no compilable code, that's the reason it is header-only to begin with. Binary code is generated only when the library is actually used. – n. m. could be an AI Aug 24 '21 at 18:36
  • @fabian yes, but I would prefer a solution without having to create an extra source file. – dorfen_ Aug 24 '21 at 18:37
  • @n.1.8e9-where's-my-sharem. Some header-only library are separating declaration from implementation (the `#define VMA_IMPLEMENTATION` in my example) Those headers can be compiled into a static library. I know how to do it by hand, I just don't know how to do it with CMake. – dorfen_ Aug 24 '21 at 18:43
  • `Some header-only library are separating declaration from implementation (the #define VMA_IMPLEMENTATION` That's not `compile_option`, but `target_compile_definitions` – KamilCuk Aug 24 '21 at 18:46
  • 1
    You may be able to achieve something like this by setting the `LANGUAGE` and `HEADER_FILE_ONLY` source file properties; according to the docs you'll need cmake 3.20 though. Still sceptical that this will yield the desired results, unless this is a possibility described in the header only lib's documentation. I'm not familiar with the lib so I cannot tell. – fabian Aug 24 '21 at 18:48
  • 1
    5 min google search: https://github.com/usnistgov/hevx/blob/master/third_party/VulkanMemoryAllocator.cmake – KamilCuk Aug 24 '21 at 18:51
  • @KamilCuk well, you're right, my bad xD Changing it doesn't fix the issue, tho. Still having empty library, and missing sybols. – dorfen_ Aug 24 '21 at 18:52
  • @KamilCuk And your link is what I'm looking for. Thanks. But I'm still curious about how to do it without having an extra file. – dorfen_ Aug 24 '21 at 18:54

1 Answers1

1

VMA_IMPLEMENTATION is a compile_definition not compile_option.

You have to set file language, in addition to target (I think).

set_source_file_properties(
    VulkanMemoryAllocator-Hpp/vk_mem_alloc.h PROPERTIES
    LANGUAGE CXX
)

I would just copy the header so that CMake knows it's C++ from extension, it's just simpler.

add_custom_command(
    COMMENT 'Copying vk_mem_alloc'
    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vk_mem_alloc.cpp
    DEPENDS VulkanMemoryAllocator-Hpp/vk_mem_alloc.h
    COMMAND ${CMAKE_COMMAND} -E copy
        VulkanMemoryAllocator-Hpp/vk_mem_alloc.h
        ${CMAKE_CURRENT_BINARY_DIR}/vk_mem_alloc.cpp
)
add_library(VulkanMemoryAllocator STATIC
    ${CMAKE_CURRENT_BINARY_DIR}/vk_mem_alloc.cpp
)
target_include_directories(VulkanMemoryAllocator PUBLIC
    VulkanMemoryAllocator-Hpp
)
target_compile_definitions(VulkanMemoryAllocator PRIVATE
    VMA_IMPLEMENTATION
)

Here https://github.com/usnistgov/hevx/blob/master/third_party/VulkanMemoryAllocator.cmake is a similar solution, that creates a C++ file with #define and compiles it.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111