diff --git a/CMakeLists.txt b/CMakeLists.txt index 661a2dd..581a375 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10) project(md5sum LANGUAGES CXX) if ("${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.13") - cmake_policy(SET CMP0077 NEW) + cmake_policy(SET CMP0077 NEW) endif() # ------------------------------------------------------------------------------------ # @@ -17,14 +17,14 @@ option(MD5_ENABLE_BENCHMARK "Enable benchmark of the md5sum library." OFF) set(CXX_STANDARDS) foreach (CXX_FEATURE ${CMAKE_CXX_COMPILE_FEATURES}) - if (CXX_FEATURE MATCHES "^cxx_std_[0-9]+$") - string(REGEX MATCH "[0-9]+$" CXX_STANDARD ${CXX_FEATURE}) - list(APPEND CXX_STANDARDS ${CXX_STANDARD}) # supported c++ standards - endif() + if (CXX_FEATURE MATCHES "^cxx_std_[0-9]+$") + string(REGEX MATCH "[0-9]+$" CXX_STANDARD ${CXX_FEATURE}) + list(APPEND CXX_STANDARDS ${CXX_STANDARD}) # supported c++ standards + endif() endforeach() if (NOT 17 IN_LIST CXX_STANDARDS) - message(FATAL_ERROR "MD5 project require at least C++17.") + message(FATAL_ERROR "MD5 project require at least C++17.") endif() list(GET CXX_STANDARDS -1 MD5_CXX_STANDARD) # select the latest C++ standard @@ -34,27 +34,41 @@ set(CMAKE_CXX_STANDARD ${MD5_CXX_STANDARD}) # ------------------------------------------------------------------------------------ # if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) # using release build in default + set(CMAKE_BUILD_TYPE Release) # using release build in default endif() -add_compile_options(-Wall -Wextra -Werror) -if (MD5_ENABLE_LTO) +if (MSVC) + add_compile_options(/W4) # TODO: add `/WX` after fix MSVC warnings + if (MD5_ENABLE_LTO) + add_compile_options(/GL) + add_link_options(/LTCG) + endif() +else() + add_compile_options(-Wall -Wextra -Werror) + if (MD5_ENABLE_LTO) add_compile_options(-flto=auto) + endif() endif() +# ------------------------------------------------------------------------------------ # + file(GLOB MD5_SRC src/impl/*.cc) if (NOT MD5_SHARED_LIB) - add_library(md5sum STATIC ${MD5_SRC}) + add_library(md5sum STATIC ${MD5_SRC}) else() - add_library(md5sum SHARED ${MD5_SRC}) + add_library(md5sum SHARED ${MD5_SRC}) + if (NOT MSVC) target_compile_options(md5sum PRIVATE -fvisibility=hidden) + endif() endif() -set(MD5_COMPILE_OPTIONS - -fno-rtti - -fno-exceptions - -fno-unwind-tables - -fno-asynchronous-unwind-tables) +if (MSVC) + set(MD5_COMPILE_OPTIONS /GR-) +else() + set(MD5_COMPILE_OPTIONS + -fno-rtti -fno-exceptions + -fno-unwind-tables -fno-asynchronous-unwind-tables) +endif() target_compile_options(md5sum PRIVATE ${MD5_COMPILE_OPTIONS}) target_include_directories(md5sum PUBLIC src/) @@ -64,9 +78,9 @@ add_library(md5sum::md5 ALIAS md5sum) # ------------------------------------------------------------------------------------ # if (MD5_BUILD_DEMO) - add_executable(md5_demo demo.cc) - target_link_libraries(md5_demo PRIVATE md5sum) - target_compile_options(md5_demo PRIVATE ${MD5_COMPILE_OPTIONS}) + add_executable(md5_demo demo.cc) + target_link_libraries(md5_demo PRIVATE md5sum) + target_compile_options(md5_demo PRIVATE ${MD5_COMPILE_OPTIONS}) endif() # ------------------------------------------------------------------------------------ # @@ -74,17 +88,17 @@ endif() include(third_party/ThirdParty.cmake) if (MD5_ENABLE_TESTING) - enable_testing() - file(GLOB MD5_TEST_SRC test/*.cc) - add_executable(md5_test ${MD5_TEST_SRC}) - target_link_libraries(md5_test PRIVATE md5sum GTest::gtest_main) - add_test(NAME md5_test COMMAND md5_test) + enable_testing() + file(GLOB MD5_TEST_SRC test/*.cc) + add_executable(md5_test ${MD5_TEST_SRC}) + target_link_libraries(md5_test PRIVATE md5sum GTest::gtest_main) + add_test(NAME md5_test COMMAND md5_test) endif() if (MD5_ENABLE_BENCHMARK) - add_executable(md5_benchmark benchmark.cc) - target_link_libraries(md5_benchmark PRIVATE md5sum benchmark::benchmark_main) - target_compile_options(md5_benchmark PRIVATE ${MD5_COMPILE_OPTIONS}) + add_executable(md5_benchmark benchmark.cc) + target_link_libraries(md5_benchmark PRIVATE md5sum benchmark::benchmark_main) + target_compile_options(md5_benchmark PRIVATE ${MD5_COMPILE_OPTIONS}) endif() # ------------------------------------------------------------------------------------ # diff --git a/src/impl/constexpr.inl b/src/impl/constexpr.inl index 1e7965e..e6d1d8a 100644 --- a/src/impl/constexpr.inl +++ b/src/impl/constexpr.inl @@ -36,10 +36,13 @@ constexpr Block GetBlock(const md5_data &data, const uint64_t index) { Block block {}; for (int i = 0; i < 16; ++i) { const auto offset = index + i * 4; - (block[i] <<= 8) |= GetByte(data, offset + 3); - (block[i] <<= 8) |= GetByte(data, offset + 2); - (block[i] <<= 8) |= GetByte(data, offset + 1); - (block[i] <<= 8) |= GetByte(data, offset + 0); + block[i] |= GetByte(data, offset + 3); + block[i] <<= 8; + block[i] |= GetByte(data, offset + 2); + block[i] <<= 8; + block[i] |= GetByte(data, offset + 1); + block[i] <<= 8; + block[i] |= GetByte(data, offset + 0); } return block; } diff --git a/src/impl/core.cc b/src/impl/core.cc index 3e48130..251d2d5 100644 --- a/src/impl/core.cc +++ b/src/impl/core.cc @@ -16,17 +16,24 @@ using md5::value::T; #define H(x, y, z) (x ^ y ^ z) #define I(x, y, z) (y ^ (x | ~z)) -#define STEP(i, f, a, b, c, d) \ +#define MD5_ROUND(i, f, a, b, c, d) \ do { \ a += f(b, c, d) + block[K(i)] + T(i); \ a = a << S(i) | a >> (32 - S(i)); \ a += b; \ } while (0) -#define FF(i, ...) STEP((0x00 | i), F, __VA_ARGS__) -#define GG(i, ...) STEP((0x10 | i), G, __VA_ARGS__) -#define HH(i, ...) STEP((0x20 | i), H, __VA_ARGS__) -#define II(i, ...) STEP((0x30 | i), I, __VA_ARGS__) +#ifdef _MSC_VER +#define EXPAND(...) __VA_ARGS__ +#define ROUND(...) EXPAND(MD5_ROUND(__VA_ARGS__)) +#else +#define ROUND MD5_ROUND +#endif + +#define FF(i, ...) ROUND(i | 0x00, F, __VA_ARGS__) +#define GG(i, ...) ROUND(i | 0x10, G, __VA_ARGS__) +#define HH(i, ...) ROUND(i | 0x20, H, __VA_ARGS__) +#define II(i, ...) ROUND(i | 0x30, I, __VA_ARGS__) #define MD5_UPDATE(OP) \ OP(0x0, R1); OP(0x1, R2); OP(0x2, R3); OP(0x3, R4); \ diff --git a/src/md5.h b/src/md5.h index bb098ac..50d25d2 100644 --- a/src/md5.h +++ b/src/md5.h @@ -7,10 +7,18 @@ static_assert(sizeof(uintptr_t) == 8, "Project only works on 64-bits architecture."); +#ifdef _MSC_VER +static_assert('\x01\x02\x03\x04' == 0x04030201, +#else static_assert(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__, +#endif "Project only works on little-endian architecture."); +#if defined(__clang__) || defined(__GNUC__) #define MD5_EXPORT __attribute__ ((visibility ("default"))) +#else +#define MD5_EXPORT +#endif #include "impl/value.inl" #include "impl/constexpr.inl" diff --git a/third_party/ThirdParty.cmake b/third_party/ThirdParty.cmake index a49bfe0..14a24cf 100644 --- a/third_party/ThirdParty.cmake +++ b/third_party/ThirdParty.cmake @@ -1,9 +1,14 @@ if (MD5_ENABLE_TESTING) - add_subdirectory(third_party/googletest/ EXCLUDE_FROM_ALL) + if (MSVC) + set(gtest_force_shared_crt ON) + endif() + add_subdirectory(third_party/googletest/ EXCLUDE_FROM_ALL) endif() if (MD5_ENABLE_BENCHMARK) - set(BENCHMARK_ENABLE_TESTING OFF) + if (NOT MSVC) set(BENCHMARK_ENABLE_EXCEPTIONS OFF) - add_subdirectory(third_party/benchmark/ EXCLUDE_FROM_ALL) + endif() + set(BENCHMARK_ENABLE_TESTING OFF) + add_subdirectory(third_party/benchmark/ EXCLUDE_FROM_ALL) endif()