diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index 87e5181..5bc0bb5 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -11,7 +11,7 @@ jobs: matrix: configuration: [Debug, Release] - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v1 @@ -23,21 +23,18 @@ jobs: libxcb-randr0-dev libxcb-util0-dev pkg-config - libgtkmm-3.0-dev + libgtkmm-3.0-dev libfontenc-dev libxaw7-dev libxmu-dev libxmuu-dev libxpm-dev libxres-dev libxss-dev libxv-dev libxvmc-dev libxxf86vm-dev libxcb-render-util0-dev libxcb-xkb-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-shape0-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-xinerama0-dev libxcb-dri3-dev libxcb-cursor-dev - name: Get Conan - run: pip install conan && - conan profile new default --detect && - conan profile update settings.compiler.libcxx=libstdc++11 default && - conan profile update settings.compiler.version=8 default - - name: Add remotes to Conan - run: conan config install conan/config/common + run: pip install conan + - name: Setup Conan + run: conan profile detect - name: Conan install env: CC: gcc-10 CXX: g++-10 run: mkdir build && conan install . - -if build + -of build --build missing -s build_type=${{ matrix.configuration }} - name: Configure @@ -67,14 +64,13 @@ jobs: - uses: actions/setup-python@v1 - uses: ilammy/msvc-dev-cmd@v1.5.0 - name: Get Conan - run: pip install conan && conan profile new default --detect - - name: Add remotes to Conan - run: conan config install conan/config/common + run: pip install conan + - name: Setup Conan + run: conan profile detect - name: Conan install run: mkdir build && - conan config set general.parallel_download=8 && conan install . - -if build + -of build --build missing -s build_type=${{ matrix.configuration }} - name: Configure diff --git a/CMakeLists.txt b/CMakeLists.txt index aee09ab..4bcdf0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,12 +36,10 @@ find_package(Bullet REQUIRED) find_package(yaml-cpp REQUIRED) find_package(Catch2 REQUIRED) find_package(TBB REQUIRED) -find_package(scope_guard REQUIRED) find_package(Eigen3 REQUIRED) find_package(fmt REQUIRED) find_package(Boost REQUIRED) find_package(Vulkan REQUIRED) -find_package(embed-resource REQUIRED) find_package(Freetype REQUIRED) find_package(OpenMesh REQUIRED) find_package(yaml-cpp REQUIRED) @@ -53,10 +51,6 @@ find_package(rapidfuzz REQUIRED) add_executable(glslangValidator IMPORTED) set_target_properties(glslangValidator PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/bin/glslangValidator) -add_executable(embed-resource IMPORTED) -set_target_properties(embed-resource PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/bin/embed-resource) - -include(${CMAKE_CURRENT_BINARY_DIR}/scripts/embed-resource.cmake) add_subdirectory(lmlib) add_subdirectory(lmng) diff --git a/README.md b/README.md index aa5d96d..8e686b2 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ Example 3D game made with the engine. ## Requirements * Python 3 -* The [Conan](https://conan.io/) package manager +* The [Conan](https://conan.io/) package manager (version 1- `pip install conan<2.0`) * [CMake](https://cmake.org/) * Vulkan graphics drivers * Linux @@ -71,6 +71,8 @@ Example 3D game made with the engine. * pkg-config * libgtkmm-3.0-dev * vulkan-validation-layers +* Windows + * LunarG Vulkan SDK ## Setup On the command line, in the repository root directory, run: diff --git a/conan/config/common/remotes.txt b/conan/config/common/remotes.txt deleted file mode 100644 index 0043870..0000000 --- a/conan/config/common/remotes.txt +++ /dev/null @@ -1,2 +0,0 @@ -conan-center https://center.conan.io True -lm-engine-gitlab https://gitlab.com/api/v4/projects/26470715/packages/conan True diff --git a/conan/config/linux/profiles/default b/conan/config/linux/profiles/default deleted file mode 100644 index af98fde..0000000 --- a/conan/config/linux/profiles/default +++ /dev/null @@ -1,12 +0,0 @@ -[settings] -os=Linux -os_build=Linux -arch=x86_64 -arch_build=x86_64 -compiler=gcc -compiler.version=9 -compiler.libcxx=libstdc++11 -build_type=Debug -[options] -[build_requires] -[env] diff --git a/conanfile.txt b/conanfile.txt index 11f3dc0..e9572b3 100644 --- a/conanfile.txt +++ b/conanfile.txt @@ -8,31 +8,27 @@ yaml-cpp/0.6.3 vulkan-loader/1.2.198.0 glslang/11.7.0 eigen/3.3.9 -tbb/2020.1 +onetbb/2021.9.0 range-v3/0.11.0 spdlog/1.8.5 -scope_guard/0.2.3@lawrencem/stable fmt/7.1.3 boost/1.73.0 -embed-resource/0.2@lawrencem/stable openmesh/8.1 clara/1.1.5 -freetype/2.10.2 +freetype/2.13.0 sdl/2.0.18 rapidfuzz/cci.20210513 +zlib/1.2.13 -[build_requires] -catch2/2.13.0 +[test_requires] +catch2/3.4.0 [options] -yaml-cpp:shared=True -OpenMesh:shared=True -sdl:shared=True +yaml-cpp/*:shared=True +OpenMesh/*:shared=True +sdl/*:shared=True [imports] -bin, embed-resource -> ./bin -bin, embed-resource.exe -> ./bin bin, glslangValidator* -> ./bin bin, *.dll -> ./bin lib, *.so* -> ./bin -cmake, embed-resource.cmake -> ./scripts diff --git a/lmhuv/src/rendering/shapes.cpp b/lmhuv/src/rendering/shapes.cpp index 90b408c..d88ccfa 100644 --- a/lmhuv/src/rendering/shapes.cpp +++ b/lmhuv/src/rendering/shapes.cpp @@ -1,7 +1,7 @@ #include "shapes.h" #include "../trimesh/util.h" -#include +#include #include #include diff --git a/lmlib/CMakeLists.txt b/lmlib/CMakeLists.txt index 53d09b4..ebd010f 100644 --- a/lmlib/CMakeLists.txt +++ b/lmlib/CMakeLists.txt @@ -8,6 +8,9 @@ set( CACHE INTERNAL "lmlib top-level directory") include(cmake/cpp_standard.cmake) +include(embed-resource.cmake) + +add_executable(embed-resource src/embedresource-cpp-11.cpp include/lmlib/Resource.h) if (MSVC) set( diff --git a/lmlib/embed-resource.cmake b/lmlib/embed-resource.cmake new file mode 100644 index 0000000..e64b3a6 --- /dev/null +++ b/lmlib/embed-resource.cmake @@ -0,0 +1,40 @@ +# Call this with the output of custom commands that buld resources +# you want to embed. The paths should be absolute. +function(embed_built_resources out_var) + set(result) + foreach (in_f ${ARGN}) + file(RELATIVE_PATH src_f ${CMAKE_CURRENT_BINARY_DIR} "${in_f}") + set(out_f ${in_f}.cpp) + get_filename_component(out_f_dir "${out_f}" DIRECTORY) + add_custom_command( + OUTPUT ${out_f} + COMMAND ${CMAKE_COMMAND} -E make_directory "${out_f_dir}" + COMMAND embed-resource "${out_f}" "${src_f}" + DEPENDS "${in_f}" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Building binary file for embedding ${out_f}" + VERBATIM) + list(APPEND result "${out_f}") + endforeach() + set(${out_var} "${result}" PARENT_SCOPE) +endfunction() + +# Call this with relative paths to sources you want to embed as resources. +function(embed_resources out_var) + set(result) + foreach (in_f ${ARGN}) + file(RELATIVE_PATH src_f embed-resource "${CMAKE_CURRENT_SOURCE_DIR}/${in_f}") + set(out_f "${PROJECT_BINARY_DIR}/${in_f}.cpp") + get_filename_component(out_f_dir "${out_f}" DIRECTORY) + add_custom_command( + OUTPUT ${out_f} + COMMAND ${CMAKE_COMMAND} -E make_directory "${out_f_dir}" + COMMAND embed-resource "${out_f}" "${src_f}" + DEPENDS "${in_f}" + WORKING_DIRECTORY embed-resource + COMMENT "Building binary file for embedding ${out_f}" + VERBATIM) + list(APPEND result "${out_f}") + endforeach() + set(${out_var} "${result}" PARENT_SCOPE) +endfunction() \ No newline at end of file diff --git a/lmlib/include/lmlib/Resource.h b/lmlib/include/lmlib/Resource.h new file mode 100644 index 0000000..e170622 --- /dev/null +++ b/lmlib/include/lmlib/Resource.h @@ -0,0 +1,24 @@ +#pragma once +#include +#include + +class Resource { +public: + Resource(const unsigned char* start, const size_t len) : resource_data(start), data_len(len) {} + + const char * const data() const { return (char*)resource_data; } + const size_t size() const { return data_len; } + + const char *begin() const { return (char*)resource_data; } + const char *end() const { return (char*)resource_data + data_len; } + + std::string toString() { return std::string((char*)data(), size()); } + +private: + const unsigned char* resource_data; + const size_t data_len; + +}; +#define LOAD_RESOURCE(varname, RESOURCE) \ + extern const unsigned char _resource_##RESOURCE[]; extern const size_t _resource_##RESOURCE##_len; \ + static auto varname = Resource(_resource_##RESOURCE, _resource_##RESOURCE##_len); diff --git a/lmlib/include/lmlib/scope_guard.hpp b/lmlib/include/lmlib/scope_guard.hpp new file mode 100644 index 0000000..47712cb --- /dev/null +++ b/lmlib/include/lmlib/scope_guard.hpp @@ -0,0 +1,184 @@ +/* + * Created on: 13/02/2018 + * Author: ricab + * + * See README.md for documentation of this header's public interface. + */ + +#ifndef SCOPE_GUARD_HPP_ +#define SCOPE_GUARD_HPP_ + +#include +#include + +#if __cplusplus >= 201703L && defined(SG_REQUIRE_NOEXCEPT_IN_CPP17) +#define SG_REQUIRE_NOEXCEPT +#endif + +namespace sg +{ + namespace detail + { + /* --- Some custom type traits --- */ + + // Type trait determining whether a type is callable with no arguments + template + struct is_noarg_callable_t + : public std::false_type + {}; // in general, false + + template + struct is_noarg_callable_t()())> + : public std::true_type + {}; // only true when call expression valid + + // Type trait determining whether a no-argument callable returns void + template + struct returns_void_t + : public std::is_same()())> + {}; + + /* Type trait determining whether a no-arg callable is nothrow invocable if + required. This is where SG_REQUIRE_NOEXCEPT logic is encapsulated. */ + template + struct is_nothrow_invocable_if_required_t + : public +#ifdef SG_REQUIRE_NOEXCEPT + std::is_nothrow_invocable /* Note: _r variants not enough to + confirm void return: any return can be + discarded so all returns are + compatible with void */ +#else + std::true_type +#endif + {}; + + // logic AND of two or more type traits + template + struct and_t : public and_t> + {}; // for more than two arguments + + template + struct and_t : public std::conditional::type + {}; // for two arguments + + // Type trait determining whether a type is a proper scope_guard callback. + template + struct is_proper_sg_callback_t + : public and_t, + returns_void_t, + is_nothrow_invocable_if_required_t, + std::is_nothrow_destructible> + {}; + + + /* --- The actual scope_guard template --- */ + + template::value>::type> + class scope_guard; + + + /* --- Now the friend maker --- */ + + template + detail::scope_guard make_scope_guard(Callback&& callback) + noexcept(std::is_nothrow_constructible::value); /* + we need this in the inner namespace due to MSVC bugs preventing + sg::detail::scope_guard from befriending a sg::make_scope_guard + template instance in the parent namespace (see https://is.gd/xFfFhE). */ + + + /* --- The template specialization that actually defines the class --- */ + + template + class scope_guard final + { + public: + typedef Callback callback_type; + + scope_guard(scope_guard&& other) + noexcept(std::is_nothrow_constructible::value); + + ~scope_guard() noexcept; // highlight noexcept dtor + + void dismiss() noexcept; + + public: + scope_guard() = delete; + scope_guard(const scope_guard&) = delete; + scope_guard& operator=(const scope_guard&) = delete; + scope_guard& operator=(scope_guard&&) = delete; + + private: + explicit scope_guard(Callback&& callback) + noexcept(std::is_nothrow_constructible::value); /* + meant for friends only */ + + friend scope_guard make_scope_guard(Callback&&) + noexcept(std::is_nothrow_constructible::value); /* + only make_scope_guard can create scope_guards from scratch (i.e. non-move) + */ + + private: + Callback m_callback; + bool m_active; + + }; + + } // namespace detail + + + /* --- Now the single public maker function --- */ + + using detail::make_scope_guard; // see comment on declaration above + +} // namespace sg + +//////////////////////////////////////////////////////////////////////////////// +template +sg::detail::scope_guard::scope_guard(Callback&& callback) +noexcept(std::is_nothrow_constructible::value) + : m_callback(std::forward(callback)) /* use () instead of {} because + of DR 1467 (https://is.gd/WHmWuo), which still impacts older compilers + (e.g. GCC 4.x and clang <=3.6, see https://godbolt.org/g/TE9tPJ and + https://is.gd/Tsmh8G) */ + , m_active{true} +{} + +//////////////////////////////////////////////////////////////////////////////// +template +sg::detail::scope_guard::~scope_guard() noexcept +{ + if(m_active) + m_callback(); +} + +//////////////////////////////////////////////////////////////////////////////// +template +sg::detail::scope_guard::scope_guard(scope_guard&& other) +noexcept(std::is_nothrow_constructible::value) + : m_callback(std::forward(other.m_callback)) // idem + , m_active{std::move(other.m_active)} +{ + other.m_active = false; +} + +//////////////////////////////////////////////////////////////////////////////// +template +inline void sg::detail::scope_guard::dismiss() noexcept +{ + m_active = false; +} + +//////////////////////////////////////////////////////////////////////////////// +template +inline auto sg::detail::make_scope_guard(Callback&& callback) +noexcept(std::is_nothrow_constructible::value) +-> detail::scope_guard +{ + return detail::scope_guard{std::forward(callback)}; +} + +#endif /* SCOPE_GUARD_HPP_ */ diff --git a/lmlib/src/embedresource-cpp-11.cpp b/lmlib/src/embedresource-cpp-11.cpp new file mode 100644 index 0000000..086f6ab --- /dev/null +++ b/lmlib/src/embedresource-cpp-11.cpp @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include + + +int main(int argc, char** argv) +{ + if (argc < 3) + { + std::cerr << "USAGE: " << argv[0] << " {sym} {rsrc}" << std::endl + << std::endl + << " Creates {sym}.c from the contents of {rsrc}" << std::endl; + return EXIT_FAILURE; + } + + // Replace characters in the file path incompatible with a c variable name. + std::string sym(argv[2]); + std::replace(sym.begin(), sym.end(), '.', '_'); + std::replace(sym.begin(), sym.end(), '-', '_'); + std::replace(sym.begin(), sym.end(), '/', '_'); + std::replace(sym.begin(), sym.end(), '\\', '_'); + + // Get length of input resource. + std::ifstream ifs; + ifs.open(argv[2], std::ios_base::ate | std::ios_base::binary); + if (ifs.fail()) + { + std::cout << "Failed to open " << argv[2] << '\n'; + return EXIT_FAILURE; + } + auto resource_byte_size = ifs.tellg(); + ifs.close(); + + // Read input resource into a buffer. + ifs.open(argv[2], std::ios_base::binary); + auto buffer = std::unique_ptr(new char[resource_byte_size]); + ifs.read(buffer.get(), resource_byte_size); + ifs.close(); + + // Write output as a .c file. + std::ofstream ofs; + ofs.open(argv[1], std::ios_base::binary); + if (ofs.fail()) + { + std::cout << "Failed to open " << argv[1] << '\n'; + return EXIT_FAILURE; + } + + ofs << "#include " << std::endl; + ofs << "extern unsigned char const _resource_" << sym << "[] = {" << std::endl; + + size_t lineCount = 0; + for (int i = 0; i < resource_byte_size; ++i) + { + char c = buffer.get()[i]; + ofs << "0x" << std::hex << (c & 0xff) << ", "; + if (++lineCount == 10) + { + ofs << std::endl; + lineCount = 0; + } + } + + ofs << "};" << std::endl; + ofs << "extern size_t const _resource_" << sym << "_len = sizeof(_resource_" << sym + << ");"; + + ofs.close(); + + return EXIT_SUCCESS; +} diff --git a/lmtk/CMakeLists.txt b/lmtk/CMakeLists.txt index 7174fe0..37e2a10 100644 --- a/lmtk/CMakeLists.txt +++ b/lmtk/CMakeLists.txt @@ -48,10 +48,8 @@ target_link_libraries( lmgl lmpl lmlib - embed-resource::embed-resource Freetype::Freetype ${PLATFORM_LIBRARIES} - scope_guard::scope_guard Boost::Boost EnTT::EnTT SDL2::SDL2 diff --git a/lmtk/src/font/windows.cpp b/lmtk/src/font/windows.cpp index 7846312..2c0d6d6 100644 --- a/lmtk/src/font/windows.cpp +++ b/lmtk/src/font/windows.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include class font_loader_internal : public lmtk::ifont_loader { diff --git a/lmtk/src/rect_border.cpp b/lmtk/src/rect_border.cpp index f351e9f..3f4a2b6 100644 --- a/lmtk/src/rect_border.cpp +++ b/lmtk/src/rect_border.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include diff --git a/lmtk/src/shapes.cpp b/lmtk/src/shapes.cpp index 0dcca42..e847c2f 100644 --- a/lmtk/src/shapes.cpp +++ b/lmtk/src/shapes.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/lmtk/src/text_layout.cpp b/lmtk/src/text_layout.cpp index e018d76..f682471 100644 --- a/lmtk/src/text_layout.cpp +++ b/lmtk/src/text_layout.cpp @@ -2,7 +2,7 @@ #include FT_FREETYPE_H #include FT_GLYPH_H -#include +#include #include