diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ea49b68..f870b4d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,7 @@ jobs: - name: Configure cmake shell: bash working-directory: ${{ runner.workspace }}/build - run: cmake -S $GITHUB_WORKSPACE/ffi -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -Dmun_build_examples=ON -Dmun_build_tests=ON -Dmun_executable_path=$GITHUB_WORKSPACE/ffi/bin/${{ matrix.config.artifact-name }} -Dmun_examples_path=$GITHUB_WORKSPACE/mun/examples + run: cmake -S $GITHUB_WORKSPACE/ffi -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -Dmun_build_examples=ON -Dmun_build_tests=ON -Dmun_executable_url_or_path=$GITHUB_WORKSPACE/ffi/bin/${{ matrix.config.artifact-name }} -Dmun_examples_path=$GITHUB_WORKSPACE/mun/examples - name: Build shell: bash diff --git a/.gitignore b/.gitignore index 14842df..64371f0 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,4 @@ CMakeSettings.json # Build artifacts *.munlib **/target/* +build/ diff --git a/.gitmodules b/.gitmodules index 4e7b1bf..593444e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ -[submodule "external/catch2"] - path = external/catch2 +[submodule "catch2"] + path = cpp/tests/catch2 url = https://github.com/catchorg/Catch2.git -[submodule "external/md5"] - path = external/md5 - url = https://github.com/Wodann/constexpr-md5-cpp.git diff --git a/CMakeLists.txt b/CMakeLists.txt index bbe888c..2745090 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,9 @@ project(MunRuntime VERSION 0.1.0 LANGUAGES C CXX) option(mun_build_examples "Build all of Mun's own examples." OFF) option(mun_build_tests "Build all of Mun's own tests." OFF) +set(mun_library_url_or_path "" CACHE FILEPATH "Location of an archive on the web or a local directory containing containing the Mun libraries.") + +set(cpp_source_dir ${CMAKE_CURRENT_SOURCE_DIR}/cpp) # Determine platform (32/64) if (${CMAKE_SIZEOF_VOID_P} EQUAL 8) @@ -15,7 +18,7 @@ add_library(MunRuntime SHARED IMPORTED GLOBAL) set_target_properties(MunRuntime PROPERTIES INTERFACE_INCLUDE_DIRECTORIES - "${CMAKE_CURRENT_SOURCE_DIR}/include;${CMAKE_CURRENT_SOURCE_DIR}/external/md5/include" + "${cpp_source_dir}/include" ) if (X64) @@ -29,17 +32,41 @@ if (X64) message(ERROR "Unsupported operating system.") endif () else () - message(ERROR "64-bit operating systems are not supported at present.") + message(ERROR "Only 64-bit operating systems are supported at present.") +endif () + +include(ExternalProject) + +if (mun_library_url_or_path) + if (IS_DIRECTORY ${mun_library_url_or_path}) + set(mun_library_dir ${mun_library_url_or_path}) + else () + # Download the mun libraries + ExternalProject_Add( + mun_library_download + PREFIX ${CMAKE_BINARY_DIR}/mun + URL ${mun_library_url_or_path} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + ExternalProject_Get_Property(mun_library_download source_dir) + set(mun_library_dir ${source}) + add_dependencies(MunRuntime mun_library_download) + endif () +else () + message(FATAL_ERROR "You must specify the mun_library_url_or_path to be able to test the Mun Runtime") endif () set_target_properties(MunRuntime PROPERTIES - IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/bin/${mun_os}/${CMAKE_SHARED_LIBRARY_PREFIX}mun_runtime${CMAKE_SHARED_LIBRARY_SUFFIX} + IMPORTED_LOCATION ${mun_library_dir}/${CMAKE_SHARED_LIBRARY_PREFIX}mun_runtime${CMAKE_SHARED_LIBRARY_SUFFIX} ) if (WIN32) set_target_properties(MunRuntime PROPERTIES - IMPORTED_IMPLIB ${CMAKE_CURRENT_SOURCE_DIR}/bin/${mun_os}/mun_runtime${CMAKE_SHARED_LIBRARY_SUFFIX}.lib -) + IMPORTED_IMPLIB ${mun_library_dir}/mun_runtime${CMAKE_SHARED_LIBRARY_SUFFIX}.lib + ) endif () if (mun_build_examples) @@ -48,5 +75,5 @@ endif () include(CTest) if (mun_build_tests) - add_subdirectory(tests) + add_subdirectory(${cpp_source_dir}/tests) endif () diff --git a/bin/linux64/libmun_runtime.so b/bin/linux64/libmun_runtime.so deleted file mode 100644 index a071508..0000000 Binary files a/bin/linux64/libmun_runtime.so and /dev/null differ diff --git a/bin/osx64/libmun_runtime.dylib b/bin/osx64/libmun_runtime.dylib deleted file mode 100644 index fc50246..0000000 Binary files a/bin/osx64/libmun_runtime.dylib and /dev/null differ diff --git a/bin/win64/mun_runtime.dll b/bin/win64/mun_runtime.dll deleted file mode 100644 index 0cc958f..0000000 Binary files a/bin/win64/mun_runtime.dll and /dev/null differ diff --git a/bin/win64/mun_runtime.dll.lib b/bin/win64/mun_runtime.dll.lib deleted file mode 100644 index 009326a..0000000 Binary files a/bin/win64/mun_runtime.dll.lib and /dev/null differ diff --git a/LICENSE-APACHE b/cpp/LICENSE-APACHE similarity index 100% rename from LICENSE-APACHE rename to cpp/LICENSE-APACHE diff --git a/LICENSE-MIT b/cpp/LICENSE-MIT similarity index 100% rename from LICENSE-MIT rename to cpp/LICENSE-MIT diff --git a/README.md b/cpp/README.md similarity index 100% rename from README.md rename to cpp/README.md diff --git a/include/mun/error.h b/cpp/include/mun/error.h similarity index 100% rename from include/mun/error.h rename to cpp/include/mun/error.h diff --git a/include/mun/function.h b/cpp/include/mun/function.h similarity index 100% rename from include/mun/function.h rename to cpp/include/mun/function.h diff --git a/include/mun/gc.h b/cpp/include/mun/gc.h similarity index 100% rename from include/mun/gc.h rename to cpp/include/mun/gc.h diff --git a/include/mun/invoke_fn.h b/cpp/include/mun/invoke_fn.h similarity index 100% rename from include/mun/invoke_fn.h rename to cpp/include/mun/invoke_fn.h diff --git a/include/mun/invoke_result.h b/cpp/include/mun/invoke_result.h similarity index 100% rename from include/mun/invoke_result.h rename to cpp/include/mun/invoke_result.h diff --git a/include/mun/marshal.h b/cpp/include/mun/marshal.h similarity index 100% rename from include/mun/marshal.h rename to cpp/include/mun/marshal.h diff --git a/cpp/include/mun/md5.h b/cpp/include/mun/md5.h new file mode 100644 index 0000000..8414a99 --- /dev/null +++ b/cpp/include/mun/md5.h @@ -0,0 +1,222 @@ +/* + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Created by: https://github.com/Wodann/constexpr-md5-cpp + */ + +#ifndef CONSTEXPR_MD5_H_ +#define CONSTEXPR_MD5_H_ + +#include +#include +#include +#include + +namespace md5 { + using Digest = std::array; + + namespace details { + constexpr uint32_t CBLOCK = 64; + constexpr uint32_t LBLOCK = CBLOCK / 4; + + constexpr size_t const_strlen(const char* str) { + return (*str == 0) ? 0 : const_strlen(str + 1) + 1; + } + + constexpr Digest make_digest(const std::array& input) noexcept { + Digest digest{}; + for (size_t i = 0; i < input.size(); ++i) { + digest[i * 4] = static_cast((input[i]) & 0xff); + digest[i * 4 + 1] = static_cast((input[i] >> 8) & 0xff); + digest[i * 4 + 2] = static_cast((input[i] >> 16) & 0xff); + digest[i * 4 + 3] = static_cast((input[i] >> 24) & 0xff); + } + return digest; + } + + using Fn = uint32_t(*)(uint32_t, uint32_t, uint32_t); + constexpr uint32_t f(uint32_t b, uint32_t c, uint32_t d) noexcept { + return (b & c) | (~b & d); + } + + constexpr uint32_t g(uint32_t b, uint32_t c, uint32_t d) noexcept { + return (b & d) | (c & ~d); + } + + constexpr uint32_t h(uint32_t b, uint32_t c, uint32_t d) noexcept { + return b ^ c ^ d; + } + + constexpr uint32_t i(uint32_t b, uint32_t c, uint32_t d) noexcept { + return c ^ (b | ~d); + } + + constexpr Fn F[4] = { f, g, h, i }; + + constexpr uint32_t G[CBLOCK] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, + 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, + 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 + }; + + constexpr uint32_t K[CBLOCK] = { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 + }; + + constexpr uint32_t S[LBLOCK] = { + 7, 12, 17, 22, + 5, 9, 14, 20, + 4, 11, 16, 23, + 6, 10, 15, 21 + }; + + constexpr char PADDING[CBLOCK] = { + -128, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 = -128 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + constexpr uint32_t rotate(uint32_t x, uint32_t n) noexcept { + return (x << n) | (x >> (32 - n)); + } + + constexpr uint32_t t(Fn f, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t s, uint32_t ac) noexcept { + return b + rotate(a + f(b, c, d) + x + ac, s); + } + + constexpr uint32_t to_uint32(const unsigned char* data) noexcept { + return + (static_cast(data[3]) << 24) | + (static_cast(data[2]) << 16) | + (static_cast(data[1]) << 8) | + (static_cast(data[0])); + } + + struct Context { + std::array buffer; + std::array state; + uint32_t nl, nh; + + constexpr Context() noexcept + : buffer() + , state{ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 } + , nl(0) + , nh(0) + {} + + constexpr void append(const char* data, size_t len) noexcept { + std::array input{}; + auto k = (nl >> 3) & 0x3f; + auto length = static_cast(len); + nl += length << 3; + if (nl < length << 3) { + nh += 1; + } + nh += length >> 29; + for (auto ptr = data; ptr != data + len; ++ptr) { + buffer[k++] = static_cast(static_cast(*ptr) + UCHAR_MAX + 1); + if (k == 0x40) { + auto j = 0; + for (auto i = 0; i < LBLOCK; ++i) { + input[i] = to_uint32(&buffer[j]); + j += 4; + } + transform(input); + k = 0; + } + } + } + + constexpr void transform(const std::array& input) noexcept { + auto a = state[0], b = state[1], c = state[2], d = state[3]; + for (uint32_t r = 0; r < 4; ++r) { + const auto g = G + r * LBLOCK; + const auto s = S + r * 4; + const auto k = K + r * LBLOCK; + + for (auto i = 0; i < input.size(); ++i) { + const auto new_b = t(F[r], a, b, c, d, input[g[i]], s[i % 4], k[i]); + a = d; + d = c; + c = b; + b = new_b; + } + } + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + } + + constexpr Digest final() noexcept { + + std::array input{}; + const auto k = ((nl >> 3) & 0x3f); + input[14] = nl; + input[15] = nh; + + append(PADDING, k < 56 ? 56 - k : 120 - k); + + auto j = 0; + for (auto i = 0; i < 14; ++i) { + input[i] = to_uint32(&buffer[j]); + j += 4; + } + transform(input); + + return make_digest(state); + } + }; + } + + template + constexpr Digest compute(const char(&data)[N]) noexcept { + details::Context c; + // Don't hash the null-terminator + c.append(data, N - 1); + return c.final(); + } + + constexpr Digest compute(const char* s) noexcept { + details::Context c; + // Don't hash the null-terminator + c.append(s, details::const_strlen(s)); + return c.final(); + } +} + +#endif diff --git a/include/mun/mun.h b/cpp/include/mun/mun.h similarity index 100% rename from include/mun/mun.h rename to cpp/include/mun/mun.h diff --git a/include/mun/reflection.h b/cpp/include/mun/reflection.h similarity index 100% rename from include/mun/reflection.h rename to cpp/include/mun/reflection.h diff --git a/include/mun/runtime.h b/cpp/include/mun/runtime.h similarity index 100% rename from include/mun/runtime.h rename to cpp/include/mun/runtime.h diff --git a/include/mun/runtime_capi.h b/cpp/include/mun/runtime_capi.h similarity index 100% rename from include/mun/runtime_capi.h rename to cpp/include/mun/runtime_capi.h diff --git a/include/mun/struct_ref.h b/cpp/include/mun/struct_ref.h similarity index 100% rename from include/mun/struct_ref.h rename to cpp/include/mun/struct_ref.h diff --git a/include/mun/type_info.h b/cpp/include/mun/type_info.h similarity index 99% rename from include/mun/type_info.h rename to cpp/include/mun/type_info.h index 7262c67..3565f71 100644 --- a/include/mun/type_info.h +++ b/cpp/include/mun/type_info.h @@ -1,10 +1,9 @@ #ifndef MUN_TYPE_INFO_H #define MUN_TYPE_INFO_H -#include - #include +#include "mun/md5.h" #include "mun/runtime_capi.h" namespace mun { diff --git a/include/mun/util.h b/cpp/include/mun/util.h similarity index 100% rename from include/mun/util.h rename to cpp/include/mun/util.h diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt new file mode 100644 index 0000000..5ae4659 --- /dev/null +++ b/cpp/tests/CMakeLists.txt @@ -0,0 +1,78 @@ +include(ExternalProject) + +set(mun_executable_url_or_path "" CACHE FILEPATH "Location of an archive on the web or a local directory containing containing the Mun executable. This is required for building the Mun test snippets") + +add_executable(mun_executable IMPORTED) +if (mun_executable_url_or_path) + if (IS_DIRECTORY ${mun_executable_url_or_path}) + set_target_properties(mun_executable PROPERTIES IMPORTED_LOCATION ${mun_executable_url_or_path}/mun${CMAKE_EXECUTABLE_SUFFIX}) + else () + # Download the mun executable + ExternalProject_Add( + mun_executable_download + PREFIX ${CMAKE_CURRENT_BINARY_DIR}/mun + URL ${mun_executable_url_or_path} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + + ExternalProject_Get_Property(mun_executable_download source_dir) + set_target_properties(mun_executable PROPERTIES IMPORTED_LOCATION ${source_dir}/mun${CMAKE_EXECUTABLE_SUFFIX}) + add_dependencies(mun_executable mun_executable_download) + endif () +else () + message(FATAL_ERROR "You must specify the mun_executable_url_or_path to be able to test the Mun Runtime") +endif () + +if (NOT mun_examples_path) + message(FATAL_ERROR "You must specify the mun_examples_path to be able to test the Mun Runtime") +endif () + +# Sanitize the path, since we're forwarding this to C++ +file(TO_CMAKE_PATH ${mun_examples_path} mun_examples_path) + +# Find all mun files +set(mun_folder ${CMAKE_CURRENT_SOURCE_DIR}/..) +file(GLOB_RECURSE mun_test_files RELATIVE ${mun_examples_path} ${mun_examples_path}/*.toml) +set(mun_tests) + +foreach (mun_file ${mun_test_files}) + get_filename_component(mun_file_dir ${mun_file} DIRECTORY) + set(abs_package_dir ${mun_examples_path}/${mun_file_dir}) + set(abs_toml_file ${abs_package_dir}/mun.toml) + set(mun_executable_file mod.munlib) + set(mun_executable_path ${abs_package_dir}/target/${mun_executable_file}) + add_custom_command( + OUTPUT ${mun_executable_path} + COMMAND mun_executable build --manifest-path "${abs_toml_file}" + WORKING_DIRECTORY ${abs_package_dir} + MAIN_DEPENDENCY ${abs_toml_file}) + list(APPEND mun_tests ${mun_executable_path}) +endforeach () + +add_custom_target(mun_test_munlibs ALL + DEPENDS ${mun_tests}) + +# Add the tests +add_executable(MunRuntimeTests + catch_main.cc + marshal.cc + runtime.cc + extern.cc +) + +target_include_directories(MunRuntimeTests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/catch2/single_include ${mun_folder}/include) +target_link_libraries(MunRuntimeTests MunRuntime) +add_dependencies(MunRuntimeTests mun_test_munlibs) +target_compile_definitions(MunRuntimeTests PRIVATE -DMUN_TEST_DIR="${mun_examples_path}/") +set_property(TARGET MunRuntimeTests PROPERTY CXX_STANDARD 17) + +add_custom_command(TARGET MunRuntimeTests POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + $ + $) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/catch2/contrib") +include(Catch) +catch_discover_tests(MunRuntimeTests) diff --git a/external/catch2 b/cpp/tests/catch2 similarity index 100% rename from external/catch2 rename to cpp/tests/catch2 diff --git a/tests/catch_main.cc b/cpp/tests/catch_main.cc similarity index 100% rename from tests/catch_main.cc rename to cpp/tests/catch_main.cc diff --git a/tests/extern.cc b/cpp/tests/extern.cc similarity index 100% rename from tests/extern.cc rename to cpp/tests/extern.cc diff --git a/tests/marshal.cc b/cpp/tests/marshal.cc similarity index 100% rename from tests/marshal.cc rename to cpp/tests/marshal.cc diff --git a/tests/runtime.cc b/cpp/tests/runtime.cc similarity index 100% rename from tests/runtime.cc rename to cpp/tests/runtime.cc diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 41a28b6..48dbeda 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,22 +1 @@ -add_executable(MunExample - src/main.cc -) - -target_compile_features(MunExample - PRIVATE - cxx_std_17 -) - -include(FindThreads) - -target_link_libraries(MunExample - PRIVATE - MunRuntime - Threads::Threads -) - -add_custom_command(TARGET MunExample PRE_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different - $ - $ -) +add_subdirectory(buoyancy) diff --git a/examples/buoyancy/CMakeLists.txt b/examples/buoyancy/CMakeLists.txt new file mode 100644 index 0000000..8b61ca6 --- /dev/null +++ b/examples/buoyancy/CMakeLists.txt @@ -0,0 +1,22 @@ +add_executable(MunExampleBuoyancy + main.cc +) + +target_compile_features(MunExampleBuoyancy + PRIVATE + cxx_std_17 +) + +include(FindThreads) + +target_link_libraries(MunExampleBuoyancy + PRIVATE + MunRuntime + Threads::Threads +) + +add_custom_command(TARGET MunExampleBuoyancy PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + $ + $ +) diff --git a/examples/src/main.cc b/examples/buoyancy/main.cc similarity index 100% rename from examples/src/main.cc rename to examples/buoyancy/main.cc diff --git a/external/md5 b/external/md5 deleted file mode 160000 index 8dd3dda..0000000 --- a/external/md5 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8dd3ddace19f7dd5fcf9a8cf3e63242130d350de diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt deleted file mode 100644 index a857f79..0000000 --- a/tests/CMakeLists.txt +++ /dev/null @@ -1,77 +0,0 @@ -include(ExternalProject) - -set(mun_executable_path "" CACHE FILEPATH "Location of the Mun executable. This or mun_executable_url is required for building the Mun test snippets") -set(mun_executable_url "" CACHE FILEPATH "Location of the Mun executable on the web. This or mun_executable_path is required for building the Mun test snippets") - -set(mun_examples_path "" CACHE FILEPATH "Location of the Mun example source. This is required for building the Mun test snippets") - -# Download the mun binary -add_executable(mun_binary IMPORTED) -string(TOUPPER ${mun_os} mun_os_uppercase) -if (mun_executable_path) - set_target_properties(mun_binary PROPERTIES IMPORTED_LOCATION ${mun_executable_path}/mun${CMAKE_EXECUTABLE_SUFFIX}) -elseif (mun_executable_url) - ExternalProject_Add( - mun_binary_download - PREFIX ${CMAKE_CURRENT_BINARY_DIR}/mun - URL ${mun_executable_url} - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - ) - - ExternalProject_Get_Property(mun_binary_download source_dir) - set_target_properties(mun_binary PROPERTIES IMPORTED_LOCATION ${source_dir}/mun${CMAKE_EXECUTABLE_SUFFIX}) - add_dependencies(mun_binary mun_binary_download) -else () - message(FATAL_ERROR "You must specify either the mun_executable_url or mun_executable_path to be able to test the Mun Runtime") -endif () - -if (NOT mun_examples_path) - message(FATAL_ERROR "You must specify the mun_examples_path to be able to test the Mun Runtime") -endif () - -# Find all mun files -set(mun_folder ${CMAKE_CURRENT_SOURCE_DIR}/..) -file(GLOB_RECURSE mun_test_files RELATIVE ${mun_examples_path} ${mun_examples_path}/*.toml) -set(mun_tests) - -foreach (mun_file ${mun_test_files}) - get_filename_component(mun_file_dir ${mun_file} DIRECTORY) - set(abs_package_dir ${mun_examples_path}/${mun_file_dir}) - set(abs_toml_file ${abs_package_dir}/mun.toml) - set(mun_binary_file mod.munlib) - set(mun_binary_path ${abs_package_dir}/target/${mun_binary_file}) - add_custom_command( - OUTPUT ${mun_binary_path} - COMMAND mun_binary build --manifest-path "${abs_toml_file}" - WORKING_DIRECTORY ${abs_package_dir} - MAIN_DEPENDENCY ${abs_toml_file}) - list(APPEND mun_tests ${mun_binary_path}) -endforeach () - -add_custom_target(mun_test_munlibs ALL - DEPENDS ${mun_tests}) - -# Add the tests -add_executable(MunRuntimeTests - catch_main.cc - marshal.cc - runtime.cc - extern.cc -) - -target_include_directories(MunRuntimeTests PRIVATE ${mun_folder}/external/catch2/single_include ${mun_folder}/include) -target_link_libraries(MunRuntimeTests MunRuntime) -add_dependencies(MunRuntimeTests mun_test_munlibs) -target_compile_definitions(MunRuntimeTests PRIVATE -DMUN_TEST_DIR="${mun_examples_path}/") -set_property(TARGET MunRuntimeTests PROPERTY CXX_STANDARD 17) - -add_custom_command(TARGET MunRuntimeTests POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - $ - $) - -list(APPEND CMAKE_MODULE_PATH "${mun_folder}/external/catch2/contrib") -include(Catch) -catch_discover_tests(MunRuntimeTests)