From 7fbc3d13e2a23713956ccc3470d04fb8275279d9 Mon Sep 17 00:00:00 2001 From: Chris Fretz Date: Wed, 22 Jan 2020 19:20:03 -0500 Subject: [PATCH] Added Appveyor integration for Windows CI Culmination of the windows porting work so far Integration with visual studio is still to be improved, but is becoming very usable --- .appveyor.yml | 31 +++++++++++++++++++++++++++++++ .gitignore | 3 +++ .travis.yml | 2 +- CMakeLists.txt | 8 ++++---- README.md | 1 + include/dart/abi.h | 14 ++++++++++++++ src/buffer.cc | 4 +++- src/generic.cc | 8 +++++++- test/CMakeLists.txt | 4 ++-- test/buffer_abi_unit_tests.cc | 24 +++++++++++++++++++----- test/generic_abi_unit_tests.cc | 4 ++-- test/heap_abi_unit_tests.cc | 4 ++-- test/json_test.cc | 2 +- 13 files changed, 90 insertions(+), 19 deletions(-) create mode 100644 .appveyor.yml diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 0000000..8317ebd --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,31 @@ +build: + verbosity: detailed + +branches: + only: + - master + - development + +platform: x64 + +environment: + matrix: + - GENERATOR: Visual Studio 16 2019 + BUILD_TYPE: Debug + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + +build_script: + - mkdir tmp + - cd tmp + - curl -fsSL "https://github.com/microsoft/GSL/archive/v2.0.0.zip" -o gsl.zip + - 7z x gsl.zip + - Xcopy /E /I GSL-2.0.0\include\gsl ..\include\extern\gsl\ + - curl -fsSL "https://github.com/Tencent/rapidjson/archive/v1.1.0.zip" -o rapidjson.zip + - 7z x rapidjson.zip + - Xcopy /E /I rapidjson-1.1.0\include\rapidjson ..\include\extern\rapidjson + - cd .. + - mkdir build + - cd build + - cmake .. -G "%GENERATOR%" -A x64 -Dbuild_abi=ON -Dextended_test=ON + - cmake --build . --config %BUILD_TYPE% + - ctest --output-on-failure --build-config %BUILD_TYPE% diff --git a/.gitignore b/.gitignore index 79d2d44..b9c0218 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ *.DS_Store *.swp *.swo +.vs/* +CMakeSettings.json +out/* build/* docs/* benchmark/build/* diff --git a/.travis.yml b/.travis.yml index 86cb1b2..4cfa663 100644 --- a/.travis.yml +++ b/.travis.yml @@ -210,5 +210,5 @@ script: after_success: - | if [ "${TRAVIS_OS_NAME}" = "osx" ] && [ "${GEN_COVERAGE}" = "true" ]; then - coveralls -r . -b build/ -i include/ -i src/ -e include/extern/ -e include/dart/support/variant.h --gcov-options '\-lp' + coveralls -r . -b build/ -i include/ -i src/ -e include/extern/catch.h -e include/dart/support/variant.h --gcov-options '\-lp' fi diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a30389..a7af40c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,9 +19,9 @@ option(gen_coverage "Generate gcov coverage information in support envs" OFF) option(use_asan "Link tests with address sanitizer" OFF) # Check which dependencies are installed. -find_path(libgsl gsl/gsl) find_library(libyaml yaml) -find_path(librj rapidjson/reader.h) +find_path(libgsl gsl/gsl HINTS ${PROJECT_SOURCE_DIR}/include/extern) +find_path(librj rapidjson/reader.h HINTS ${PROJECT_SOURCE_DIR}/include/extern) if (NOT librj) CHECK_INCLUDE_FILE_CXX("rapidjson/reader.h" librj) endif () @@ -92,8 +92,8 @@ if (build_abi) # Set our preprocessor to export dll symbols if we're on windows. if (MSVC) - set_property(TARGET dart_abi APPEND PROPERTY COMPILE_DEFINITIONS DART_EXPORTS) - set_property(TARGET dart_abi_static APPEND PROPERTY COMPILE_DEFINITIONS DART_EXPORTS) + target_compile_definitions(dart_abi PUBLIC DART_EXPORTS=1) + target_compile_definitions(dart_abi_static PUBLIC DART_EXPORTS=1) endif () # Set compile switches based on what's installed diff --git a/README.md b/README.md index 8884856..3e16100 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ Dart ============== [![Build Status](https://travis-ci.com/target/libdart.svg?branch=master)](https://travis-ci.com/target/libdart) +[![Build status](https://ci.appveyor.com/api/projects/status/trv6dpc03nm3d9df?svg=true)](https://ci.appveyor.com/project/Cfretz244/libdart) [![Coverage Status](https://coveralls.io/repos/github/target/libdart/badge.svg?branch=master)](https://coveralls.io/github/target/libdart?branch=master) ### A High Performance, Network Optimized, JSON Manipulation Library **Dart** is both a wire-level binary `JSON` protocol, along with a high performance, diff --git a/include/dart/abi.h b/include/dart/abi.h index 9db4a8d..2b6d639 100644 --- a/include/dart/abi.h +++ b/include/dart/abi.h @@ -8118,6 +8118,20 @@ extern "C" { */ DART_ABI_EXPORT char const* dart_get_error(); + /** + * @brief + * Free a buffer returned from one of the dart_*_dup_bytes functions + * + * @details + * Dart requires its buffer representations to be aligned to a 64-bit + * boundary for internal design reasons (simplifies alignment logic significantly). + * Very easy to do on *nix machines with posix_memalign, which allocates aligned + * memory that can be passed directly to free. + * Windows, on the other hand, has _aligned_malloc and _aligned_free, which MUST + * be paired, so to write portable code this function must exist. + */ + DART_ABI_EXPORT void dart_aligned_free(void* ptr); + #ifdef __cplusplus } #endif diff --git a/src/buffer.cc b/src/buffer.cc index 735a385..ff56675 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -588,7 +588,9 @@ extern "C" { if (err) return err; // Assign to it. - auto* del = +[] (gsl::byte const* ptr) { free(const_cast(ptr)); }; + // We need to use dart_aligned_free here for the destructor as on windows, aligned alloc + // must be paired with a call to aligned free. Linux/Mac are just fine with normal free + auto* del = +[] (gsl::byte const* ptr) { dart_aligned_free(const_cast(ptr)); }; owner_type owner {reinterpret_cast(bytes), del}; return err_handler([&] { return buffer_unwrap( diff --git a/src/generic.cc b/src/generic.cc index 393360b..9299bd5 100644 --- a/src/generic.cc +++ b/src/generic.cc @@ -553,7 +553,9 @@ namespace { dart_err_t dart_take_bytes_rc_err_impl(dart_packet_t* dst, dart_rc_type_t rc, void* bytes) { using owner_type = std::unique_ptr; - auto* del = +[] (gsl::byte const* ptr) { free(const_cast(ptr)); }; + // We need to use dart_aligned_free here for the destructor as on windows, aligned alloc + // must be paired with a call to aligned free. Linux/Mac are just fine with normal free + auto* del = +[] (gsl::byte const* ptr) { dart_aligned_free(const_cast(ptr)); }; owner_type owner {reinterpret_cast(bytes), del}; return packet_typed_constructor_access( [&] (auto& dst) { @@ -1644,4 +1646,8 @@ extern "C" { return dart::detail::errmsg.data(); } + void dart_aligned_free(void* ptr) { + dart::shim::aligned_free(ptr); + } + } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d0fa091..37e91a4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -57,7 +57,7 @@ if (build_abi) target_link_libraries(abi_tests PUBLIC "-fsanitize=address") endif () - target_link_libraries(abi_tests PUBLIC dart_abi) + target_link_libraries(abi_tests PUBLIC dart_abi_static) target_include_directories(abi_tests PUBLIC ../include ${libgsl}) target_compile_options(abi_tests PUBLIC ${dart_default_compile_options} ${dart_test_compile_options}) set_property(TARGET unit_tests APPEND PROPERTY COMPILE_DEFINITIONS DART_HAS_ABI) @@ -109,7 +109,7 @@ if (librj) endif () if (build_abi) set_property(TARGET json_test APPEND PROPERTY COMPILE_DEFINITIONS DART_HAS_ABI) - target_link_libraries(json_test PUBLIC dart_abi) + target_link_libraries(json_test PUBLIC dart_abi_static) endif () # Generate coverage information if it was requested diff --git a/test/buffer_abi_unit_tests.cc b/test/buffer_abi_unit_tests.cc index 5381571..3327753 100644 --- a/test/buffer_abi_unit_tests.cc +++ b/test/buffer_abi_unit_tests.cc @@ -447,9 +447,9 @@ SCENARIO("buffer objects can be iterated over", "[buffer abi unit]") { SCENARIO("buffer objects can switch between finalized and non-finalized representations", "[buffer abi unit]") { GIVEN("an object with lots of contents") { - auto mut = dart_obj_init_va("sass,oidb,sidbn", + auto mut = dart_obj_init_va("sass,aidb,sidbn", "hello", "world", "arr", "one", "two", - "obj", "nest_int", 1337, "nest_dcm", 3.14159, "nest_bool", true, + "arr", 1337, 3.14159, true, "yes", "no", "int", 1337, "dcm", 3.14159, "bool", true, "none"); auto fin = dart_to_buffer(&mut); auto guard = make_scope_guard([&] { @@ -461,12 +461,26 @@ SCENARIO("buffer objects can switch between finalized and non-finalized represen // These functions are equivalent auto defin = dart_buffer_definalize(&fin); auto liftd = dart_buffer_lift(&fin); + + auto finbool = dart_buffer_obj_get(&fin, "bool"); + auto dynbool = dart_heap_obj_get(&defin, "bool"); + auto finarr = dart_buffer_obj_get(&fin, "arr"); + auto dynarr = dart_heap_obj_get(&defin, "arr"); auto guard = make_scope_guard([&] { + dart_heap_destroy(&dynarr); + dart_buffer_destroy(&finarr); + dart_heap_destroy(&dynbool); + dart_buffer_destroy(&finbool); dart_heap_destroy(&liftd); dart_heap_destroy(&defin); }); - THEN("it still compares equal with its original representation") { + REQUIRE(dart_buffer_is_bool(&finbool)); + REQUIRE(dart_heap_is_bool(&dynbool)); + REQUIRE(dart_buffer_is_obj(&fin)); + REQUIRE(dart_heap_is_obj(&defin)); + REQUIRE(dart_buffer_is_arr(&finarr)); + REQUIRE(dart_heap_is_arr(&dynarr)); REQUIRE(!dart_is_finalized(&defin)); REQUIRE(!dart_is_finalized(&liftd)); REQUIRE(dart_equal(&defin, &liftd)); @@ -512,8 +526,8 @@ SCENARIO("finalized buffer objects have unique object representations") { auto* ownone = dart_buffer_dup_bytes(&finone, &lenone); auto* owntwo = dart_buffer_dup_bytes(&fintwo, nullptr); auto guard = make_scope_guard([&] { - free(owntwo); - free(ownone); + dart_aligned_free(owntwo); + dart_aligned_free(ownone); }); REQUIRE(lenone == lentwo); REQUIRE(std::memcmp(ownone, owntwo, lenone) == 0); diff --git a/test/generic_abi_unit_tests.cc b/test/generic_abi_unit_tests.cc index a898c19..fb9b1ff 100644 --- a/test/generic_abi_unit_tests.cc +++ b/test/generic_abi_unit_tests.cc @@ -1120,8 +1120,8 @@ SCENARIO("finalized objects have unique object representations") { auto* ownone = dart_dup_bytes(&finone, &lenone); auto* owntwo = dart_dup_bytes(&fintwo, &lentwo); auto guard = make_scope_guard([&] { - free(owntwo); - free(ownone); + dart_aligned_free(owntwo); + dart_aligned_free(ownone); }); REQUIRE(lenone == lentwo); REQUIRE(std::memcmp(ownone, owntwo, lenone) == 0); diff --git a/test/heap_abi_unit_tests.cc b/test/heap_abi_unit_tests.cc index 740d38e..691d753 100644 --- a/test/heap_abi_unit_tests.cc +++ b/test/heap_abi_unit_tests.cc @@ -1118,8 +1118,8 @@ SCENARIO("heap finalized objects have unique object representations") { auto* ownone = dart_dup_bytes(&finone, &lenone); auto* owntwo = dart_dup_bytes(&fintwo, &lentwo); auto guard = make_scope_guard([&] { - free(owntwo); - free(ownone); + dart_aligned_free(owntwo); + dart_aligned_free(ownone); }); REQUIRE(lenone == lentwo); REQUIRE(std::memcmp(ownone, owntwo, lenone) == 0); diff --git a/test/json_test.cc b/test/json_test.cc index 258e1e3..69c2d23 100644 --- a/test/json_test.cc +++ b/test/json_test.cc @@ -254,7 +254,7 @@ TEST_CASE("dart_packet parses JSON via RapidJSON", "[json unit]") { compare_rj_dart_abi(packet, &buffertwo); compare_rj_dart_abi(packet, &bufferthree); compare_rj_dart_abi(packet, &bufferfour); - + // Validate the underlying buffer. auto pktdup = dart_take_bytes(dart_dup_bytes(&bufferone, nullptr)); auto pktduptwo = dart_take_bytes_rc(dart_dup_bytes(&bufferone, nullptr), DART_RC_SAFE);