Make desktop core dependencies portable

This commit is contained in:
2026-08-15 13:01:11 +02:00
parent d869edfaa8
commit 925869d2f4
4 changed files with 104 additions and 84 deletions
+71 -33
View File
@@ -4,11 +4,47 @@ project(vectorail-core VERSION 0.1.0 LANGUAGES CXX)
include(GNUInstallDirs) include(GNUInstallDirs)
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
include(FetchContent)
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
find_package(PNG REQUIRED)
find_package(SDL3 CONFIG REQUIRED) set(VECTORAIL_CORE_FETCHED_DEPENDENCIES OFF)
find_package(glm CONFIG REQUIRED)
find_package(SDL3 CONFIG QUIET)
if(NOT TARGET SDL3::SDL3)
set(SDL_INSTALL OFF CACHE BOOL "" FORCE)
FetchContent_Declare(SDL3
GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
GIT_TAG main
)
FetchContent_MakeAvailable(SDL3)
set(VECTORAIL_CORE_FETCHED_DEPENDENCIES ON)
endif()
find_package(glm CONFIG QUIET)
if(NOT TARGET glm::glm)
FetchContent_Declare(glm
GIT_REPOSITORY https://github.com/g-truc/glm.git
GIT_TAG master
)
FetchContent_MakeAvailable(glm)
set(VECTORAIL_CORE_FETCHED_DEPENDENCIES ON)
endif()
FetchContent_Declare(stb
GIT_REPOSITORY https://github.com/nothings/stb.git
GIT_TAG 2c980bb59875b0d32144a71867fbdebb2f77cd20
)
FetchContent_MakeAvailable(stb)
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR AND
NOT VECTORAIL_CORE_FETCHED_DEPENDENCIES)
set(VECTORAIL_CORE_INSTALL_DEFAULT ON)
else()
set(VECTORAIL_CORE_INSTALL_DEFAULT OFF)
endif()
option(VECTORAIL_CORE_INSTALL "Generate VectorailCore install rules"
${VECTORAIL_CORE_INSTALL_DEFAULT})
add_library(vectorail-core add_library(vectorail-core
src/DdsTexture.cpp src/DdsTexture.cpp
@@ -24,12 +60,13 @@ target_include_directories(vectorail-core
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE
${stb_SOURCE_DIR}
) )
target_link_libraries(vectorail-core target_link_libraries(vectorail-core
PUBLIC PUBLIC
SDL3::SDL3 SDL3::SDL3
OpenGL::GL OpenGL::GL
PNG::PNG
glm::glm glm::glm
) )
@@ -39,33 +76,34 @@ set_target_properties(vectorail-core PROPERTIES
SOVERSION ${PROJECT_VERSION_MAJOR} SOVERSION ${PROJECT_VERSION_MAJOR}
) )
install(TARGETS vectorail-core if(VECTORAIL_CORE_INSTALL)
EXPORT VectorailCoreTargets install(TARGETS vectorail-core
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT VectorailCoreTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
) INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) )
install(EXPORT VectorailCoreTargets install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
FILE VectorailCoreTargets.cmake install(EXPORT VectorailCoreTargets
NAMESPACE Vectorail:: FILE VectorailCoreTargets.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VectorailCore NAMESPACE Vectorail::
) DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VectorailCore
)
configure_package_config_file(
cmake/VectorailCoreConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/VectorailCoreConfig.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VectorailCore
)
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/VectorailCoreConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/VectorailCoreConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/VectorailCoreConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VectorailCore
)
configure_package_config_file(
cmake/VectorailCoreConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/VectorailCoreConfig.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VectorailCore
)
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/VectorailCoreConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/VectorailCoreConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/VectorailCoreConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VectorailCore
)
endif()
-2
View File
@@ -2,9 +2,7 @@
include(CMakeFindDependencyMacro) include(CMakeFindDependencyMacro)
find_dependency(OpenGL) find_dependency(OpenGL)
find_dependency(PNG)
find_dependency(SDL3 CONFIG) find_dependency(SDL3 CONFIG)
find_dependency(glm CONFIG) find_dependency(glm CONFIG)
include("${CMAKE_CURRENT_LIST_DIR}/VectorailCoreTargets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/VectorailCoreTargets.cmake")
+3
View File
@@ -5,6 +5,9 @@
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif #endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h> #include <windows.h>
#endif #endif
+30 -49
View File
@@ -2,11 +2,13 @@
#include "vectorail/core/gl_loader.hpp" #include "vectorail/core/gl_loader.hpp"
#include <png.h> #define STBI_ONLY_PNG
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#include <cstdio> #include <algorithm>
#include <cstring>
#include <fstream> #include <fstream>
#include <limits>
#include <span> #include <span>
#include <vector> #include <vector>
@@ -35,56 +37,34 @@ bool readFile(const std::string& path, std::vector<uint8_t>& bytes) {
return static_cast<bool>(file) || file.eof(); return static_cast<bool>(file) || file.eof();
} }
struct PngMemoryReader {
std::span<const uint8_t> bytes;
size_t offset = 0;
};
void readPngMemory(png_structp png, png_bytep destination, png_size_t length) {
auto* reader = static_cast<PngMemoryReader*>(png_get_io_ptr(png));
if (!reader || length > reader->bytes.size() - reader->offset) {
png_error(png, "truncated PNG stream");
return;
}
std::memcpy(destination, reader->bytes.data() + reader->offset, length);
reader->offset += length;
}
bool decodePng(std::span<const uint8_t> bytes, DdsTexture& out, std::string* error) { bool decodePng(std::span<const uint8_t> bytes, DdsTexture& out, std::string* error) {
out = {}; out = {};
if (bytes.size() < 8 || png_sig_cmp(bytes.data(), 0, 8) != 0) { constexpr uint8_t signature[] = {0x89, 'P', 'N', 'G', 0x0d, 0x0a, 0x1a, 0x0a};
if (bytes.size() < sizeof(signature) ||
!std::equal(std::begin(signature), std::end(signature), bytes.begin())) {
if (error) *error = "not a PNG stream"; if (error) *error = "not a PNG stream";
return false; return false;
} }
if (bytes.size() > static_cast<size_t>(std::numeric_limits<int>::max())) {
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (error) *error = "PNG stream is too large";
png_infop info = png ? png_create_info_struct(png) : nullptr;
if (!png || !info || setjmp(png_jmpbuf(png))) {
if (error) *error = "could not decode PNG";
if (png) png_destroy_read_struct(&png, info ? &info : nullptr, nullptr);
return false; return false;
} }
PngMemoryReader reader{bytes}; int width = 0;
png_set_read_fn(png, &reader, readPngMemory); int height = 0;
png_read_info(png, info); int sourceChannels = 0;
const png_uint_32 width = png_get_image_width(png, info); stbi_uc* rgba = stbi_load_from_memory(
const png_uint_32 height = png_get_image_height(png, info); bytes.data(), static_cast<int>(bytes.size()),
const int colorType = png_get_color_type(png, info); &width, &height, &sourceChannels, STBI_rgb_alpha);
const int bitDepth = png_get_bit_depth(png, info); if (!rgba || width <= 0 || height <= 0) {
if (bitDepth == 16) png_set_strip_16(png); if (error) {
if (colorType == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); const char* reason = stbi_failure_reason();
if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) png_set_expand_gray_1_2_4_to_8(png); *error = reason ? std::string("could not decode PNG: ") + reason
if (png_get_valid(png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png); : "could not decode PNG";
if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png); }
if ((colorType & PNG_COLOR_MASK_ALPHA) == 0) png_set_add_alpha(png, 0xff, PNG_FILLER_AFTER); stbi_image_free(rgba);
png_read_update_info(png, info); return false;
}
std::vector<uint8_t> rgba(static_cast<size_t>(width) * height * 4);
std::vector<png_bytep> rows(height);
for (png_uint_32 y = 0; y < height; ++y) rows[y] = rgba.data() + static_cast<size_t>(y) * width * 4;
png_read_image(png, rows.data());
png_destroy_read_struct(&png, &info, nullptr);
glGenTextures(1, &out.id); glGenTextures(1, &out.id);
glBindTexture(GL_TEXTURE_2D, out.id); glBindTexture(GL_TEXTURE_2D, out.id);
@@ -92,11 +72,12 @@ bool decodePng(std::span<const uint8_t> bytes, DdsTexture& out, std::string* err
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, static_cast<GLsizei>(width), static_cast<GLsizei>(height), glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
0, GL_RGBA, GL_UNSIGNED_BYTE, rgba.data()); 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
out.width = static_cast<int>(width); stbi_image_free(rgba);
out.height = static_cast<int>(height); out.width = width;
out.height = height;
return true; return true;
} }