diff --git a/CMakeLists.txt b/CMakeLists.txt index e915c8e2..8f4c3c00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ set(DXFCXX_VERSION "v4.2.0" CACHE STRING "The dxFeed Graal CXX API package versi dxfcxx_ParseVersion(${DXFCXX_VERSION} DXFCXX_MAJOR_VERSION DXFCXX_MINOR_VERSION DXFCXX_PATCH_VERSION DXFCXX_SUFFIX_VERSION) -set(DXFEED_GRAAL_NATIVE_SDK_VERSION "2.2.1" CACHE STRING "") +set(DXFEED_GRAAL_NATIVE_SDK_VERSION "2.5.0" CACHE STRING "") set(FMTLIB_VERSION "11.0.2") set(BOOST_VERSION "1.84.0") set(UTFCPP_VERSION "3.2.3") @@ -63,7 +63,7 @@ option(DXFCXX_INSTALL_SAMPLES "Prepare install the samples" ${DXFCXX_IS_ROOT_PRO option(DXFCXX_INSTALL_TOOLS "Prepare install the tools" ${DXFCXX_IS_ROOT_PROJECT}) option(DXFCXX_LINK_STATIC_RUNTIME "Compile and link with -MT/-MTd or equivalent flag(s) to use a multi-threaded statically-linked runtime library. Visual Studio only." OFF) -option(DXFCXX_NODEFAULTLIB_LIBCMT "Ignore libcmt/libcmtd. Use if DXFCXX_LINK_STATIC_RUNTIME == ON." ${DXFCXX_LINK_STATIC_RUNTIME}) +option(DXFCXX_NODEFAULTLIB "Ignore libcmt/libcmtd/msvcrt/msvcrtd. Use if DXFCXX_LINK_STATIC_RUNTIME == ON." ${DXFCXX_LINK_STATIC_RUNTIME}) option(DXFCXX_ENABLE_METRICS "Enable metrics collection" OFF) @@ -93,6 +93,7 @@ set(DXFCXX_GRAAL_TARGET_CPU "unknown" CACHE STRING "") include(cmake/ParseAndDetectPlatforms.cmake) include(cmake/LinkStacktrace.cmake) include(cmake/LinkAsanUbsan.cmake) +include(cmake/SetupStaticRuntimeMSVC.cmake) if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/third_party/graal-native-sdk-${DXFEED_GRAAL_NATIVE_SDK_VERSION}-${DXFCXX_GRAAL_TARGET_PLATFORM}/CMakeLists.txt") add_subdirectory(third_party/graal-native-sdk-${DXFEED_GRAAL_NATIVE_SDK_VERSION}-${DXFCXX_GRAAL_TARGET_PLATFORM}) @@ -146,17 +147,8 @@ else () CPMAddPackage("gh:ttldtor/Process#v${PROCESS_VERSION}") endif () -if (DXFCXX_LINK_STATIC_RUNTIME) - set_target_properties(process PROPERTIES - MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" - ) - - if (DXFCXX_NODEFAULTLIB_LIBCMT) - target_link_options(process PRIVATE - "/NODEFAULTLIB:LIBCMT" - "/NODEFAULTLIB:LIBCMTD" - ) - endif () +if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")) + SetupStaticRuntimeMSVC(process ${DXFCXX_LINK_STATIC_RUNTIME} ${DXFCXX_NODEFAULTLIB}) endif () if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/third_party/Console-${CONSOLE_VERSION}/CMakeLists.txt") @@ -165,12 +157,20 @@ else () CPMAddPackage("gh:ttldtor/Console#v${CONSOLE_VERSION}") endif () +if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")) + SetupStaticRuntimeMSVC(console ${DXFCXX_LINK_STATIC_RUNTIME} ${DXFCXX_NODEFAULTLIB}) +endif () + if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/third_party/portals/CMakeLists.txt") add_subdirectory(third_party/portals) else () CPMAddPackage("gh:ttldtor/portals#default") endif () +if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")) + SetupStaticRuntimeMSVC(portals ${DXFCXX_LINK_STATIC_RUNTIME} ${DXFCXX_NODEFAULTLIB}) +endif () + add_subdirectory(third_party/utfcpp-${UTFCPP_VERSION}) set(FMT_INSTALL OFF) @@ -189,6 +189,10 @@ else () FetchContent_MakeAvailable(fmt) endif () +if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")) + SetupStaticRuntimeMSVC(fmt ${DXFCXX_LINK_STATIC_RUNTIME} ${DXFCXX_NODEFAULTLIB}) +endif () + #set(BUILD_TZ_LIB ON) #set(USE_SYSTEM_TZ_DB ON) add_subdirectory(third_party/date-${DATE_VERSION}) @@ -469,20 +473,9 @@ add_library(dxfcxx ALIAS ${PROJECT_NAME}) add_library(dxfcxx::static ALIAS ${PROJECT_NAME}_static) add_library(dxfcxx::graal ALIAS DxFeedGraalNativeSdk) -if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - set_target_properties(${PROJECT_NAME} PROPERTIES CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) - if (DXFCXX_LINK_STATIC_RUNTIME) - set_target_properties(${PROJECT_NAME}_static PROPERTIES - MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" - ) - - if (DXFCXX_NODEFAULTLIB_LIBCMT) - target_link_options(${PROJECT_NAME}_static PRIVATE - "/NODEFAULTLIB:LIBCMT" - "/NODEFAULTLIB:LIBCMTD" - ) - endif () - endif () +if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")) + # set_target_properties(${PROJECT_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) + SetupStaticRuntimeMSVC(${PROJECT_NAME}_static ${DXFCXX_LINK_STATIC_RUNTIME} ${DXFCXX_NODEFAULTLIB}) endif () target_include_directories(${PROJECT_NAME} PUBLIC include) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index a27c4c5d..cf5924bc 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,3 +1,19 @@ +## v4.3.0 + +* Renamed `DXFCXX_NODEFAULTLIB_LIBCMT` to `DXFCXX_NODEFAULTLIB` CMake project option for clearer purposes and added support for additional libraries in `/NODEFAULTLIB` configuration. +* **\[MDAPI-254]\[C++]** Migrated to Graal SDK v2.5.0 + * Added `AGGREGATE`, `COMPOSITE`, `REGIONAL` OrderSource. The new system property `dxscheme.unitaryOrderSource=true|false` has been added. + It controls whether a single or unitary source is used when subscribing to all sources. It is set to 'false' by default. + All separate sources, such as `COMPOSITE_ASK`, `COMPOSITE_BID`, `REGIONAL_ASK`, `REGIONAL_BID`, `AGGREGATE_ASK` and `AGGREGATE_BID` have been + declared deprecated. + * Added new Order source for BlueOcean ATS: ocea. + * Added new Order sources for IG CFDs Gate: IGC, igc. + * Added new Order sources for EDX Gate: EDX, edx. + * Added new Order sources for Nuam Exchange Gate: NUAM, nuam. +* Added the ability to automatically generate the DXEndpoint name. + If the user does not explicitly specify the endpoint name, it will be generated using the template `qdcxx{Id}`, + where `{Id}` will be an empty string for the first instance of the endpoint and "-2", "-3", etc. for subsequent instances. + ## v4.2.0 * **\[MDAPI-249]\[C++]** Transitive dependencies are hidden. diff --git a/cmake/LinkAsanUbsan.cmake b/cmake/LinkAsanUbsan.cmake index 61b66649..3474ca7f 100644 --- a/cmake/LinkAsanUbsan.cmake +++ b/cmake/LinkAsanUbsan.cmake @@ -8,7 +8,7 @@ function(LinkAsan targetName) target_link_options(${targetName} PRIVATE "-fsanitize=address") else () target_compile_options(${targetName} PRIVATE "/fsanitize=address") - target_link_options(${targetName} PRIVATE "/fsanitize=address") + # target_link_options(${targetName} PRIVATE "/fsanitize=address") target_compile_definitions(${targetName} PUBLIC diff --git a/cmake/SetupStaticRuntimeMSVC.cmake b/cmake/SetupStaticRuntimeMSVC.cmake new file mode 100644 index 00000000..14b4aed8 --- /dev/null +++ b/cmake/SetupStaticRuntimeMSVC.cmake @@ -0,0 +1,20 @@ +# Copyright (c) 2025 Devexperts LLC. +# SPDX-License-Identifier: MPL-2.0 + +function(SetupStaticRuntimeMSVC targetName linkStaticRuntime noDefaultLib) + if (${linkStaticRuntime}) + set_target_properties(${targetName} PROPERTIES + MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" + ) + + if (${noDefaultLib}) + target_link_options(${targetName} PRIVATE + /NODEFAULTLIB:libcmt + /NODEFAULTLIB:libcmtd + /NODEFAULTLIB:msvcrt + /NODEFAULTLIB:msvcrtd + /VERBOSE + ) + endif () + endif () +endfunction() \ No newline at end of file diff --git a/include/dxfeed_graal_cpp_api/event/market/OrderSource.hpp b/include/dxfeed_graal_cpp_api/event/market/OrderSource.hpp index 970ed0d7..b49b583f 100644 --- a/include/dxfeed_graal_cpp_api/event/market/OrderSource.hpp +++ b/include/dxfeed_graal_cpp_api/event/market/OrderSource.hpp @@ -42,8 +42,9 @@ class DXFCPP_EXPORT OrderSource final : public IndexedEventSource { static constexpr std::uint32_t PUB_OTC_MARKETS_ORDER = 0x0004; static constexpr std::uint32_t PUB_SPREAD_ORDER = 0x0008U; static constexpr std::uint32_t FULL_ORDER_BOOK = 0x0010U; + static constexpr std::uint32_t PUB_NUAM_ORDER = 0x0020U; - static constexpr std::uint32_t FLAGS_SIZE = 5U; + static constexpr std::uint32_t FLAGS_SIZE = 6U; public: static const std::unordered_map, std::reference_wrapper> @@ -85,43 +86,87 @@ class DXFCPP_EXPORT OrderSource final : public IndexedEventSource { /** * Bid side of a composite Quote. * It is a synthetic source. + * It cannot be used with DXFeed::getIndexedEventsPromise method and it cannot be published directly to. * The subscription on composite Quote event is observed when this source is subscribed to. + * @deprecated Use the OrderSource::COMPOSITE source. */ static const OrderSource COMPOSITE_BID; /** * Ask side of a composite Quote. - * It is a synthetic source. + * It is a synthetic and separate source. + * It cannot be used with DXFeed::getIndexedEventsPromise method and it cannot be published directly to. * The subscription on composite Quote event is observed when this source is subscribed to. + * @deprecated Use the OrderSource::COMPOSITE source. */ static const OrderSource COMPOSITE_ASK; /** * Bid side of a regional Quote. - * It is a synthetic source. + * It is a synthetic and separate source. + * It cannot be used with DXFeed::getIndexedEventsPromise method and it cannot be published directly to. * The subscription on regional Quote event is observed when this source is subscribed to. + * @deprecated Use the OrderSource::REGIONAL source. */ static const OrderSource REGIONAL_BID; /** * Ask side of a regional Quote. - * It is a synthetic source. + * It is a synthetic and separate source. + * It cannot be used with DXFeed::getIndexedEventsPromise method and it cannot be published directly to. * The subscription on regional Quote event is observed when this source is subscribed to. + * @deprecated Use the OrderSource::REGIONAL source. */ static const OrderSource REGIONAL_ASK; /** * Bid side of an aggregate order book (futures depth and NASDAQ Level II). + * It is a aggregate and separate source. * This source cannot be directly published via dxFeed API, but otherwise it is fully operational. + * @deprecated Use the OrderSource::AGGREGATE source. */ static const OrderSource AGGREGATE_BID; /** * Ask side of an aggregate order book (futures depth and NASDAQ Level II). + * It is a aggregate and separate source. * This source cannot be directly published via dxFeed API, but otherwise it is fully operational. + * @deprecated Use the OrderSource::AGGREGATE source. */ static const OrderSource AGGREGATE_ASK; + /** + * Composite Quote. + * It is a synthetic and unitary source, that represents both bid and ask side. + * It cannot be used with DXFeed::getIndexedEventsPromise method and it cannot be published directly to. + * The subscription on composite Quote event is observed when this source is subscribed to. + * To use this source when subscribing to all sources (e.g., when subscribing to an order without specifying a + * source), instead of OrderSource::COMPOSITE_ASK and OrderSource::COMPOSITE_BID, set the system property + * `dxscheme.unitaryOrderSource` to `true`. + */ + static const OrderSource COMPOSITE; + + /** + * Regional Quote. + * It is a synthetic and unitary source, that represents both bid and ask side. + * It cannot be used with DXFeed::getIndexedEventsPromise method and it cannot be published directly to. + * The subscription on regional Quote event is observed when this source is subscribed to. + * To use this source when subscribing to all sources (e.g., when subscribing to an order without specifying a + * source), instead of OrderSource::REGIONAL_ASK and OrderSource::REGIONAL_BID, set the system property + * `dxscheme.unitaryOrderSource` to `true`. + */ + static const OrderSource REGIONAL; + + /** + * Aggregate order book (futures depth and NASDAQ Level II). + * It is a aggregate and unitary source, that represents both bid and ask side. + * This source cannot be directly published via dxFeed API, but otherwise it is fully operational. + * To use this source when subscribing to all sources (e.g., when subscribing to an order without specifying a + * source), instead of OrderSource::AGGREGATE_ASK and OrderSource::AGGREGATE_BID, set the system property + * `dxscheme.unitaryOrderSource` to `true`. + */ + static const OrderSource AGGREGATE; + /** * Default source for publishing custom order books. * Order, AnalyticOrder, OtcMarketsOrder and SpreadOrder events are @ref ::isPublishable() "publishable" @@ -402,6 +447,13 @@ class DXFCPP_EXPORT OrderSource final : public IndexedEventSource { */ static const OrderSource OCEA; + /** + * Blue Ocean Technologies Alternative Trading System. Record for price level book. + * Order events are @ref ::isPublishable() "publishable" on this source and the corresponding subscription can be + * observed via DXPublisher. + */ + static const OrderSource ocea; + /** * Pink Sheets. Record for price level book. * Pink sheets are listings for stocks that trade over-the-counter (OTC). @@ -443,6 +495,54 @@ class DXFCPP_EXPORT OrderSource final : public IndexedEventSource { */ static const OrderSource cedx; + /** + * IG CFDs Gate. + * + * Order events are @ref ::isPublishable() "publishable" on this source and the corresponding subscription can be + * observed via DXPublisher. + */ + static const OrderSource IGC; + + /** + * IG CFDs Gate. Record for price level book. + * + * Order events are @ref ::isPublishable() "publishable" on this source and the corresponding subscription can be + * observed via DXPublisher. + */ + static const OrderSource igc; + + /** + * EDX Exchange. + * + * Order events are @ref ::isPublishable() "publishable" on this source and the corresponding subscription can be + * observed via DXPublisher. + */ + static const OrderSource EDX; + + /** + * EDX Exchange. Record for price level book. + * + * Order events are @ref ::isPublishable() "publishable" on this source and the corresponding subscription can be + * observed via DXPublisher. + */ + static const OrderSource edx; + + /** + * Nuam Exchange Gate. + * + * Order and NuamOrder events are @ref ::isPublishable() "publishable" on this source and the corresponding + * subscription can be observed via DXPublisher. + */ + static const OrderSource NUAM; + + /** + * Nuam Exchange Gate. Record for price level book. + * + * Order and NuamOrder events are @ref ::isPublishable() "publishable" on this source and the corresponding + * subscription can be observed via DXPublisher. + */ + static const OrderSource nuam; + /** * Determines whether specified source identifier refers to special order source. * Special order sources are used for wrapping non-order events into order events. diff --git a/src/api/DXEndpoint.cpp b/src/api/DXEndpoint.cpp index 135ec37c..f4ed508c 100644 --- a/src/api/DXEndpoint.cpp +++ b/src/api/DXEndpoint.cpp @@ -125,16 +125,9 @@ std::shared_ptr DXEndpoint::create(void *endpointHandle, DXEndpoint: ", role = " + roleToString(role) + ", properties[" + std::to_string(properties.size()) + "])"); } - auto name = properties.contains(NAME_PROPERTY) ? properties.at(NAME_PROPERTY) : std::string{}; - - if (name.empty()) { - std::size_t id = ApiContext::getInstance()->getManager>()->getLastId(); - - name = fmt::format("qdcxx{}", (id <= 1) ? "" : fmt::format("-{}", id)); - } - - auto endpoint = DXEndpoint::createShared(JavaObjectHandle(endpointHandle), role, name); - auto id = ApiContext::getInstance()->getManager>()->registerEntity(endpoint); + auto endpoint = + DXEndpoint::createShared(JavaObjectHandle(endpointHandle), role, properties.at(NAME_PROPERTY)); + const auto id = ApiContext::getInstance()->getManager>()->registerEntity(endpoint); endpoint->stateChangeListenerHandle_ = isolated::api::IsolatedDXEndpoint::StateChangeListener::create( dxfcpp::bit_cast(&Impl::onPropertyChange), dxfcpp::bit_cast(id.getValue())); @@ -336,6 +329,16 @@ std::shared_ptr DXEndpoint::Builder::build() { loadDefaultPropertiesImpl(); + if (auto name = properties_.contains(NAME_PROPERTY) ? properties_.at(NAME_PROPERTY) : std::string{}; name.empty()) { + std::size_t id = ApiContext::getInstance()->getManager>()->getLastId(); + + name = fmt::format("qdcxx{}", (id <= 1) ? "" : fmt::format("-{}", id)); + + const auto newBuilder = withProperty(NAME_PROPERTY, name); + + return newBuilder->build(); + } + return DXEndpoint::create(isolated::api::IsolatedDXEndpoint::Builder::build(handle_), role_, properties_); } diff --git a/src/event/market/OrderSource.cpp b/src/event/market/OrderSource.cpp index 386941cb..83c80bbe 100644 --- a/src/event/market/OrderSource.cpp +++ b/src/event/market/OrderSource.cpp @@ -14,9 +14,12 @@ const OrderSource OrderSource::REGIONAL_BID(3, "REGIONAL_BID", 0); const OrderSource OrderSource::REGIONAL_ASK(4, "REGIONAL_ASK", 0); const OrderSource OrderSource::AGGREGATE_BID(5, "AGGREGATE_BID", 0); const OrderSource OrderSource::AGGREGATE_ASK(6, "AGGREGATE_ASK", 0); +const OrderSource OrderSource::COMPOSITE(7, "COMPOSITE", 0); +const OrderSource OrderSource::REGIONAL(8, "REGIONAL", 0); +const OrderSource OrderSource::AGGREGATE(9, "AGGREGATE", 0); const OrderSource OrderSource::DEFAULT(0, "DEFAULT", PUB_ORDER | PUB_ANALYTIC_ORDER | PUB_OTC_MARKETS_ORDER | PUB_SPREAD_ORDER | - FULL_ORDER_BOOK); + FULL_ORDER_BOOK | PUB_NUAM_ORDER); const OrderSource OrderSource::NTV("NTV", PUB_ORDER | FULL_ORDER_BOOK); const OrderSource OrderSource::ntv("ntv", PUB_ORDER); @@ -52,11 +55,18 @@ const OrderSource OrderSource::iex("iex", PUB_ORDER); const OrderSource OrderSource::MEMX("MEMX", PUB_ORDER); const OrderSource OrderSource::memx("memx", PUB_ORDER); const OrderSource OrderSource::OCEA("OCEA", PUB_ORDER); +const OrderSource OrderSource::ocea("ocea", PUB_ORDER); const OrderSource OrderSource::pink("pink", PUB_ORDER | PUB_OTC_MARKETS_ORDER); const OrderSource OrderSource::ARCA("ARCA", PUB_ORDER); const OrderSource OrderSource::arca("arca", PUB_ORDER); const OrderSource OrderSource::CEDX("CEDX", PUB_ORDER); const OrderSource OrderSource::cedx("cedx", PUB_ORDER); +const OrderSource OrderSource::IGC("IGC", PUB_ORDER); +const OrderSource OrderSource::igc("igc", PUB_ORDER); +const OrderSource OrderSource::EDX("EDX", PUB_ORDER); +const OrderSource OrderSource::edx("edx", PUB_ORDER); +const OrderSource OrderSource::NUAM("NUAM", PUB_ORDER | FULL_ORDER_BOOK | PUB_NUAM_ORDER); +const OrderSource OrderSource::nuam("nuam", PUB_ORDER | PUB_NUAM_ORDER); const std::unordered_map, std::reference_wrapper> OrderSource::PREDEFINED_SOURCES = @@ -71,13 +81,14 @@ const std::unordered_map, std::reference return result; }({// - COMPOSITE_BID, COMPOSITE_ASK, REGIONAL_BID, REGIONAL_ASK, AGGREGATE_BID, AGGREGATE_ASK, + COMPOSITE_BID, COMPOSITE_ASK, REGIONAL_BID, REGIONAL_ASK, AGGREGATE_BID, AGGREGATE_ASK, COMPOSITE, REGIONAL, + AGGREGATE, // DEFAULT, // NTV, ntv, NFX, ESPD, XNFI, ICE, ISE, DEA, DEX, dex, BYX, BZX, bzx, BATE, CHIX, CEUX, BXTR, IST, BI20, ABE, - FAIR, GLBX, glbx, ERIS, XEUR, xeur, CFE, C2OX, SMFE, smfe, iex, MEMX, memx, OCEA, pink, ARCA, arca, CEDX, - cedx}); + FAIR, GLBX, glbx, ERIS, XEUR, xeur, CFE, C2OX, SMFE, smfe, iex, MEMX, memx, OCEA, ocea, pink, ARCA, arca, + CEDX, cedx, IGC, igc, EDX, edx, NUAM, nuam}); std::unordered_map OrderSource::USER_SOURCES_{}; @@ -158,6 +169,11 @@ std::uint32_t OrderSource::getEventTypeMask(const EventTypeEnum &eventType) { return PUB_SPREAD_ORDER; } + // TODO: MDAPI-243, MDAPI-256 + // if (eventType == EventTypeEnum::NUAM_ORDER) { + // return PUB_NUAM_ORDER; + // } + throw InvalidArgumentException("Invalid order event type: " + eventType.getName()); } @@ -172,7 +188,7 @@ std::unique_ptr OrderSource::toG } bool OrderSource::isSpecialSourceId(std::int32_t sourceId) noexcept { - return sourceId >= COMPOSITE_BID.id() && sourceId <= AGGREGATE_ASK.id(); + return sourceId >= COMPOSITE_BID.id() && sourceId <= AGGREGATE.id(); } const OrderSource &OrderSource::valueOf(std::int32_t sourceId) {