pyspw-rmap 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. pyspw_rmap-0.0.1/.clang-format +5 -0
  2. pyspw_rmap-0.0.1/.clang-tidy +29 -0
  3. pyspw_rmap-0.0.1/.clangd +25 -0
  4. pyspw_rmap-0.0.1/.envrc +1 -0
  5. pyspw_rmap-0.0.1/.github/workflows/publish.yml +57 -0
  6. pyspw_rmap-0.0.1/.gitignore +8 -0
  7. pyspw_rmap-0.0.1/CMakeLists.txt +65 -0
  8. pyspw_rmap-0.0.1/LICENSE +21 -0
  9. pyspw_rmap-0.0.1/PKG-INFO +7 -0
  10. pyspw_rmap-0.0.1/README.md +171 -0
  11. pyspw_rmap-0.0.1/app/CMakeLists.txt +12 -0
  12. pyspw_rmap-0.0.1/app/spwrmap.cc +290 -0
  13. pyspw_rmap-0.0.1/app/spwrmap_speedtest.cc +404 -0
  14. pyspw_rmap-0.0.1/bindings/python/CMakeLists.txt +44 -0
  15. pyspw_rmap-0.0.1/bindings/python/pyspw_rmap/__init__.py +7 -0
  16. pyspw_rmap-0.0.1/bindings/python/src/pyspw_rmap.cc +210 -0
  17. pyspw_rmap-0.0.1/bindings/python/src/span_caster.hh +96 -0
  18. pyspw_rmap-0.0.1/cmake/spw_rmapConfig.cmake.in +5 -0
  19. pyspw_rmap-0.0.1/examples/CMakeLists.txt +9 -0
  20. pyspw_rmap-0.0.1/examples/packet_builder.cc +48 -0
  21. pyspw_rmap-0.0.1/examples/spwrmap_example.cc +92 -0
  22. pyspw_rmap-0.0.1/examples/spwrmap_example.py +54 -0
  23. pyspw_rmap-0.0.1/flake.lock +61 -0
  24. pyspw_rmap-0.0.1/flake.nix +119 -0
  25. pyspw_rmap-0.0.1/include/spw_rmap/crc.hh +21 -0
  26. pyspw_rmap-0.0.1/include/spw_rmap/error_code.hh +57 -0
  27. pyspw_rmap-0.0.1/include/spw_rmap/internal/debug.hh +41 -0
  28. pyspw_rmap-0.0.1/include/spw_rmap/internal/spw_rmap_tcp_node_impl.hh +973 -0
  29. pyspw_rmap-0.0.1/include/spw_rmap/internal/tcp_client.hh +73 -0
  30. pyspw_rmap-0.0.1/include/spw_rmap/internal/tcp_server.hh +75 -0
  31. pyspw_rmap-0.0.1/include/spw_rmap/packet_builder.hh +174 -0
  32. pyspw_rmap-0.0.1/include/spw_rmap/packet_parser.hh +85 -0
  33. pyspw_rmap-0.0.1/include/spw_rmap/rmap_packet_type.hh +23 -0
  34. pyspw_rmap-0.0.1/include/spw_rmap/spw_rmap_node_base.hh +129 -0
  35. pyspw_rmap-0.0.1/include/spw_rmap/spw_rmap_tcp_node.hh +126 -0
  36. pyspw_rmap-0.0.1/include/spw_rmap/target_node.hh +84 -0
  37. pyspw_rmap-0.0.1/pyproject.toml +19 -0
  38. pyspw_rmap-0.0.1/src/CMakeLists.txt +9 -0
  39. pyspw_rmap-0.0.1/src/crc.cc +55 -0
  40. pyspw_rmap-0.0.1/src/packet_builder.cc +243 -0
  41. pyspw_rmap-0.0.1/src/packet_parser.cc +226 -0
  42. pyspw_rmap-0.0.1/src/tcp_client.cc +340 -0
  43. pyspw_rmap-0.0.1/src/tcp_server.cc +261 -0
  44. pyspw_rmap-0.0.1/tests/CMakeLists.txt +15 -0
  45. pyspw_rmap-0.0.1/tests/test_internal_tcp.cc +224 -0
  46. pyspw_rmap-0.0.1/tests/test_packet.cc +366 -0
  47. pyspw_rmap-0.0.1/tests/test_spw_rmap_node.cc +244 -0
  48. pyspw_rmap-0.0.1/treefmt.toml +13 -0
@@ -0,0 +1,5 @@
1
+ BasedOnStyle: Google
2
+ ColumnLimit: 80
3
+ IndentWidth: 2
4
+ TabWidth: 2
5
+ UseTab: Never
@@ -0,0 +1,29 @@
1
+ Checks:
2
+ - modernize-*
3
+ - bugprone-*
4
+ - cppcoreguidelines-*
5
+ - -bugprone-easily-swappable-parameters
6
+ - -cppcoreguidelines-avoid-magic-numbers
7
+ - -modernize-use-std-numbers
8
+ - -cppcoreguidelines-owning-memory
9
+ - -cppcoreguidelines-pro-type-vararg
10
+ - -cppcoreguidelines-pro-bounds-pointer-arithmetic
11
+ - -cppcoreguidelines-avoid-do-while
12
+
13
+ WarningsAsErrors: '*'
14
+
15
+ ExtraArgs:
16
+ - -nostdlibinc
17
+ - -isystem/nix/store/hv7qldswrqvg1sjys1lmgjg875hkffng-python3-3.13.9/include
18
+ - -isystem/nix/store/dg6ikmg5aavlpldk5yr0ka63y9ry1hb0-gtest-1.17.0-dev/include
19
+ - -isystem/nix/store/a3mw2msblrnfmdr9nmw8ysiqh2nl4fyl-python3-3.13.9-env/include
20
+ - -isystem/nix/store/qrqws7rbynwdg34kig3mp33rjsar32dd-libcxx-19.1.2+apple-sdk-15.5/include
21
+ - -isystem/nix/store/lzwcv5378dilf1bw4gkazy3h6hkp66gm-compiler-rt-libc-21.1.2-dev/include
22
+ - -isystem/nix/store/9zym1ak4fkg1jy6w63kq37x02da6vipb-libiconv-109.100.2-dev/include
23
+ - -isystem/nix/store/4spjp33v2kkahvwl9r09hlnr8ayw6wm3-libresolv-91-dev/include
24
+ - -isystem/nix/store/xhv6ncxn7ic2ir7pp6q1vs3q83kd6nc4-libsbuf-14.1.0-dev/include
25
+ - -isystem/nix/store/qrqws7rbynwdg34kig3mp33rjsar32dd-libcxx-19.1.2+apple-sdk-15.5/include/c++/v1
26
+ - -isystem/nix/store/b0pmskfnq9b3vfqqn2zr0kfp3lj17zaw-clang-wrapper-21.1.2/resource-root/include
27
+ - -isystem/nix/store/rrjy7x4jpxp92gs1prpbg79ng0mcl5hj-apple-sdk-14.4/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include
28
+ - -isystem/nix/store/rrjy7x4jpxp92gs1prpbg79ng0mcl5hj-apple-sdk-14.4/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks (framework directory)
29
+ - -isystem/nix/store/lm725blqlq4bjmfrxps1wdizgh3k4q6z-libSystem-B/include
@@ -0,0 +1,25 @@
1
+ CompileFlags:
2
+ Add:
3
+ - -Wall
4
+ - -Werror
5
+ - -Wextra
6
+ - -Wpedantic
7
+ - -std=c++23
8
+ - -xc++
9
+ - -nostdlibinc
10
+ - -isystem/nix/store/hv7qldswrqvg1sjys1lmgjg875hkffng-python3-3.13.9/include
11
+ - -isystem/nix/store/dg6ikmg5aavlpldk5yr0ka63y9ry1hb0-gtest-1.17.0-dev/include
12
+ - -isystem/nix/store/a3mw2msblrnfmdr9nmw8ysiqh2nl4fyl-python3-3.13.9-env/include
13
+ - -isystem/nix/store/qrqws7rbynwdg34kig3mp33rjsar32dd-libcxx-19.1.2+apple-sdk-15.5/include
14
+ - -isystem/nix/store/lzwcv5378dilf1bw4gkazy3h6hkp66gm-compiler-rt-libc-21.1.2-dev/include
15
+ - -isystem/nix/store/9zym1ak4fkg1jy6w63kq37x02da6vipb-libiconv-109.100.2-dev/include
16
+ - -isystem/nix/store/4spjp33v2kkahvwl9r09hlnr8ayw6wm3-libresolv-91-dev/include
17
+ - -isystem/nix/store/xhv6ncxn7ic2ir7pp6q1vs3q83kd6nc4-libsbuf-14.1.0-dev/include
18
+ - -isystem/nix/store/qrqws7rbynwdg34kig3mp33rjsar32dd-libcxx-19.1.2+apple-sdk-15.5/include/c++/v1
19
+ - -isystem/nix/store/b0pmskfnq9b3vfqqn2zr0kfp3lj17zaw-clang-wrapper-21.1.2/resource-root/include
20
+ - -isystem/nix/store/rrjy7x4jpxp92gs1prpbg79ng0mcl5hj-apple-sdk-14.4/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include
21
+ - -isystem/nix/store/rrjy7x4jpxp92gs1prpbg79ng0mcl5hj-apple-sdk-14.4/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks (framework directory)
22
+ - -isystem/nix/store/lm725blqlq4bjmfrxps1wdizgh3k4q6z-libSystem-B/include
23
+
24
+
25
+ CompilationDatabase: ./build
@@ -0,0 +1 @@
1
+ use flake
@@ -0,0 +1,57 @@
1
+ name: Publish Python Package
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ release:
8
+ types:
9
+ - published
10
+
11
+ permissions:
12
+ contents: read
13
+ id-token: write
14
+
15
+ jobs:
16
+ publish-testpypi:
17
+ if: github.event_name == 'push'
18
+ runs-on: ubuntu-latest
19
+ env:
20
+ CMAKE_ARGS: -DSPWRMAP_BUILD_TESTS=OFF
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+ - uses: actions/setup-python@v5
24
+ with:
25
+ python-version: "3.x"
26
+ - name: Install build tooling
27
+ run: |
28
+ python -m pip install --upgrade pip
29
+ python -m pip install build
30
+ - name: Build distribution
31
+ run: python -m build
32
+ - name: Publish package to TestPyPI
33
+ uses: pypa/gh-action-pypi-publish@release/v1
34
+ with:
35
+ password: ${{ secrets.TEST_PYPI_API_TOKEN }}
36
+ repository-url: https://test.pypi.org/legacy/
37
+
38
+ publish-pypi:
39
+ if: github.event_name == 'release'
40
+ runs-on: ubuntu-latest
41
+ env:
42
+ CMAKE_ARGS: -DSPWRMAP_BUILD_TESTS=OFF
43
+ steps:
44
+ - uses: actions/checkout@v4
45
+ - uses: actions/setup-python@v5
46
+ with:
47
+ python-version: "3.x"
48
+ - name: Install build tooling
49
+ run: |
50
+ python -m pip install --upgrade pip
51
+ python -m pip install build
52
+ - name: Build distribution
53
+ run: python -m build
54
+ - name: Publish package to PyPI
55
+ uses: pypa/gh-action-pypi-publish@release/v1
56
+ with:
57
+ password: ${{ secrets.PYPI_API_TOKEN }}
@@ -0,0 +1,8 @@
1
+ .DS_Store
2
+
3
+ .direnv
4
+ .cache
5
+
6
+ build/
7
+ result
8
+ workdir/
@@ -0,0 +1,65 @@
1
+ cmake_minimum_required(VERSION 3.15)
2
+ project(spw_rmap LANGUAGES CXX)
3
+
4
+ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
5
+
6
+ option(SPWRMAP_BUILD_APPS "Build command line applications" ON)
7
+ option(SPWRMAP_BUILD_EXAMPLES "Build examples" OFF)
8
+ option(SPWRMAP_BUILD_TESTS "Build tests" ON)
9
+
10
+ add_library(${PROJECT_NAME} STATIC)
11
+
12
+ add_subdirectory(src)
13
+
14
+ if(SPWRMAP_BUILD_APPS)
15
+ add_subdirectory(app)
16
+ endif()
17
+
18
+ if(SPWRMAP_BUILD_EXAMPLES)
19
+ add_subdirectory(examples)
20
+ endif()
21
+
22
+ if(SPWRMAP_BUILD_TESTS)
23
+ enable_testing()
24
+ add_subdirectory(tests)
25
+ endif()
26
+
27
+ if(SPWRMAP_BUILD_PYTHON_BINDINGS)
28
+ add_subdirectory(bindings/python)
29
+ endif()
30
+
31
+ include(CMakePackageConfigHelpers)
32
+
33
+ install(
34
+ TARGETS ${PROJECT_NAME}
35
+ EXPORT spw_rmapTargets
36
+ INCLUDES
37
+ DESTINATION include
38
+ ARCHIVE DESTINATION lib)
39
+
40
+ install(
41
+ EXPORT spw_rmapTargets
42
+ FILE spw_rmapTargets.cmake
43
+ NAMESPACE spw_rmap::
44
+ DESTINATION lib/cmake/spw_rmap)
45
+
46
+ configure_package_config_file(
47
+ ${CMAKE_CURRENT_SOURCE_DIR}/cmake/spw_rmapConfig.cmake.in
48
+ ${CMAKE_CURRENT_BINARY_DIR}/spw_rmapConfig.cmake
49
+ INSTALL_DESTINATION lib/cmake/spw_rmap)
50
+
51
+ write_basic_package_version_file(
52
+ ${CMAKE_CURRENT_BINARY_DIR}/spw_rmapConfigVersion.cmake
53
+ VERSION 0.0.1
54
+ COMPATIBILITY SameMajorVersion)
55
+
56
+ file(GLOB HEADER_FILES ${CMAKE_SOURCE_DIR}/include/spw_rmap/*.hh)
57
+ file(GLOB HEADER_FILES_INTERNAL
58
+ ${CMAKE_SOURCE_DIR}/include/spw_rmap/internal/*.hh)
59
+
60
+ install(FILES ${HEADER_FILES} DESTINATION include/spw_rmap)
61
+ install(FILES ${HEADER_FILES_INTERNAL} DESTINATION include/spw_rmap/internal)
62
+
63
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/spw_rmapConfig.cmake
64
+ ${CMAKE_CURRENT_BINARY_DIR}/spw_rmapConfigVersion.cmake
65
+ DESTINATION lib/cmake/spw_rmap)
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Gen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.2
2
+ Name: pyspw_rmap
3
+ Version: 0.0.1
4
+ Summary: spw_rmap with python bindings
5
+ License: MIT
6
+ Requires-Python: >=3.9
7
+
@@ -0,0 +1,171 @@
1
+ # spw_rmap
2
+
3
+ `spw_rmap` is a SpaceWire/RMAP helper library that provides packet builders/parsers, a TCP transport, CLI utilities, and Python bindings.
4
+
5
+ ## Building
6
+
7
+ ```bash
8
+ cmake -S . -B build
9
+ cmake --build build
10
+ ```
11
+
12
+ Key CMake options:
13
+
14
+ - `SPWRMAP_BUILD_APPS` (default `ON`): build the `spwrmap` and `spwrmap_speedtest` CLI tools.
15
+ - `SPWRMAP_BUILD_EXAMPLES` (default `OFF`): enable examples under `examples/`.
16
+ - `SPWRMAP_BUILD_TESTS` (default `ON`): add the `tests` subdirectory and register the GTest suite.
17
+ - `SPWRMAP_BUILD_PYTHON_BINDINGS` (default `OFF`): build the pybind11 module (also enabled when using `pyproject.toml` / `scikit-build-core`).
18
+
19
+ ## Testing
20
+
21
+ ```bash
22
+ cmake --build build --target spwrmap_tests
23
+ cd build
24
+ ctest --output-on-failure
25
+ ```
26
+
27
+ Some TCP tests require the ability to bind a local port; they will be skipped automatically when the environment forbids that operation (e.g., in sandboxed CI).
28
+
29
+ ## Python bindings
30
+
31
+ To build the wheel:
32
+
33
+ ```bash
34
+ python -m pip install . # uses pyproject + scikit-build-core
35
+ ```
36
+
37
+ The resulting package exposes `_core.SpwRmapTCPNode` mirroring the C++ API.
38
+
39
+ ## Key Concepts
40
+
41
+ - `target_node`: abstraction describing a SpaceWire node address (logical address, SpaceWire hop list, reply path). Implemented by `TargetNodeBase` with fixed/dynamic variants so the same transport can talk to different hardware endpoints.
42
+ - `tcp_node`: the SpaceWire-over-TCP bridge (`SpwRmapTCPClient`/`SpwRmapTCPServer`) that owns the sockets, buffers, and RMAP transaction management.
43
+ - `write` / `read`: synchronous helpers that perform the transaction, block until a reply arrives (or timeout/retry), and return `std::expected` success/error codes.
44
+ - `writeAsync` / `readAsync`: asynchronous variants returning `std::future` that resolve when the reply is received; they invoke user-supplied callbacks before fulfilling the future so event-driven integrations can react immediately.
45
+
46
+ See `examples/spwrmap_example.cc` (C++) and `examples/spwrmap_example.py` (Python) for minimal workflows demonstrating how to connect, construct a target node, and issue read/write RMAP commands.
47
+
48
+ # Quick Start Guide
49
+
50
+ ## C++
51
+
52
+ ### Initialize spw
53
+
54
+ ```cpp
55
+ #include <chrono>
56
+ #include <memory>
57
+ #include <thread>
58
+ #include <vector>
59
+
60
+ #include <spw_rmap/spw_rmap_tcp_node.hh>
61
+ #include <spw_rmap/target_node.hh>
62
+
63
+ int main() {
64
+ using namespace std::chrono_literals;
65
+
66
+ spw_rmap::SpwRmapTCPClient client(
67
+ {.ip_address = "127.0.0.1", .port = "10030"});
68
+
69
+ client.setInitiatorLogicalAddress(0xFE);
70
+ client.connect(500ms).value(); // abort on failure
71
+
72
+ std::thread loop([&client] {
73
+ auto res = client.runLoop();
74
+ if (!res) {
75
+ throw std::system_error(res.error());
76
+ }
77
+ });
78
+
79
+ // ...
80
+
81
+ client.shutdown();
82
+ if (loop.joinable()) {
83
+ loop.join();
84
+ }
85
+ }
86
+ ```
87
+
88
+ You can also call `poll()` manually from your own loop instead of spawning a thread.
89
+
90
+ ### Creating target node
91
+
92
+ ```cpp
93
+ auto target = std::make_shared<spw_rmap::TargetNodeDynamic>(
94
+ /*logical_address=*/0x34,
95
+ std::vector<uint8_t>{3, 5, 7}, // SpaceWire hops
96
+ std::vector<uint8_t>{9, 11, 13, 0x0} // Reply path
97
+ );
98
+ ```
99
+
100
+ `TargetNodeFixed<N,M>` is available when the address sizes are known at compile time.
101
+
102
+ ### Read and write
103
+
104
+ ```cpp
105
+ std::array<uint8_t, 4> write_payload{0x12, 0x34, 0x56, 0x78};
106
+ client.write(target, /*address=*/0x20000000, write_payload).value();
107
+
108
+ std::array<uint8_t, 4> read_buffer{};
109
+ client.read(target, 0x20000000, std::span(read_buffer)).value();
110
+
111
+ auto read_future =
112
+ client.readAsync(target, 0x20000000, /*length=*/4,
113
+ [](spw_rmap::Packet packet) {
114
+ std::cout << "Async read returned "
115
+ << packet.data.size() << " bytes\n";
116
+ });
117
+ read_future.get().value();
118
+
119
+ auto write_future =
120
+ client.writeAsync(target, 0x20000000, std::span(write_payload),
121
+ [](const spw_rmap::Packet&) {
122
+ std::cout << "Async write acknowledged\n";
123
+ });
124
+ write_future.get().value();
125
+ ```
126
+
127
+ `write`/`read` are *synchronous*: they transmit the command, block until a reply is parsed (with retries/timeouts handled internally), and return `std::expected`.
128
+ `writeAsync`/`readAsync` are *asynchronous*: they enqueue the transaction, immediately return a `std::future`, and invoke the supplied callback as soon as the reply arrives—before the future resolves—allowing low-latency event handling.
129
+
130
+ ## Python
131
+
132
+ ### Initialize spw
133
+
134
+ ```python
135
+ from pyspw_rmap import _core as spw
136
+
137
+ node = spw.SpwRmapTCPNode("127.0.0.1", "10030")
138
+ node.start() # connects and launches runLoop internally
139
+ ```
140
+
141
+ Call `node.stop()` to shut down and join the worker thread. Manual polling isn’t exposed in Python; launch `start()` once and let the worker handle replies.
142
+
143
+ ### Creating target node
144
+
145
+ ```python
146
+ target = spw.TargetNode()
147
+ target.logical_address = 0x34
148
+ target.target_spacewire_address = [3, 5, 7]
149
+ target.reply_address = [9, 11, 13, 0]
150
+ ```
151
+
152
+ ### Read and write
153
+
154
+ ```python
155
+ # blocking write/read; no async API is exposed in Python
156
+ node.write(target, 0x20000000, [0x12, 0x34, 0x56, 0x78])
157
+ data = node.read(target, 0x20000000, 4)
158
+ print("sync read:", list(data))
159
+
160
+ node.stop()
161
+
162
+ ## Timeouts and Error Handling
163
+
164
+ - `write` / `read` accept a `timeout` (default 100 ms) and a `retry_count`. When the timeout expires the pending transaction is cancelled internally, its transaction ID is released, and the call returns `std::errc::timed_out`. This prevents deadlocks when a remote node never replies.
165
+
166
+ - Asynchronous APIs propagate callback failures: if the function you pass to `writeAsync` / `readAsync` throws, the exception is caught by the library, the transaction is cancelled, and the returned `std::future` resolves to `std::errc::operation_canceled`. This keeps the polling loop alive and makes the failure visible to the caller. Catch exceptions inside your callback if you want to mark the operation successful despite local errors.
167
+ ```
168
+
169
+ Python bindings currently offer only synchronous `read`/`write` methods. To parallelize operations you must call them from your own threads or processes; there is no built-in async wrapper.
170
+
171
+ The [examples](examples) directory contains CLI programs that parse command-line arguments, manage the lifecycle for you, and show additional patterns (speed tests, multi-target setups, etc.).
@@ -0,0 +1,12 @@
1
+ add_executable(spwrmap_cli spwrmap.cc)
2
+ target_link_libraries(spwrmap_cli PRIVATE spw_rmap)
3
+ target_compile_features(spwrmap_cli PRIVATE cxx_std_23)
4
+ set_target_properties(spwrmap_cli PROPERTIES OUTPUT_NAME spwrmap)
5
+
6
+ add_executable(spwrmap_speedtest_cli spwrmap_speedtest.cc)
7
+ target_link_libraries(spwrmap_speedtest_cli PRIVATE spw_rmap)
8
+ target_compile_features(spwrmap_speedtest_cli PRIVATE cxx_std_23)
9
+ set_target_properties(spwrmap_speedtest_cli PROPERTIES
10
+ OUTPUT_NAME spwrmap_speedtest)
11
+
12
+ install(TARGETS spwrmap_cli spwrmap_speedtest_cli RUNTIME DESTINATION bin)