From c0e30492298d1ca6f24159a238dac74fcefac945 Mon Sep 17 00:00:00 2001 From: Leon H <140434610+LeonHosch@users.noreply.github.com> Date: Tue, 30 Apr 2024 10:35:27 +0200 Subject: [PATCH 1/4] [Python] Added BinarySubscriber and BinaryPublisher with examples (#1526) Co-authored-by: Leon Hosch --- lang/python/core/ecal/core/publisher.py | 12 +++++ lang/python/core/ecal/core/subscriber.py | 45 ++++++++++++++++ samples/CMakeLists.txt | 3 ++ .../pubsub/binary/binary_rec/CMakeLists.txt | 32 +++++++++++ .../pubsub/binary/binary_rec/binary_rec.py | 49 +++++++++++++++++ .../binary/binary_rec/binary_rec.pyproj | 35 ++++++++++++ .../binary/binary_rec_cb/CMakeLists.txt | 32 +++++++++++ .../binary/binary_rec_cb/binary_rec_cb.py | 52 ++++++++++++++++++ .../binary/binary_rec_cb/binary_rec_cb.pyproj | 35 ++++++++++++ .../pubsub/binary/binary_snd/CMakeLists.txt | 32 +++++++++++ .../pubsub/binary/binary_snd/binary_snd.py | 54 +++++++++++++++++++ .../binary/binary_snd/binary_snd.pyproj | 35 ++++++++++++ 12 files changed, 416 insertions(+) create mode 100644 samples/python/pubsub/binary/binary_rec/CMakeLists.txt create mode 100644 samples/python/pubsub/binary/binary_rec/binary_rec.py create mode 100644 samples/python/pubsub/binary/binary_rec/binary_rec.pyproj create mode 100644 samples/python/pubsub/binary/binary_rec_cb/CMakeLists.txt create mode 100644 samples/python/pubsub/binary/binary_rec_cb/binary_rec_cb.py create mode 100644 samples/python/pubsub/binary/binary_rec_cb/binary_rec_cb.pyproj create mode 100644 samples/python/pubsub/binary/binary_snd/CMakeLists.txt create mode 100644 samples/python/pubsub/binary/binary_snd/binary_snd.py create mode 100644 samples/python/pubsub/binary/binary_snd/binary_snd.pyproj diff --git a/lang/python/core/ecal/core/publisher.py b/lang/python/core/ecal/core/publisher.py index 8f341dfaa8..3e870080a4 100644 --- a/lang/python/core/ecal/core/publisher.py +++ b/lang/python/core/ecal/core/publisher.py @@ -65,6 +65,18 @@ def __init__(self, name, type_=None): def send(self, msg, time=-1): return self.c_publisher.send(msg.SerializeToString(), time) +class BinaryPublisher(MessagePublisher): + """Spezialized publisher that sends out binary messages + """ + def __init__(self, name): + topic_type = "binary" + topic_enc = "base" + topic_desc = b"" + super(BinaryPublisher, self).__init__(name, topic_type, topic_enc, topic_desc) + + def send(self, msg, time=-1): + return self.c_publisher.send(msg, time) + class StringPublisher(MessagePublisher): """Spezialized publisher that sends out plain strings """ diff --git a/lang/python/core/ecal/core/subscriber.py b/lang/python/core/ecal/core/subscriber.py index f6ca858f02..4011a2a82c 100644 --- a/lang/python/core/ecal/core/subscriber.py +++ b/lang/python/core/ecal/core/subscriber.py @@ -117,6 +117,51 @@ def _on_receive(self, topic_name, msg, time): self.callback(topic_name, proto_message, time) +class BinarySubscriber(MessageSubscriber): + """Specialized subscriber that subscribes to binary messages + """ + def __init__(self, name): + topic_type = "binary" + topic_enc = "base" + topic_desc = b"" + super(BinarySubscriber, self).__init__(name, topic_type, topic_enc, topic_desc) + self.callback = None + + def receive(self, timeout=0): + """ receive subscriber content with timeout + + :param timeout: receive timeout in ms + + """ + ret, msg, time = self.c_subscriber.receive(timeout) + if ret > 0: + msg = msg + else: + msg = b"" + return ret, msg, time + + def set_callback(self, callback): + """ set callback function for incoming messages + + :param callback: python callback function (f(topic_name, msg, time)) + + """ + self.callback = callback + self.c_subscriber.set_callback(self._on_receive) + + def rem_callback(self, callback): + """ remove callback function for incoming messages + + :param callback: python callback function (f(topic_name, msg, time)) + + """ + self.c_subscriber.rem_callback(self._on_receive) + self.callback = None + + def _on_receive(self, topic_name, msg, time): + self.callback(topic_name, msg, time) + + class StringSubscriber(MessageSubscriber): """Spezialized publisher subscribes to plain strings """ diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index dca119e633..22f0b515e8 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -73,6 +73,9 @@ if(BUILD_PY_BINDING) add_subdirectory(python/pubsub/string/minimal_rec) add_subdirectory(python/pubsub/string/minimal_rec_cb) add_subdirectory(python/pubsub/string/minimal_snd) + add_subdirectory(python/pubsub/binary/binary_rec) + add_subdirectory(python/pubsub/binary/binary_rec_cb) + add_subdirectory(python/pubsub/binary/binary_snd) # services add_subdirectory(python/services/minimal_service) diff --git a/samples/python/pubsub/binary/binary_rec/CMakeLists.txt b/samples/python/pubsub/binary/binary_rec/CMakeLists.txt new file mode 100644 index 0000000000..181e6cbaa3 --- /dev/null +++ b/samples/python/pubsub/binary/binary_rec/CMakeLists.txt @@ -0,0 +1,32 @@ +# ========================= eCAL LICENSE ================================= +# +# Copyright (C) 2016 - 2019 Continental Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ========================= eCAL LICENSE ================================= + +project(binary_rec) + +find_package(eCAL REQUIRED) + +set(PROJECT_GROUP binary) + +if(ECAL_INCLUDE_PY_SAMPLES) + if(WIN32) + + include_external_msproject(${PROJECT_NAME}_py ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pyproj) + set_property(TARGET ${PROJECT_NAME}_py PROPERTY FOLDER samples/python/${PROJECT_GROUP}) + + endif() +endif() \ No newline at end of file diff --git a/samples/python/pubsub/binary/binary_rec/binary_rec.py b/samples/python/pubsub/binary/binary_rec/binary_rec.py new file mode 100644 index 0000000000..8e2041b0b9 --- /dev/null +++ b/samples/python/pubsub/binary/binary_rec/binary_rec.py @@ -0,0 +1,49 @@ + # ========================= eCAL LICENSE ================================= +# +# Copyright (C) 2016 - 2019 Continental Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ========================= eCAL LICENSE ================================= + +import sys + +import ecal.core.core as ecal_core +from ecal.core.subscriber import BinarySubscriber + +def main(): + # print eCAL version and date + print("eCAL {} ({})\n".format(ecal_core.getversion(), ecal_core.getdate())) + + # initialize eCAL API + ecal_core.initialize(sys.argv, "py_binary_rec") + + # set process state + ecal_core.set_process_state(1, 1, "I feel good") + + # create subscriber + sub = BinarySubscriber("Hello") + + # receive messages + while ecal_core.ok(): + ret, msg, time = sub.receive(500) + if ret > 0: + print("Received: {} ms {}".format(time, bytes.fromhex(msg.decode("utf-8")))) + else: + print("Subscriber timeout ..") + + # finalize eCAL API + ecal_core.finalize() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/samples/python/pubsub/binary/binary_rec/binary_rec.pyproj b/samples/python/pubsub/binary/binary_rec/binary_rec.pyproj new file mode 100644 index 0000000000..31855265cf --- /dev/null +++ b/samples/python/pubsub/binary/binary_rec/binary_rec.pyproj @@ -0,0 +1,35 @@ + + + + Debug + 2.0 + . + binary_rec.py + ..\..\..\lang\python\src + . + . + binary_rec + binary_rec + {093990a3-9395-3bb2-b625-473f1bba2ce6} + + + true + false + + + true + false + + + + + + 10.0 + + + + + + + + \ No newline at end of file diff --git a/samples/python/pubsub/binary/binary_rec_cb/CMakeLists.txt b/samples/python/pubsub/binary/binary_rec_cb/CMakeLists.txt new file mode 100644 index 0000000000..2887d4a544 --- /dev/null +++ b/samples/python/pubsub/binary/binary_rec_cb/CMakeLists.txt @@ -0,0 +1,32 @@ +# ========================= eCAL LICENSE ================================= +# +# Copyright (C) 2016 - 2019 Continental Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ========================= eCAL LICENSE ================================= + +project(binary_rec_cb) + +find_package(eCAL REQUIRED) + +set(PROJECT_GROUP binary) + +if(ECAL_INCLUDE_PY_SAMPLES) + if(WIN32) + + include_external_msproject(${PROJECT_NAME}_py ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pyproj) + set_property(TARGET ${PROJECT_NAME}_py PROPERTY FOLDER samples/python/${PROJECT_GROUP}) + + endif() +endif() diff --git a/samples/python/pubsub/binary/binary_rec_cb/binary_rec_cb.py b/samples/python/pubsub/binary/binary_rec_cb/binary_rec_cb.py new file mode 100644 index 0000000000..546c8cc1c2 --- /dev/null +++ b/samples/python/pubsub/binary/binary_rec_cb/binary_rec_cb.py @@ -0,0 +1,52 @@ +# ========================= eCAL LICENSE ================================= +# +# Copyright (C) 2016 - 2019 Continental Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ========================= eCAL LICENSE ================================= + +import sys +import time + +import ecal.core.core as ecal_core +from ecal.core.subscriber import BinarySubscriber + +# eCAL receive callback +def callback(topic_name, msg, time): + print("Received: {} ms {}".format(time, bytes.fromhex(msg.decode("utf-8")))) + +def main(): + # print eCAL version and date + print("eCAL {} ({})\n".format(ecal_core.getversion(), ecal_core.getdate())) + + # initialize eCAL API + ecal_core.initialize(sys.argv, "py_binary_rec_cb") + + # set process state + ecal_core.set_process_state(1, 1, "I feel good") + + # create subscriber and connect callback + sub = BinarySubscriber("Hello") + sub.set_callback(callback) + + # idle main thread + while ecal_core.ok(): + time.sleep(0.1) + + # finalize eCAL API + ecal_core.finalize() + +if __name__ == "__main__": + main() + diff --git a/samples/python/pubsub/binary/binary_rec_cb/binary_rec_cb.pyproj b/samples/python/pubsub/binary/binary_rec_cb/binary_rec_cb.pyproj new file mode 100644 index 0000000000..5478851607 --- /dev/null +++ b/samples/python/pubsub/binary/binary_rec_cb/binary_rec_cb.pyproj @@ -0,0 +1,35 @@ + + + + Debug + 2.0 + . + binary_rec_cb.py + ..\..\..\lang\python\src + . + . + binary_rec_cb + binary_rec_cb + {a38cc1fc-76f7-3172-81ac-b754dc0f9d60} + + + true + false + + + true + false + + + + + + 10.0 + + + + + + + + \ No newline at end of file diff --git a/samples/python/pubsub/binary/binary_snd/CMakeLists.txt b/samples/python/pubsub/binary/binary_snd/CMakeLists.txt new file mode 100644 index 0000000000..bdc0dec522 --- /dev/null +++ b/samples/python/pubsub/binary/binary_snd/CMakeLists.txt @@ -0,0 +1,32 @@ +# ========================= eCAL LICENSE ================================= +# +# Copyright (C) 2016 - 2019 Continental Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ========================= eCAL LICENSE ================================= + +project(binary_snd) + +find_package(eCAL REQUIRED) + +set(PROJECT_GROUP binary) + +if(ECAL_INCLUDE_PY_SAMPLES) + if(WIN32) + + include_external_msproject(${PROJECT_NAME}_py ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pyproj) + set_property(TARGET ${PROJECT_NAME}_py PROPERTY FOLDER samples/python/${PROJECT_GROUP}) + + endif() +endif() \ No newline at end of file diff --git a/samples/python/pubsub/binary/binary_snd/binary_snd.py b/samples/python/pubsub/binary/binary_snd/binary_snd.py new file mode 100644 index 0000000000..914765d488 --- /dev/null +++ b/samples/python/pubsub/binary/binary_snd/binary_snd.py @@ -0,0 +1,54 @@ +# ========================= eCAL LICENSE ================================= +# +# Copyright (C) 2016 - 2019 Continental Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ========================= eCAL LICENSE ================================= + +import sys +import time +import random + +import ecal.core.core as ecal_core +from ecal.core.publisher import BinaryPublisher + +def main(): + # print eCAL version and date + print("eCAL {} ({})\n".format(ecal_core.getversion(), ecal_core.getdate())) + + # initialize eCAL API + ecal_core.initialize(sys.argv, "py_binary_snd") + + # set process state + ecal_core.set_process_state(1, 1, "I feel good") + + # create publisher + pub = BinaryPublisher("Hello") + msg_fox = b"4120717569636b2062726f776e20666f7820" + + # send messages + msg_count = 0 + while ecal_core.ok(): + msg_count += 1 + hex_ascii = bytes(''.join([hex(ord(digit))[2:] for digit in str(msg_count)]), "utf-8") + msg = msg_fox + hex_ascii + pub.send(msg) + print("Sent: ", msg) + time.sleep(0.01) + + # finalize eCAL API + ecal_core.finalize() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/samples/python/pubsub/binary/binary_snd/binary_snd.pyproj b/samples/python/pubsub/binary/binary_snd/binary_snd.pyproj new file mode 100644 index 0000000000..c7223cb68c --- /dev/null +++ b/samples/python/pubsub/binary/binary_snd/binary_snd.pyproj @@ -0,0 +1,35 @@ + + + + Debug + 2.0 + . + binary_snd.py + ..\..\..\lang\python\src + . + . + binary_snd + binary_snd + {5ebed1e0-8867-3120-bbfe-6d6db73e8077} + + + true + false + + + true + false + + + + + + 10.0 + + + + + + + + \ No newline at end of file From a65a831e487636bfe5131a685bea3cc6ca52cc7d Mon Sep 17 00:00:00 2001 From: Florian Reimold <11774314+FlorianReimold@users.noreply.github.com> Date: Fri, 3 May 2024 08:30:39 +0200 Subject: [PATCH 2/4] [Core / Service]: Fixed crash that occured when communicating with eCAL 5.12 services (#1579) The crash occured when a v0 client connected to a service server. --- .../src/server_session_impl_v0.cpp | 12 ++ .../ecal_service/src/server_session_impl_v0.h | 5 + .../test/src/ecal_tcp_service_test.cpp | 145 ++++++++++++++++++ 3 files changed, 162 insertions(+) diff --git a/ecal/service/ecal_service/src/server_session_impl_v0.cpp b/ecal/service/ecal_service/src/server_session_impl_v0.cpp index bb984839e0..d06dfe050c 100644 --- a/ecal/service/ecal_service/src/server_session_impl_v0.cpp +++ b/ecal/service/ecal_service/src/server_session_impl_v0.cpp @@ -74,6 +74,18 @@ namespace eCAL // Data receiving and sending /////////////////////////////////////////////// void ServerSessionV0::start() + { + // Call the handle_start with the io_service + // It is important to async call handle_start(), as it will call a + // user-defined callback. As we have no influence what that callback will + // be, we must call it from another thread to make sure to not double-lock + // mutexes from the server_impl, if the callback should itself call a + // server_impl api function. + + io_context_->post([me = shared_from_this()]() { me->handle_start(); }); + } + + void ServerSessionV0::handle_start() { // Go to handshake state state_ = State::CONNECTED; diff --git a/ecal/service/ecal_service/src/server_session_impl_v0.h b/ecal/service/ecal_service/src/server_session_impl_v0.h index cffeda48a0..4c4f93dbe8 100644 --- a/ecal/service/ecal_service/src/server_session_impl_v0.h +++ b/ecal/service/ecal_service/src/server_session_impl_v0.h @@ -75,6 +75,11 @@ namespace eCAL /////////////////////////////////////////////// public: void start() override; + + private: + void handle_start(); + + public: void stop() override; eCAL::service::State get_state() const override; diff --git a/ecal/service/test/src/ecal_tcp_service_test.cpp b/ecal/service/test/src/ecal_tcp_service_test.cpp index 0683ed708c..67455b54d4 100644 --- a/ecal/service/test/src/ecal_tcp_service_test.cpp +++ b/ecal/service/test/src/ecal_tcp_service_test.cpp @@ -1605,6 +1605,151 @@ TEST(ecal_service, Callback_SerializedServiceCallbacks) // NOLINT } #endif +#if 1 +// Call different eCAL Service API functions from within the callbacks +TEST(ecal_service, Callback_ApiCallsFromCallbacks) +{ + for (std::uint8_t protocol_version = min_protocol_version; protocol_version <= max_protocol_version; protocol_version++) + { + const auto io_context = std::make_shared(); + const asio::io_context::work dummy_work(*io_context); + + atomic_signalable num_server_service_callback_called (0); + atomic_signalable num_server_event_callback_called (0); + atomic_signalable num_client_response_callback_called(0); + atomic_signalable num_client_event_callback_called (0); + + // declare server and client shared_ptrs as we need those in the callbacks. + std::shared_ptr server; + std::shared_ptr client; + + const eCAL::service::Server::ServiceCallbackT server_service_callback + = [&num_server_service_callback_called, &server](const std::shared_ptr& /*request*/, const std::shared_ptr& /*response*/) -> void + { + if (server) + { + bool is_connected = server->is_connected(); + int connection_count = server->get_connection_count(); + uint16_t port = server->get_port(); + + EXPECT_EQ(is_connected, true); + EXPECT_EQ(connection_count, 1); + } + + num_server_service_callback_called++; + }; + + const eCAL::service::Server::EventCallbackT server_event_callback + = [&num_server_event_callback_called, &server](eCAL::service::ServerEventType event, const std::string& /*message*/) -> void + { + if (server) + { + bool is_connected = server->is_connected(); + int connection_count = server->get_connection_count(); + uint16_t port = server->get_port(); + + if (event == eCAL::service::ServerEventType::Connected) + { + ASSERT_EQ(is_connected, true); + ASSERT_EQ(connection_count, 1); + } + else if (event == eCAL::service::ServerEventType::Disconnected) + { + ASSERT_EQ(is_connected, false); + ASSERT_EQ(connection_count, 0); + } + } + + num_server_event_callback_called++; + }; + + const eCAL::service::ClientSession::ResponseCallbackT client_response_callback + = [&num_client_response_callback_called, &client] + (const eCAL::service::Error& error, const std::shared_ptr& /*response*/) -> void + { + if(client) + { + // We just test if those functions can be called without crashing + auto address = client->get_address(); + auto port = client->get_port(); + auto protocol_version = client->get_accepted_protocol_version(); + auto queue_size = client->get_queue_size(); + auto state = client->get_state(); + } + + num_client_response_callback_called++; + }; + + const eCAL::service::ClientSession::EventCallbackT client_event_callback + = [&num_client_event_callback_called, &client] + (eCAL::service::ClientEventType event, const std::string& /*message*/) -> void + { + if (client) + { + // We just test if those functions can be called without crashing + auto address = client->get_address(); + auto port = client->get_port(); + auto protocol_version = client->get_accepted_protocol_version(); + auto queue_size = client->get_queue_size(); + auto state = client->get_state(); + } + + num_client_event_callback_called++; + }; + + server = eCAL::service::Server::create(io_context, protocol_version, 0, server_service_callback, true, server_event_callback); + + EXPECT_EQ(num_server_service_callback_called.get(), 0); + EXPECT_EQ(num_server_event_callback_called.get(), 0); + EXPECT_EQ(num_client_response_callback_called.get(), 0); + EXPECT_EQ(num_client_event_callback_called.get(), 0); + + client = eCAL::service::ClientSession::create(io_context, protocol_version, "127.0.0.1", server->get_port(), client_event_callback); + + std::thread io_thread([&io_context]() + { + io_context->run(); + }); + + // Wait for the connected events to be called + num_server_event_callback_called.wait_for([](int value) { return value >= 1; }, std::chrono::milliseconds(500)); + num_client_event_callback_called.wait_for([](int value) { return value >= 1; }, std::chrono::milliseconds(500)); + + EXPECT_EQ(num_server_service_callback_called.get(), 0); + EXPECT_EQ(num_server_event_callback_called.get(), 1); + EXPECT_EQ(num_client_response_callback_called.get(), 0); + EXPECT_EQ(num_client_event_callback_called.get(), 1); + + // Call service and wait for the response + client->async_call_service(std::make_shared("1"), client_response_callback); + + num_server_service_callback_called .wait_for([](int value) { return value >= 1; }, std::chrono::milliseconds(500)); + num_client_response_callback_called.wait_for([](int value) { return value >= 1; }, std::chrono::milliseconds(500)); + + EXPECT_EQ(num_server_service_callback_called.get(), 1); + EXPECT_EQ(num_server_event_callback_called.get(), 1); + EXPECT_EQ(num_client_response_callback_called.get(), 1); + EXPECT_EQ(num_client_event_callback_called.get(), 1); + + // Terminate the client + client = nullptr; + + // Wait for the disconnected events to be called + num_server_event_callback_called.wait_for([](int value) { return value >= 2; }, std::chrono::milliseconds(500)); + + EXPECT_EQ(num_server_service_callback_called.get(), 1); + EXPECT_EQ(num_server_event_callback_called.get(), 2); + + // Terminate the server + server = nullptr; + + // join the io_thread + io_context->stop(); + io_thread.join(); + } +} +#endif + #if 1 TEST(ecal_service, ErrorCallback_ErrorCallbackNoServer) // NOLINT { From 6a4bf8b3fcd759b7287ba1df22ac6f9c13c32716 Mon Sep 17 00:00:00 2001 From: KerstinKeller Date: Tue, 7 May 2024 09:21:08 +0200 Subject: [PATCH 3/4] [build] reactivate capnproto and flatbuffers sapmles (#1585) --- samples/CMakeLists.txt | 12 ++++++++++++ .../cpp/pubsub/capnp/addressbook_rec/CMakeLists.txt | 2 +- .../pubsub/capnp/addressbook_rec_cb/CMakeLists.txt | 2 +- .../capnp/addressbook_rec_dynamic/CMakeLists.txt | 2 +- .../cpp/pubsub/capnp/addressbook_snd/CMakeLists.txt | 2 +- .../cpp/pubsub/flatbuffer/monster_rec/CMakeLists.txt | 2 +- .../cpp/pubsub/flatbuffer/monster_snd/CMakeLists.txt | 2 +- 7 files changed, 18 insertions(+), 6 deletions(-) diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 22f0b515e8..ad8b6312be 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -33,6 +33,18 @@ add_subdirectory(cpp/measurement/measurement_read) add_subdirectory(cpp/measurement/measurement_write) endif(HAS_HDF5) +if (HAS_CAPNPROTO) +add_subdirectory(cpp/pubsub/capnp/addressbook_rec) +add_subdirectory(cpp/pubsub/capnp/addressbook_rec_cb) +add_subdirectory(cpp/pubsub/capnp/addressbook_rec_dynamic) +add_subdirectory(cpp/pubsub/capnp/addressbook_snd) +endif(HAS_CAPNPROTO) + +if (HAS_FLATBUFFERS) +add_subdirectory(cpp/pubsub/flatbuffer/monster_rec) +add_subdirectory(cpp/pubsub/flatbuffer/monster_snd) +endif(HAS_FLATBUFFERS) + # services add_subdirectory(cpp/services/ecalplayer_client) if(HAS_QT) diff --git a/samples/cpp/pubsub/capnp/addressbook_rec/CMakeLists.txt b/samples/cpp/pubsub/capnp/addressbook_rec/CMakeLists.txt index bc91ac896c..28cf9e8dfd 100644 --- a/samples/cpp/pubsub/capnp/addressbook_rec/CMakeLists.txt +++ b/samples/cpp/pubsub/capnp/addressbook_rec/CMakeLists.txt @@ -38,4 +38,4 @@ target_link_options(${PROJECT_NAME} PRIVATE $<$:/ignore:40 ecal_install_sample(${PROJECT_NAME}) -set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER samples/cpp/pubsub/capnp/addressbook) +set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER samples/cpp/pubsub/capnproto) diff --git a/samples/cpp/pubsub/capnp/addressbook_rec_cb/CMakeLists.txt b/samples/cpp/pubsub/capnp/addressbook_rec_cb/CMakeLists.txt index 8b6ec95a6f..7719484ef9 100644 --- a/samples/cpp/pubsub/capnp/addressbook_rec_cb/CMakeLists.txt +++ b/samples/cpp/pubsub/capnp/addressbook_rec_cb/CMakeLists.txt @@ -38,4 +38,4 @@ target_link_options(${PROJECT_NAME} PRIVATE $<$:/ignore:40 ecal_install_sample(${PROJECT_NAME}) -set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER samples/cpp/pubsub/capnp/addressbook) \ No newline at end of file +set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER samples/cpp/pubsub/capnproto) \ No newline at end of file diff --git a/samples/cpp/pubsub/capnp/addressbook_rec_dynamic/CMakeLists.txt b/samples/cpp/pubsub/capnp/addressbook_rec_dynamic/CMakeLists.txt index 0af1ddd0e7..cdb1817eeb 100644 --- a/samples/cpp/pubsub/capnp/addressbook_rec_dynamic/CMakeLists.txt +++ b/samples/cpp/pubsub/capnp/addressbook_rec_dynamic/CMakeLists.txt @@ -34,4 +34,4 @@ target_link_options(${PROJECT_NAME} PRIVATE $<$:/ignore:40 ecal_install_sample(${PROJECT_NAME}) -set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER samples/cpp/pubsub/capnp/addressbook) +set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER samples/cpp/pubsub/capnproto) diff --git a/samples/cpp/pubsub/capnp/addressbook_snd/CMakeLists.txt b/samples/cpp/pubsub/capnp/addressbook_snd/CMakeLists.txt index af7f523293..89a7571036 100644 --- a/samples/cpp/pubsub/capnp/addressbook_snd/CMakeLists.txt +++ b/samples/cpp/pubsub/capnp/addressbook_snd/CMakeLists.txt @@ -38,4 +38,4 @@ target_link_options(${PROJECT_NAME} PRIVATE $<$:/ignore:40 ecal_install_sample(${PROJECT_NAME}) -set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER samples/cpp/pubsub/capnp/addressbook) +set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER samples/cpp/pubsub/capnproto) diff --git a/samples/cpp/pubsub/flatbuffer/monster_rec/CMakeLists.txt b/samples/cpp/pubsub/flatbuffer/monster_rec/CMakeLists.txt index 1501355991..65f7e5d1f5 100644 --- a/samples/cpp/pubsub/flatbuffer/monster_rec/CMakeLists.txt +++ b/samples/cpp/pubsub/flatbuffer/monster_rec/CMakeLists.txt @@ -45,4 +45,4 @@ target_link_libraries(${PROJECT_NAME} ecal_install_sample(${PROJECT_NAME}) -set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER samples/cpp/monster) \ No newline at end of file +set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER samples/cpp/pubsub/flatbuffers) \ No newline at end of file diff --git a/samples/cpp/pubsub/flatbuffer/monster_snd/CMakeLists.txt b/samples/cpp/pubsub/flatbuffer/monster_snd/CMakeLists.txt index 8e61aec451..cde6831471 100644 --- a/samples/cpp/pubsub/flatbuffer/monster_snd/CMakeLists.txt +++ b/samples/cpp/pubsub/flatbuffer/monster_snd/CMakeLists.txt @@ -45,4 +45,4 @@ target_link_libraries(${PROJECT_NAME} ecal_install_sample(${PROJECT_NAME}) -set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER samples/cpp/monster) \ No newline at end of file +set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER samples/cpp/pubsub/flatbuffers) \ No newline at end of file From e78be4116873cf0a405c9ea88db46d0eab980822 Mon Sep 17 00:00:00 2001 From: DownerCase <119755054+DownerCase@users.noreply.github.com> Date: Tue, 7 May 2024 09:37:07 +0100 Subject: [PATCH 4/4] [python] Scikit-build-core driven wheel creation (#1454) --- .github/workflows/build-macos.yml | 10 -- .github/workflows/build-ubuntu-20.yml | 38 ------ .github/workflows/build-ubuntu-22.yml | 39 ------ .github/workflows/build-windows.yml | 85 +------------ .github/workflows/build_wheels.yml | 63 ++++++++++ .gitignore | 6 + CMakeLists.txt | 19 ++- CMakePresets.json | 23 ++-- app/app_pb/CMakeLists.txt | 6 - .../ecal_python_functions.cmake | 112 ----------------- contrib/ecaltime/ecaltime_pb/CMakeLists.txt | 6 - ecal/core_pb/CMakeLists.txt | 6 - lang/python/CMakeLists.txt | 68 ++++------- lang/python/core/CMakeLists.txt | 52 +++----- lang/python/ecalhdf5/CMakeLists.txt | 59 +++------ lang/python/setup.py.in | 48 -------- pyproject.toml | 115 ++++++++++++++++++ 17 files changed, 269 insertions(+), 486 deletions(-) create mode 100644 .github/workflows/build_wheels.yml delete mode 100644 cmake/helper_functions/ecal_python_functions.cmake delete mode 100644 lang/python/setup.py.in create mode 100644 pyproject.toml diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml index 710c093ab4..01692e5d74 100644 --- a/.github/workflows/build-macos.yml +++ b/.github/workflows/build-macos.yml @@ -99,10 +99,6 @@ jobs: run: cmake --build . --config Release working-directory: ${{ runner.workspace }}/_build - - name: Build Python Wheel - run: cmake --build . --target create_python_wheel --config Release - working-directory: ${{ runner.workspace }}/_build - # - name: Build Documentation C # run: cmake --build . --target documentation_c # working-directory: ${{ runner.workspace }}/_build @@ -125,9 +121,3 @@ jobs: with: name: macos-dmg path: ${{ runner.workspace }}/_build/_deploy/*.dmg - - - name: Upload Python Wheel - uses: actions/upload-artifact@v4 - with: - name: macos-python-wheel - path: ${{ runner.workspace }}/_build/_deploy/*.whl diff --git a/.github/workflows/build-ubuntu-20.yml b/.github/workflows/build-ubuntu-20.yml index 06093aa992..cfce3aec05 100644 --- a/.github/workflows/build-ubuntu-20.yml +++ b/.github/workflows/build-ubuntu-20.yml @@ -104,39 +104,6 @@ jobs: run: cmake --build . --config Release -- -k 0 working-directory: ${{ runner.workspace }}/_build - # Create Python Wheels - # The strang-looking double-cmake is an ugly workaround to force CMake to - # re-find Python, after we have changed the venv from the outside. The - # alternative would be to clean everything, which would cause an unnecessary - # rebuild of eCAL for each python Version. - - name: Build Python 3.9 Wheel - run: | - sudo apt-get -y install python3.9-dev python3.9-venv - mkdir ".venv_39" - python3.9 -m venv ".venv_39" - source ".venv_39/bin/activate" - pip install --upgrade pip - pip install wheel setuptools - cmake $GITHUB_WORKSPACE -DPython_FIND_VIRTUALENV=FIRST - cmake $GITHUB_WORKSPACE -DPython_FIND_VIRTUALENV=ONLY - cmake --build . --target create_python_wheel --config Release - shell: bash - working-directory: ${{ runner.workspace }}/_build - - - name: Build Python 3.8 Wheel - run: | - sudo apt-get -y install python3.8-dev python3.8-venv - mkdir ".venv_38" - python3.8 -m venv ".venv_38" - source ".venv_38/bin/activate" - pip install --upgrade pip - pip install wheel setuptools - cmake $GITHUB_WORKSPACE -DPython_FIND_VIRTUALENV=FIRST - cmake $GITHUB_WORKSPACE -DPython_FIND_VIRTUALENV=ONLY - cmake --build . --target create_python_wheel --config Release - shell: bash - working-directory: ${{ runner.workspace }}/_build - - name: Run Tests run: ctest -V working-directory: ${{ runner.workspace }}/_build @@ -151,8 +118,3 @@ jobs: name: ubuntu-debian path: ${{ runner.workspace }}/_build/_deploy/*.deb - - name: Upload Python Wheel - uses: actions/upload-artifact@v4 - with: - name: ubuntu-python-wheel - path: ${{ runner.workspace }}/_build/_deploy/*.whl diff --git a/.github/workflows/build-ubuntu-22.yml b/.github/workflows/build-ubuntu-22.yml index afc88c1c29..d8e0df3381 100644 --- a/.github/workflows/build-ubuntu-22.yml +++ b/.github/workflows/build-ubuntu-22.yml @@ -103,39 +103,6 @@ jobs: run: cmake --build . --config Release -- -k 0 working-directory: ${{ runner.workspace }}/_build - # Create Python Wheels - # The strang-looking double-cmake is an ugly workaround to force CMake to - # re-find Python, after we have changed the venv from the outside. The - # alternative would be to clean everything, which would cause an unnecessary - # rebuild of eCAL for each python Version. - - name: Build Python 3.11 Wheel - run: | - sudo apt-get -y install python3.11-dev python3.11-venv - mkdir ".venv_311" - python3.11 -m venv ".venv_311" - source ".venv_311/bin/activate" - pip install --upgrade pip - pip install wheel setuptools - cmake $GITHUB_WORKSPACE -DPython_FIND_VIRTUALENV=FIRST - cmake $GITHUB_WORKSPACE -DPython_FIND_VIRTUALENV=ONLY - cmake --build . --target create_python_wheel --config Release - shell: bash - working-directory: ${{ runner.workspace }}/_build - - - name: Build Python 3.10 Wheel - run: | - sudo apt-get -y install python3.10-dev python3.10-venv - mkdir ".venv_310" - python3.10 -m venv ".venv_310" - source ".venv_310/bin/activate" - pip install --upgrade pip - pip install wheel setuptools - cmake $GITHUB_WORKSPACE -DPython_FIND_VIRTUALENV=FIRST - cmake $GITHUB_WORKSPACE -DPython_FIND_VIRTUALENV=ONLY - cmake --build . --target create_python_wheel --config Release - shell: bash - working-directory: ${{ runner.workspace }}/_build - - name: Run Tests run: ctest -V working-directory: ${{ runner.workspace }}/_build @@ -149,9 +116,3 @@ jobs: with: name: ubuntu-debian path: ${{ runner.workspace }}/_build/_deploy/*.deb - - - name: Upload Python Wheel - uses: actions/upload-artifact@v4 - with: - name: ubuntu-python-wheel - path: ${{ runner.workspace }}/_build/_deploy/*.whl diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index b9d09ac053..28444c6f03 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -127,7 +127,7 @@ jobs: -DBUILD_APPS=ON ^ -DBUILD_SAMPLES=ON ^ -DBUILD_TIME=ON ^ - -DBUILD_PY_BINDING=ON ^ + -DBUILD_PY_BINDING=OFF ^ -DBUILD_CSHARP_BINDING=ON ^ -DBUILD_ECAL_TESTS=ON ^ -DECAL_INCLUDE_PY_SAMPLES=OFF ^ @@ -163,83 +163,6 @@ jobs: run: cmake --build . --config Release working-directory: ${{ runner.workspace }}/_build/complete - # Create Python. - # The strang-looking double-cmake is an ugly workaround to force CMake to - # re-find Python, after we have changed the venv from the outside. The - # alternative would be to clean everything, which would cause an unnecessary - # rebuild of eCAL and HDF5 for each python Version. - - name: Build Python 3.12 Wheel - run: | - mkdir ".venv_312" - py -3.12 -m venv ".venv_312" - CALL ".venv_312\Scripts\activate.bat" - pip install wheel setuptools - cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=FIRST - cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=ONLY - cmake --build . --target create_python_wheel --config Release - shell: cmd - working-directory: ${{ runner.workspace }}/_build/complete - - - name: Build Python 3.11 Wheel - run: | - mkdir ".venv_311" - py -3.11 -m venv ".venv_311" - CALL ".venv_311\Scripts\activate.bat" - pip install wheel - cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=FIRST - cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=ONLY - cmake --build . --target create_python_wheel --config Release - shell: cmd - working-directory: ${{ runner.workspace }}/_build/complete - - - name: Build Python 3.10 Wheel - run: | - mkdir ".venv_310" - py -3.10 -m venv ".venv_310" - CALL ".venv_310\Scripts\activate.bat" - pip install wheel - cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=FIRST - cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=ONLY - cmake --build . --target create_python_wheel --config Release - shell: cmd - working-directory: ${{ runner.workspace }}/_build/complete - - - name: Build Python 3.9 Wheel - run: | - mkdir ".venv_39" - py -3.9 -m venv ".venv_39" - CALL ".venv_39\Scripts\activate.bat" - pip install wheel - cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=FIRST - cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=ONLY - cmake --build . --target create_python_wheel --config Release - shell: cmd - working-directory: ${{ runner.workspace }}/_build/complete - - - name: Build Python 3.8 Wheel - run: | - mkdir ".venv_38" - py -3.8 -m venv ".venv_38" - CALL ".venv_38\Scripts\activate.bat" - pip install wheel - cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=FIRST - cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=ONLY - cmake --build . --target create_python_wheel --config Release - shell: cmd - working-directory: ${{ runner.workspace }}/_build/complete - - - name: Build Python 3.7 Wheel - run: | - mkdir ".venv_37" - py -3.7 -m venv ".venv_37" - CALL ".venv_37\Scripts\activate.bat" - pip install wheel - cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=FIRST - cmake %GITHUB_WORKSPACE% -G "Visual Studio 16 2019" -A x64 -T v142 -DPython_FIND_VIRTUALENV=ONLY - cmake --build . --target create_python_wheel --config Release - shell: cmd - working-directory: ${{ runner.workspace }}/_build/complete - # - name: Build Documentation C # run: cmake --build . --target documentation_c # working-directory: ${{ runner.workspace }}/_build @@ -266,12 +189,6 @@ jobs: name: windows-setup path: ${{ runner.workspace }}/_build/complete/_deploy/*.exe - - name: Upload Python Wheels - uses: actions/upload-artifact@v4 - with: - name: windows-python-wheels - path: ${{ runner.workspace }}/_build/complete/_deploy/*.whl - # -------------------------------------------------------------------------------------------------- sign-windows-installer: diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml new file mode 100644 index 0000000000..ec6689924f --- /dev/null +++ b/.github/workflows/build_wheels.yml @@ -0,0 +1,63 @@ +name: Build Wheels + +on: + pull_request: + branches: + - master + release: + types: [published] + workflow_dispatch: + + +jobs: + build_wheels: + name: Build wheels on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest] + + steps: + - uses: actions/checkout@v4 + with: + submodules: 'true' + fetch-depth: 0 + + - name: Build wheels + uses: pypa/cibuildwheel@v2.17 + env: + CIBW_ARCHS: auto64 + + - uses: actions/upload-artifact@v4 + with: + name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }} + path: ./wheelhouse/*.whl + + build_arm64_wheels: + # Emulation takes a long time so we save it for release/manual triggering + name: Build arm64 wheels via emulation + runs-on: ubuntu-latest + if: ${{ github.event_name != 'pull_request' }} + + steps: + - uses: actions/checkout@v4 + with: + submodules: 'true' + fetch-depth: 0 + + - name: Set up QEMU + if: runner.os == 'Linux' + uses: docker/setup-qemu-action@v3 + with: + platforms: arm64 + + - name: Build wheels + uses: pypa/cibuildwheel@v2.17 + env: + CIBW_ARCHS_LINUX: aarch64 + + - uses: actions/upload-artifact@v4 + with: + name: cibw-wheels-arm64 + path: ./wheelhouse/*.whl + diff --git a/.gitignore b/.gitignore index 78c44f672e..4afb4f2396 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,12 @@ Thumbs.db /_vs_out* /out +# Python building and distribution +/_python_build/ +/dist/ +/lang/python/core/ecal/_version.py +/wheelhouse/ + # Binary libraries /thirdparty/npcap/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d5ee871cd..3777ea5eef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,7 +88,6 @@ option(BUILD_APPS "Build the eCAL applications" option(BUILD_SAMPLES "Build the eCAL samples" ON) option(BUILD_TIME "Build the eCAL time interfaces" ON) option(BUILD_PY_BINDING "Build eCAL python binding" OFF) -option(BUILD_STANDALONE_PY_WHEEL "Build eCAL python binding as standalone wheel" OFF) option(BUILD_CSHARP_BINDING "Build eCAL C# binding" OFF) option(BUILD_ECAL_TESTS "Build the eCAL google tests" OFF) @@ -125,7 +124,18 @@ option(CPACK_PACK_WITH_INNOSETUP "Create Innosetup installer for t set(ECAL_INSTALL_PYTHON_DIR "bin" CACHE PATH "Location to install the Python extension modules. Might be set by setupdtools install.") -set(ECAL_BUILD_VERSION "0.0.0" CACHE STRING "Inject a build version if not building from a git repository") +if(DEFINED SKBUILD_PROJECT_VERSION) + message(STATUS + "Using version from scikit-build-core: ${SKBUILD_PROJECT_VERSION}" + ) + set(ECAL_BUILD_VERSION "${SKBUILD_PROJECT_VERSION}" CACHE STRING + "Version provided by scikit-build-core and setuptools-scm" FORCE + ) +else() + set(ECAL_BUILD_VERSION "0.0.0" CACHE STRING + "Inject a build version if not building from a git repository" + ) +endif() set(ECAL_CSHARP_BUILD_SAMPLES ${BUILD_SAMPLES}) @@ -172,10 +182,12 @@ set(eCAL_VERSION_PATCH ${GIT_REVISION_PATCH}) set(eCAL_VERSION_STRING ${eCAL_VERSION_MAJOR}.${eCAL_VERSION_MINOR}.${eCAL_VERSION_PATCH}) set(eCAL_VERSION ${eCAL_VERSION_STRING}) +message(STATUS "eCAL version: ${eCAL_VERSION_STRING}") +message(DEBUG "eCAL git describe tag: ${GIT_DESCRIBE_TAG}") + include(helper_functions/ecal_add_functions) include(helper_functions/ecal_helper_functions) include(helper_functions/ecal_install_functions) -include(helper_functions/ecal_python_functions) if(MSVC) set(eCAL_PLATFORM_TOOLSET ${CMAKE_VS_PLATFORM_TOOLSET}) @@ -465,7 +477,6 @@ message(STATUS "BUILD_APPS : ${BUILD_APPS}") message(STATUS "BUILD_SAMPLES : ${BUILD_SAMPLES}") message(STATUS "BUILD_TIME : ${BUILD_TIME}") message(STATUS "BUILD_PY_BINDING : ${BUILD_PY_BINDING}") -message(STATUS "BUILD_STANDALONE_PY_WHEEL : ${BUILD_STANDALONE_PY_WHEEL}") message(STATUS "BUILD_CSHARP_BINDING : ${BUILD_CSHARP_BINDING}") message(STATUS "BUILD_ECAL_TESTS : ${BUILD_ECAL_TESTS}") message(STATUS "ECAL_INCLUDE_PY_SAMPLES : ${ECAL_INCLUDE_PY_SAMPLES}") diff --git a/CMakePresets.json b/CMakePresets.json index 986f0f0f8f..fcf0472f7d 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -62,20 +62,20 @@ } }, { - "name": "wheel", + "name": "python", "inherits": "core", - "displayName": "Python Wheel", - "description": "Minimal build for standalone python wheel", + "displayName": "Python Extensions", + "description": "Minimal build for Python extensions", "cacheVariables": { "HAS_HDF5": "ON", "BUILD_PY_BINDING": "ON", - "BUILD_STANDALONE_PY_WHEEL": "ON", - "ECAL_THIRDPARTY_BUILD_HDF5": null + "BUILD_SHARED": "OFF", + "ECAL_THIRDPARTY_BUILD_HDF5": "ON" } }, { "name": "docs", - "inherits": "wheel", + "inherits": "python", "displayName": "Documentation", "description": "Build documentation", "cacheVariables": { @@ -92,6 +92,7 @@ "HAS_CURL": "ON", "HAS_FTXUI": "ON", "BUILD_APPS": "ON", + "BUILD_SAMPLES": "ON", "ECAL_THIRDPARTY_BUILD_FINEFTP": "ON", "ECAL_THIRDPARTY_BUILD_FTXUI": "ON", "ECAL_THIRDPARTY_BUILD_SPDLOG": "ON", @@ -119,16 +120,16 @@ "configurePreset": "core" }, { - "name": "wheel", - "description": "Build standalone python wheel", - "configurePreset": "wheel", - "targets": "create_python_wheel" + "name": "python", + "description": "Build python extensions", + "configurePreset": "python", + "targets": "ecal_python" }, { "name": "docs", "description": "Build sphinx documentation", "configurePreset": "docs", - "targets": "documentation_sphinx" + "targets": "documentation_sphinx" }, { "name": "cli", diff --git a/app/app_pb/CMakeLists.txt b/app/app_pb/CMakeLists.txt index edd036188f..4118e26256 100644 --- a/app/app_pb/CMakeLists.txt +++ b/app/app_pb/CMakeLists.txt @@ -73,10 +73,4 @@ target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_14) ecal_install_library(${PROJECT_NAME}) -if(BUILD_PY_BINDING) - protobuf_generate_python_ext(python_sources ${PYTHON_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src ${ProtoFiles}) - target_sources(${PROJECT_NAME} PRIVATE ${python_sources}) - set_source_files_properties(${python_sources} PROPERTIES HEADER_FILE_ONLY TRUE) -endif() - set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER app/app_pb) diff --git a/cmake/helper_functions/ecal_python_functions.cmake b/cmake/helper_functions/ecal_python_functions.cmake deleted file mode 100644 index b51b5b179f..0000000000 --- a/cmake/helper_functions/ecal_python_functions.cmake +++ /dev/null @@ -1,112 +0,0 @@ -# ========================= eCAL LICENSE ================================= -# -# Copyright (C) 2016 - 2019 Continental Corporation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# ========================= eCAL LICENSE ================================= - -set(PYTHON_BINARY_DIR ${CMAKE_BINARY_DIR}/python) -set(PYTHON_BINARY_MODULE_DIR ${CMAKE_BINARY_DIR}/python/ecal) - -#! ecal_add_python_module : this function adds a python module -# -# This function -# -# \arg:TARGET_NAME the first argument -# \param:SOURCES SOURCES specify the fooness of the function -# \param:PYTHON_CODE PYTHON_CODE should always be 42 -# \group:GROUP1 GROUP1 is a list of project to foo -# -function(ecal_add_python_module TARGET_NAME) - - set(multiValueArgs SOURCES) - set(singleValueArgs PYTHON_CODE) - cmake_parse_arguments(ARGUMENTS - "" - "${singleValueArgs}" - "${multiValueArgs}" ${ARGN} ) - - if(NOT ARGUMENTS_SOURCES AND NOT ARGUMENTS_PYTHON_CODE) - message(ERROR "Error in ecal_add_python_module: Please specify SOURCES and / or PYTHON_CODE arguments") - endif() - - - # if Sources are specified, a library is created - if(ARGUMENTS_SOURCES) - Python_add_library(${TARGET_NAME} MODULE ${ARGUMENTS_SOURCES}) - set_target_properties(${TARGET_NAME} - PROPERTIES - PREFIX "" - LIBRARY_OUTPUT_DIRECTORY_DEBUG "${PYTHON_BINARY_MODULE_DIR}" - LIBRARY_OUTPUT_DIRECTORY_RELEASE "${PYTHON_BINARY_MODULE_DIR}" - LIBRARY_OUTPUT_DIRECTORY "${PYTHON_BINARY_MODULE_DIR}" - DEBUG_POSTFIX "_d" - ) - # if no sources are specified, then a custom target needs to be created - else() - add_custom_target(${TARGET_NAME} ALL - COMMENT "Custom python target: ${TARGET_NAME}") - endif() - - if(ARGUMENTS_PYTHON_CODE) - # Copy all files from the source folder to the python binary directory. - get_filename_component(absolute_folder_python_files ${ARGUMENTS_PYTHON_CODE} ABSOLUTE) - file(GLOB_RECURSE relative_python_files - RELATIVE ${absolute_folder_python_files} - LIST_DIRECTORIES false - CONFIGURE_DEPENDS - ${absolute_folder_python_files}/*.py) - - foreach (f ${relative_python_files}) - set(origin_file ${absolute_folder_python_files}/${f}) - set(destination_file ${PYTHON_BINARY_MODULE_DIR}/${f}) - configure_file(${origin_file} ${destination_file} COPYONLY) - endforeach() - endif() -endfunction() - -function(ecal_add_pybind11_module TARGET_NAME) - set(multiValueArgs SOURCES) - set(singleValueArgs PYTHON_CODE) - cmake_parse_arguments(ARGUMENTS - "" - "${singleValueArgs}" - "${multiValueArgs}" ${ARGN} ) - - if(NOT ARGUMENTS_SOURCES AND NOT ARGUMENTS_PYTHON_CODE) - message(ERROR "Error in ecal_add_python_module: Please specify SOURCES and / or PYTHON_CODE arguments") - endif() - - - pybind11_add_module(${TARGET_NAME} ${ARGUMENTS_SOURCES}) - set_target_properties(${TARGET_NAME} - PROPERTIES - PREFIX "" - LIBRARY_OUTPUT_DIRECTORY_DEBUG "${PYTHON_BINARY_MODULE_DIR}" - LIBRARY_OUTPUT_DIRECTORY_RELEASE "${PYTHON_BINARY_MODULE_DIR}" - LIBRARY_OUTPUT_DIRECTORY "${PYTHON_BINARY_MODULE_DIR}" - DEBUG_POSTFIX "_d" - ) - - if(ARGUMENTS_PYTHON_CODE) - add_custom_command( - TARGET ${TARGET_NAME} - PRE_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_directory ${ARGUMENTS_PYTHON_CODE} ${PYTHON_BINARY_MODULE_DIR} - ) - endif() -endfunction () - -function(ecal_install_python_module) -endfunction() \ No newline at end of file diff --git a/contrib/ecaltime/ecaltime_pb/CMakeLists.txt b/contrib/ecaltime/ecaltime_pb/CMakeLists.txt index 4c4dc0ab16..59998dfefe 100644 --- a/contrib/ecaltime/ecaltime_pb/CMakeLists.txt +++ b/contrib/ecaltime/ecaltime_pb/CMakeLists.txt @@ -62,10 +62,4 @@ target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_14) ecal_install_library(${PROJECT_NAME}) -if(BUILD_PY_BINDING) - protobuf_generate_python_ext(python_sources ${PYTHON_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src ${ProtoFiles}) - target_sources(${PROJECT_NAME} PRIVATE ${python_sources}) - set_source_files_properties(${python_sources} PROPERTIES HEADER_FILE_ONLY TRUE) -endif() - set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER contrib/ecaltime/ecaltime_pb) diff --git a/ecal/core_pb/CMakeLists.txt b/ecal/core_pb/CMakeLists.txt index 7f07e98b44..7295221be0 100644 --- a/ecal/core_pb/CMakeLists.txt +++ b/ecal/core_pb/CMakeLists.txt @@ -69,10 +69,4 @@ target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_14) ecal_install_library(${PROJECT_NAME}) -if(BUILD_PY_BINDING) - protobuf_generate_python_ext(python_sources ${PYTHON_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src ${ProtoFiles}) - target_sources(${PROJECT_NAME} PRIVATE ${python_sources}) - set_source_files_properties(${python_sources} PROPERTIES HEADER_FILE_ONLY TRUE) -endif() - set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER core) diff --git a/lang/python/CMakeLists.txt b/lang/python/CMakeLists.txt index be9c65a944..eeeee67a9d 100644 --- a/lang/python/CMakeLists.txt +++ b/lang/python/CMakeLists.txt @@ -5,9 +5,9 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,54 +16,34 @@ # # ========================= eCAL LICENSE ================================= -project(_ecal_py) - -find_package(Python COMPONENTS Development Interpreter) -find_package(Protobuf REQUIRED) - -set(SETUP_PY_IN "${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in") -set(SETUP_PY "${PYTHON_BINARY_DIR}/setup.py") - -# Create a shortened protobuf version string -string(REPLACE "." ";" Protobuf_VERSION_components "${Protobuf_VERSION}") -list(LENGTH Protobuf_VERSION_components Protobuf_VERSION_components_length) - -if ("${Protobuf_VERSION_components_length}" LESS "2") - message(FATAL_ERROR "Unable to determine protobuf version for python binding") -endif() -list(GET Protobuf_VERSION_components 0 Protobuf_VERSION_major) -list(GET Protobuf_VERSION_components 1 Protobuf_VERSION_minor) -MATH(EXPR Protobuf_Version_minor_inc "${Protobuf_VERSION_minor}+1") - -if (Protobuf_VERSION VERSION_LESS "3.19") - set(Protobuf_required_versions ">=${Protobuf_VERSION},<=3.20") -else() - set(Protobuf_required_versions ">=${Protobuf_VERSION}") -endif() +# 3.18 required for Development.Module. +# prior versions using just Development would also search for artifacts for +# embedding, which the manylinux containers don't provide +cmake_minimum_required(VERSION 3.18...3.26) +project(ecal_python) +find_package(Python REQUIRED COMPONENTS Development.Module Interpreter) -configure_file(${SETUP_PY_IN} ${SETUP_PY} @ONLY) +# Convenience target to have all Python targets buildable via one name +add_custom_target(${PROJECT_NAME}) -if(Python_Interpreter_FOUND) - message(STATUS "Python interpreter found: ${Python_EXECUTABLE}") +# We will want the shared objects to look relative to themselves for vendored +# dependencies, like eCAL core and hdf5 +# NB: Even though ${ORIGIN} and $ORIGIN are both valid, auditwheel only +# understands $ORIGIN +set(CMAKE_INSTALL_RPATH "\$ORIGIN") - # on make install the python module gets installed directly by invocing python interpreter - # TODO: this needs to be tested on windows also - message(STATUS "Installing Python extensions") - #install(CODE "execute_process(COMMAND ${Python_EXECUTABLE} setup.py install --user WORKING_DIRECTORY ${PYTHON_BINARY_DIR})") - add_custom_target(create_python_wheel - ${Python_EXECUTABLE} setup.py bdist_wheel --dist-dir=${BUILD_DEPLOY_DIRECTORY} - DEPENDS _ecal_core_py _ecal_hdf5_py - WORKING_DIRECTORY ${PYTHON_BINARY_DIR} - COMMENT "Creating python wheel" - ) - - set_property(TARGET ${create_python_wheel} PROPERTY FOLDER lang/python) -else() - message(FATAL_ERROR "Could not find python interpreter! This is needed to install the eCAL python binding!") -endif() +# Directly build with the install runtime paths as these shared objects aren't +# for build tree use. +set(CMAKE_BUILD_WITH_INSTALL_RPATH "ON") add_subdirectory(core) +add_dependencies(${PROJECT_NAME} _ecal_core_py) + if(HAS_HDF5) add_subdirectory(ecalhdf5) + add_dependencies(${PROJECT_NAME} _ecal_hdf5_py) +else() + message(WARNING "Building Python bindings without HDF5 support") endif() + diff --git a/lang/python/core/CMakeLists.txt b/lang/python/core/CMakeLists.txt index 0206b42252..c6d1972e1c 100644 --- a/lang/python/core/CMakeLists.txt +++ b/lang/python/core/CMakeLists.txt @@ -5,9 +5,9 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,51 +16,29 @@ # # ========================= eCAL LICENSE ================================= -if (WIN32) - add_custom_target(copy_ecal_core_dll ALL - COMMAND cmake -E copy_if_different "$" "${PYTHON_BINARY_MODULE_DIR}" - COMMENT "Copy eCAL Core DLL to python directory" - DEPENDS eCAL::core - ) - set_property(TARGET copy_ecal_core_dll PROPERTY FOLDER lang/python/core) -endif() - -# ========================================== - project(_ecal_core_py) -find_package(Python COMPONENTS Development Interpreter) -find_package(Protobuf REQUIRED) - -set(ecal_lang_py_src - src/ecal_clang.cpp - src/ecal_clang.h - src/ecal_wrap.cxx +python_add_library(${PROJECT_NAME} MODULE WITH_SOABI + src/ecal_clang.cpp + src/ecal_clang.h + src/ecal_wrap.cxx ) -ecal_add_python_module(${PROJECT_NAME} SOURCES ${ecal_lang_py_src} PYTHON_CODE ${CMAKE_CURRENT_SOURCE_DIR}/ecal) - target_link_libraries(${PROJECT_NAME} - PRIVATE - eCAL::core + PRIVATE + eCAL::core ) target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_14) -if (WIN32) - add_dependencies(${PROJECT_NAME} copy_ecal_core_dll) -endif() - -set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER lang/python/core) +set_target_properties(${PROJECT_NAME} PROPERTIES + FOLDER lang/python/core +) -if(BUILD_STANDALONE_PY_WHEEL AND NOT WIN32) - find_package(patchelf REQUIRED) - add_custom_command(TARGET ${PROJECT_NAME} - POST_BUILD - COMMAND "${CMAKE_COMMAND}" ARGS "-DRUNTIME_FILE=\"$\"" "-DRUNTIME_DEP_FILTER=\"ecal_core|protobuf\"" "-DRUNTIME_DEPLOY_DIR=\"${PYTHON_BINARY_MODULE_DIR}\"" -P "${CMAKE_SOURCE_DIR}/cmake/deploy_runtime_deps.cmake" - COMMAND "${PATCHELF_COMMAND}" ARGS "--remove-rpath" "\"$\"" - COMMAND "${PATCHELF_COMMAND}" ARGS "--force-rpath" "--set-rpath" "\\$$ORIGIN" "\"$\"") -endif() +install(TARGETS ${PROJECT_NAME} core + RUNTIME DESTINATION ecal COMPONENT python EXCLUDE_FROM_ALL + LIBRARY DESTINATION ecal COMPONENT python EXCLUDE_FROM_ALL NAMELINK_SKIP +) if(ECAL_INCLUDE_PY_SAMPLES) if(WIN32) diff --git a/lang/python/ecalhdf5/CMakeLists.txt b/lang/python/ecalhdf5/CMakeLists.txt index 48345a8930..560b878730 100644 --- a/lang/python/ecalhdf5/CMakeLists.txt +++ b/lang/python/ecalhdf5/CMakeLists.txt @@ -5,9 +5,9 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,57 +16,34 @@ # # ========================= eCAL LICENSE ================================= -if (WIN32) - if (TARGET hdf5::hdf5-shared) - add_custom_target(copy_hdf5_dll ALL - COMMAND cmake -E copy_if_different "$" "${PYTHON_BINARY_MODULE_DIR}" - COMMENT "Copy hdf5 DLL to python directory" - DEPENDS hdf5::hdf5-shared - ) - set_property(TARGET copy_hdf5_dll PROPERTY FOLDER lang/python/hdf5) - endif() -endif() - -# ========================================== - project(_ecal_hdf5_py) -find_package(Python COMPONENTS Development) - -set(ecal_lang_py_src - src/ecalhdf5_wrap.cxx +python_add_library(${PROJECT_NAME} MODULE WITH_SOABI + src/ecalhdf5_wrap.cxx ) -ecal_add_python_module(${PROJECT_NAME} SOURCES ${ecal_lang_py_src} PYTHON_CODE ${CMAKE_CURRENT_SOURCE_DIR}/ecal) - target_link_libraries(${PROJECT_NAME} - PRIVATE - eCAL::hdf5 + PRIVATE + eCAL::hdf5 ) target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_14) -if (WIN32) - if (TARGET hdf5::hdf5-shared) - add_dependencies(${PROJECT_NAME} copy_hdf5_dll) - endif() -endif() - -if(MSVC) - set_property(TARGET ${PROJECT_NAME} PROPERTY LINK_FLAGS "/ignore:4098,4099") -endif(MSVC) - -set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER lang/python/hdf5) +set_target_properties(${PROJECT_NAME} PROPERTIES + FOLDER lang/python/hdf5 +) -if(BUILD_STANDALONE_PY_WHEEL AND NOT WIN32) - find_package(patchelf REQUIRED) - add_custom_command(TARGET ${PROJECT_NAME} - POST_BUILD - COMMAND "${CMAKE_COMMAND}" ARGS "-DRUNTIME_FILE=\"$\"" "-DRUNTIME_DEP_FILTER=\"hdf5|sz|aec\"" "-DRUNTIME_DEPLOY_DIR=\"${PYTHON_BINARY_MODULE_DIR}\"" -P "${CMAKE_SOURCE_DIR}/cmake/deploy_runtime_deps.cmake" - COMMAND "${PATCHELF_COMMAND}" ARGS "--remove-rpath" "\"$\"" - COMMAND "${PATCHELF_COMMAND}" ARGS "--force-rpath" "--set-rpath" "\\$$ORIGIN" "\"$\"") +if(TARGET hdf5-shared) + install(TARGETS ${PROJECT_NAME} hdf5-shared + RUNTIME DESTINATION ecal COMPONENT python EXCLUDE_FROM_ALL + LIBRARY DESTINATION ecal COMPONENT python EXCLUDE_FROM_ALL NAMELINK_SKIP + ) endif() +install(TARGETS ${PROJECT_NAME} + DESTINATION ecal COMPONENT python EXCLUDE_FROM_ALL +) + if(ECAL_INCLUDE_PY_SAMPLES) if(WIN32) diff --git a/lang/python/setup.py.in b/lang/python/setup.py.in deleted file mode 100644 index 6a6028d645..0000000000 --- a/lang/python/setup.py.in +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python - -# ========================= eCAL LICENSE ================================= -# -# Copyright (C) 2016 - 2019 Continental Corporation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# ========================= eCAL LICENSE ================================= - -import setuptools -import platform -from setuptools.dist import Distribution - -class BinaryDistribution(Distribution): - """Distribution which always forces a binary package with platform name""" - def has_ext_modules(self): - return True - -# this is the input file for cmake. for further details have a look at the -# CMakeLists.txt in this directory. - -setuptools.setup ( - name = 'ecal5', - version = '@eCAL_VERSION_STRING@', - description = 'This is the eCAL python API', - license = 'Apache 2.0', - author = 'Rex Schilasky', - author_email = 'rex.schilasky@continental-corporation.com', - packages = setuptools.find_packages(), - data_files = [], - package_data = {'ecal': ['*.pyd', '*.so', '*.so.*', '*.dll']}, - install_requires = [ - 'protobuf@Protobuf_required_versions@' - ], - zip_safe=False, - distclass = BinaryDistribution, -) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000..fd6a1605c3 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,115 @@ +[project] # Project metadata +name = "eclipse-ecal" +readme = "README.md" +requires-python = ">=3.7" +license = { "file" = "LICENSE.txt" } +authors = [ + { "name" = "Kerstin Keller", "email" = "kerstin.keller@continental.com" }, +] +keywords = ["DDS", "Middlware"] +classifiers = ["Topic :: Scientific/Engineering"] +dependencies = ["protobuf >= 3.8, == 3.*"] +# setuptools-scm will grab the version from the latest git tag +dynamic = ["version"] + +[project.urls] +"Documentation" = "https://eclipse-ecal.github.io/ecal" +"Source" = "https://github.com/eclipse-ecal/ecal" + +[build-system] # How pip and other frontends should build this project +# Version 8 of setuptools_scm drops Python 3.7 +requires = ["scikit-build-core>=0.8", "setuptools_scm~=7.1"] +build-backend = "scikit_build_core.build" + +[tool.setuptools_scm] +write_to = "lang/python/core/ecal/_version.py" + +[tool.scikit-build] +# Setuptools-scm to provide the package version from git +metadata.version.provider = "scikit_build_core.metadata.setuptools_scm" +# Will be installed from PyPI if system version is too old/missing +cmake.version = ">=3.18" +cmake.targets = ["ecal_python"] # Targets to build +build-dir = "./_python_build" # Build directory for unisolated builds +install.components = ["python"] # CMake component to install +# Directory structure to copy as Python package, last path component is +# the package name +wheel.packages = ["lang/python/core/ecal", "lang/python/ecalhdf5/ecal"] + +# Files to include in the source archive to build from +sdist.exclude = ["*"] +sdist.include = [ + "/CMakeLists.txt", + "/pyproject.toml", + "/LICENSE.txt", + "/NOTICE.txt", + "/README.md", + "/app/app_pb/", + "/app/apps/", # TODO: Remove this directory + "/app/rec/rec_addon_*/", # TODO: Remove this directory + "/cmake/", + "/contrib/", + "/cpack/", + "/ecal/core/", + "/ecal/service/", + "/ecal/CMakeLists.txt", + "/lib/", + "/licenses/", + "lang/python/", + + "thirdparty/cmakefunctions/", + "thirdparty/protobuf/", + "thirdparty/recycle/", + "thirdparty/simpleini/", + "thirdparty/tclap/", + "thirdparty/tcp_pubsub/", + + "thirdparty/asio/", + "!thirdparty/asio/asio/asio/src/", + + # HDF5 has a lot of stuff we don't use + "/thirdparty/hdf5/", + "!/thirdparty/hdf5/hdf5/tools/", + "!/thirdparty/hdf5/hdf5/**/test*/", + "!/thirdparty/hdf5/hdf5/**/examples*/", + "!/thirdparty/hdf5/hdf5/hl/", + "!/thirdparty/hdf5/hdf5/doxygen/", + "!/thirdparty/hdf5/hdf5/java/", + "!/thirdparty/hdf5/hdf5/fortran/", + +] + +[tool.scikit-build.cmake.define] +CMAKE_PROJECT_TOP_LEVEL_INCLUDES = "cmake/submodule_dependencies.cmake" +HAS_HDF5 = "ON" +HAS_QT = "OFF" +HAS_CURL = "OFF" +HAS_FTXUI = "OFF" +BUILD_APPS = "OFF" +BUILD_SAMPLES = "OFF" +BUILD_TIME = "OFF" +BUILD_PY_BINDING = "ON" +BUILD_SHARED_LIBS = "OFF" +ECAL_INSTALL_SAMPLE_SOURCES = "OFF" +ECAL_THIRDPARTY_BUILD_CMAKE_FUNCTIONS = "ON" +ECAL_THIRDPARTY_BUILD_TCP_PUBSUB = "ON" +ECAL_THIRDPARTY_BUILD_RECYCLE = "ON" +ECAL_THIRDPARTY_BUILD_PROTOBUF = "ON" +ECAL_THIRDPARTY_BUILD_FINEFTP = "OFF" +ECAL_THIRDPARTY_BUILD_FTXUI = "OFF" +ECAL_THIRDPARTY_BUILD_SPDLOG = "OFF" +ECAL_THIRDPARTY_BUILD_TERMCOLOR = "OFF" +ECAL_THIRDPARTY_BUILD_TINYXML2 = "OFF" +ECAL_THIRDPARTY_BUILD_YAML-CPP = "OFF" +ECAL_THIRDPARTY_BUILD_CURL = "OFF" +ECAL_THIRDPARTY_BUILD_HDF5 = "ON" +# Stop HDF5 trying to export eCALCoreTargets due to the hack +# with HDF5_EXPORTED_TARGETS +HDF5_EXTERNALLY_CONFIGURED = "ON" + +[tool.cibuildwheel] +# Only support 64-bit builds for now as CMake gets confused when the +# architecture changes and causes link errors with Python +archs = ["auto64"] +# eCAL has build errors on musl libc +skip = [ "*-musllinux*" ]