Skip to content

Commit 8d813ed

Browse files
authored
RSDK-10366 - rust utils for windows (#416)
1 parent 4a4241e commit 8d813ed

File tree

16 files changed

+131
-42
lines changed

16 files changed

+131
-42
lines changed

.github/workflows/conan.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ jobs:
4040
github.event_name == 'schedule' &&
4141
steps.git_info.outputs.current_commit == steps.last_successful_commit.outputs.commit-hash
4242
43+
# TODO (RSDK-10666) add windows build testing
44+
4345
build_macos:
4446
if: github.repository_owner == 'viamrobotics'
4547
needs: [prepare]

.github/workflows/release.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,53 @@ jobs:
3636
uses: andymckay/[email protected]
3737
if: steps.release_exists.outputs.id != ''
3838

39+
build_windows:
40+
if: github.repository_owner == 'viamrobotics'
41+
needs: [prepare]
42+
runs-on: windows-latest
43+
strategy:
44+
fail-fast: false
45+
matrix:
46+
include:
47+
- target: x86_64-windows
48+
platform: windows_x86_64
49+
steps:
50+
- name: Checkout Code
51+
uses: actions/checkout@v4
52+
with:
53+
ref: ${{ needs.prepare.outputs.sha }}
54+
55+
- name: Install dependencies
56+
run: choco install -y conan git
57+
58+
- name: Create package
59+
shell: powershell
60+
# TODO (RSDK-10666) Use conan invocations rather than cmake invocations here
61+
run: |
62+
Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1
63+
refreshenv
64+
conan profile detect
65+
conan install . --output-folder=build-conan --build=missing -o "&:shared=False"
66+
cmake . --preset conan-default
67+
cmake --build --preset=conan-release --target ALL_BUILD install -j 8
68+
env:
69+
CONAN_USER_HOME: c:/cache
70+
CONAN_USER_HOME_SHORT: c:/cache/conan_shortpaths
71+
72+
- name: Copy
73+
run: |
74+
cmake --install build-conan/build --prefix builds/viam-cpp-sdk-${{ matrix.platform }}
75+
76+
- name: Create tar
77+
run: |
78+
tar -czvf builds/viam-cpp-sdk-${{ matrix.platform }}.tar.gz builds/viam-cpp-sdk-${{ matrix.platform }}
79+
80+
- name: Upload artifacts
81+
uses: actions/upload-artifact@v4
82+
with:
83+
name: viam-cpp-sdk-${{ matrix.platform }}.tar.gz
84+
path: builds/viam-cpp-sdk-${{ matrix.platform }}.tar.gz
85+
3986
build_macos:
4087
if: github.repository_owner == 'viamrobotics'
4188
needs: [prepare]

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
/build/*
66

77
# For now, ignore any viam_rust_utils library in the root.
8+
# The `lib` prefix is on unix-based systems only
89
/libviam_rust_utils*
10+
/viam_rust_utils*
911

1012
# Ignore clang cache.
1113
/.cache/

BUILDING.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,23 @@ have a different version of `protoc` available in your `PATH`, it will
260260
silently fail and later cause compilation failures due to protobuf
261261
version mismatches.
262262

263+
## Building for ARM Windows
264+
265+
The C++ SDK works well on windows for both client and module code
266+
provided there is internet connectivity. However, some manual work is
267+
required to build for client code on ARM64 architecture.
268+
269+
1. (client code only) clone [rust-utils](https://github.com/viamrobotics/rust-utils) >= v0.3.0 and
270+
build locally with `cargo build --release`. Copy `target\release\viam_rust_utils.lib`
271+
to the root of the C++ SDK directory.
272+
2. Ensure `conan` is installed (see `Building with Conan` above).
273+
3. Run the following:
274+
```
275+
conan profile detect
276+
cmake . --preset conan-default <cmake args>
277+
cmake --build --preset=conan-release -j
278+
```
279+
263280
## Options to Configure or Customize the Build
264281

265282
### Options for Package Search

CMakeLists.txt

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -266,14 +266,20 @@ if (viam_rust_utils_files)
266266
${viam_rust_utils_file}
267267
ONLY_IF_DIFFERENT
268268
)
269-
elseif(NOT WIN32) # TODO(RSDK-10366): Currently, rust_utils is not published for windows, so don't even try downloading
269+
elseif(NOT WIN32 OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64")
270270
set(lvru_system_name ${CMAKE_SYSTEM_NAME})
271271
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
272272
set(lvru_system_name "macosx")
273273
endif()
274+
275+
set(lvru_system_processor ${CMAKE_SYSTEM_PROCESSOR})
276+
if(WIN32)
277+
set(lvru_system_processor "x86_64")
278+
endif()
279+
274280
file(
275281
DOWNLOAD
276-
https://github.com/viamrobotics/rust-utils/releases/latest/download/${CMAKE_SHARED_LIBRARY_PREFIX}viam_rust_utils-${lvru_system_name}_${CMAKE_SYSTEM_PROCESSOR}${CMAKE_STATIC_LIBRARY_SUFFIX}
282+
https://github.com/viamrobotics/rust-utils/releases/latest/download/${CMAKE_SHARED_LIBRARY_PREFIX}viam_rust_utils-${lvru_system_name}_${lvru_system_processor}${CMAKE_STATIC_LIBRARY_SUFFIX}
277283
${viam_rust_utils_file}
278284
STATUS lvru_status
279285
)
@@ -283,24 +289,21 @@ elseif(NOT WIN32) # TODO(RSDK-10366): Currently, rust_utils is not published for
283289
if(NOT lvru_status_code EQUAL 0)
284290
message(FATAL_ERROR "No local viam_rust_utils found and failed to download: ${lvru_status_string}")
285291
endif()
286-
292+
else()
293+
message(WARNING "Currently running on Windows with no rust-utils file. Module code should work as expected, but client code may fail unexpectedly.")
287294
endif()
288295

289-
# TODO(RSDK-10366): Currently, rust_utils is not published for windows, so don't even declare the library
290-
if (NOT WIN32)
291-
add_library(viam_rust_utils SHARED IMPORTED)
292-
296+
if (NOT WIN32 OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64")
297+
add_library(viam_rust_utils STATIC IMPORTED)
293298
target_link_directories(viam_rust_utils
294299
INTERFACE
295300
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>"
296301
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_LIBDIR}>"
297302
)
298-
299303
set_property(TARGET viam_rust_utils PROPERTY IMPORTED_LOCATION ${viam_rust_utils_file})
300304

301305
install(
302-
IMPORTED_RUNTIME_ARTIFACTS viam_rust_utils
303-
LIBRARY COMPONENT viam-cpp-sdk_runtime
306+
FILES ${viam_rust_utils_file} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT viam-cpp-sdk_runtime
304307
)
305308
endif()
306309

conanfile.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,7 @@ def package(self):
9191

9292
def package_info(self):
9393

94-
# TODO(RSDK-10366): Currently, rust_utils is not published for windows
95-
# and the C++ SDK just doesn't include it as a dependency on that platform
96-
if not self.settings.os == "Windows":
97-
self.cpp_info.components["viam_rust_utils"].libs = ["viam_rust_utils"]
94+
self.cpp_info.components["viam_rust_utils"].libs = ["viam_rust_utils"]
9895

9996
self.cpp_info.components["viamsdk"].libs = ["viamsdk"]
10097

@@ -137,11 +134,8 @@ def package_info(self):
137134
"viamapi",
138135
])
139136

140-
# TODO(RSDK-10366): Currently, rust_utils is not published for windows
141-
# and the C++ SDK just doesn't include it as a dependency on that platform
142-
if self.settings.os != "Windows":
143-
self.cpp_info.components["viamsdk"].requires.extend([
144-
"viam_rust_utils"
145-
])
137+
self.cpp_info.components["viamsdk"].requires.extend([
138+
"viam_rust_utils"
139+
])
146140

147141
self.cpp_info.components["viamsdk"].frameworks = ["Security"]

src/viam/examples/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ char *path = dial("<your robot uri here>", "<your authentication type>", "<your
5656
Then to obtain a robot client do :
5757

5858
``` c++
59-
std::string address("unix://");
59+
std::string address("unix:");
6060
address += path;
6161
RobotServiceClient client(grpc::CreateChannel(address, grpc::InsecureChannelCredentials()));
6262
```

src/viam/examples/mlmodel/example_audio_classification_client.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ int main(int argc, char* argv[]) try {
377377
});
378378

379379
// Print out the top 5 (or fewer) label/score pairs.
380-
for (size_t i = 0; i != std::min(5UL, scored_labels.size()); ++i) {
380+
for (size_t i = 0; i != std::min(size_t{5}, scored_labels.size()); ++i) {
381381
// TODO: Avoid hardcoding the width here.
382382
VIAM_SDK_LOG(info) << boost::format("%1%: %2% %|40t|%3%\n") % i %
383383
*scored_labels[i].label % scored_labels[i].score;

src/viam/examples/modules/complex/gizmo/api.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@ class Gizmo : public Component {
3030
explicit Gizmo(std::string name);
3131
};
3232

33-
namespace viam::sdk {
33+
namespace viam {
34+
namespace sdk {
3435
template <>
3536
struct API::traits<Gizmo> {
3637
static ::viam::sdk::API api();
3738
};
38-
} // namespace viam::sdk
39+
} // namespace sdk
40+
} // namespace viam
3941

4042
// `GizmoClient` is the gRPC client implementation of a `Gizmo` component.
4143
class GizmoClient : public Gizmo {

src/viam/examples/modules/complex/summation/api.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@ class Summation : public Service {
2929
explicit Summation(std::string name);
3030
};
3131

32-
namespace viam::sdk {
32+
namespace viam {
33+
namespace sdk {
3334
template <>
3435
struct API::traits<Summation> {
3536
static API api();
3637
};
37-
} // namespace viam::sdk
38+
} // namespace sdk
39+
} // namespace viam
3840

3941
// `SummationClient` is the gRPC client implementation of a `Summation`
4042
// service.

src/viam/sdk/CMakeLists.txt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -276,22 +276,30 @@ target_link_libraries(viamsdk
276276
PRIVATE Threads::Threads
277277
)
278278

279-
# TODO(RSDK-10366): Currently, rust_utils is not published for
280-
# windows, so don't link to it. Instead, link a stub implementation
281-
# that just calls `abort`.
282-
if (NOT WIN32)
279+
# if the `viam_rust_utils` target exists then we should use it. If not then
280+
# we're probably on a non-x86_64 windows build or some other platform without
281+
# automated `rust-utils` builds, so we should use the stubs instead.
282+
if (TARGET viam_rust_utils)
283283
target_link_libraries(viamsdk
284284
PRIVATE viam_rust_utils
285285
)
286286
else()
287287
target_sources(viamsdk PRIVATE rpc/private/viam_rust_utils_stubs.cpp)
288288
endif()
289289

290+
291+
# TODO several of these dependencies should properly be attached to `viam_rust_utils`,
292+
# not `viamsdk`. However, we currently are unable to do so while maintaining compilation
290293
if (APPLE)
291294
target_link_libraries(viamsdk PUBLIC "-framework Security")
292-
else()
295+
elseif (NOT WIN32)
293296
target_link_libraries(viamsdk PRIVATE dl)
294297
target_link_libraries(viamsdk PRIVATE rt)
298+
else()
299+
target_link_libraries(viamsdk INTERFACE Ncrypt.lib)
300+
target_link_libraries(viamsdk INTERFACE Secur32.lib)
301+
target_link_libraries(viamsdk INTERFACE Ntdll.lib)
302+
target_link_libraries(viamsdk INTERFACE Userenv.lib)
295303
endif()
296304

297305

src/viam/sdk/robot/client.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ std::shared_ptr<RobotClient> RobotClient::at_address(const std::string& address,
294294

295295
std::shared_ptr<RobotClient> RobotClient::at_local_socket(const std::string& address,
296296
const Options& options) {
297-
const std::string addr = "unix://" + address;
297+
const std::string addr = "unix:" + address;
298298
auto robot = RobotClient::with_channel(
299299
ViamChannel(sdk::impl::create_viam_channel(addr, grpc::InsecureChannelCredentials())),
300300
options);

src/viam/sdk/robot/client.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class RobotClient {
9797
/// @brief Creates a robot client connected to the robot at the provided local socket.
9898
/// @param address The local socket of the robot (a .sock file, etc.).
9999
/// @param options Options for connecting and refreshing.
100-
/// Creates a direct connection to the robot using the `unix://` scheme.
100+
/// Creates a direct connection to the robot using the `unix:` scheme.
101101
/// Only useful for connecting to robots across Unix sockets.
102102
static std::shared_ptr<RobotClient> at_local_socket(const std::string& address,
103103
const Options& options);

src/viam/sdk/rpc/dial.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <viam/sdk/rpc/dial.hpp>
22

3+
#include <algorithm>
34
#include <istream>
45
#include <string>
56

@@ -171,18 +172,23 @@ ViamChannel ViamChannel::dial(const char* uri, const boost::optional<DialOptions
171172
if (opts.entity()) {
172173
entity = opts.entity()->c_str();
173174
}
174-
char* socket_path = ::dial(
175+
char* proxy_path = ::dial(
175176
uri, entity, type, payload, opts.allows_insecure_downgrade(), float_timeout.count(), ptr);
176-
if (socket_path == NULL) {
177+
if (!proxy_path) {
177178
free_rust_runtime(ptr);
178179
throw Exception(ErrorCondition::k_connection, "Unable to establish connecting path");
179180
}
180181

181-
std::string address("unix://");
182-
address += socket_path;
182+
const std::string localhost_prefix("127.0.0.1");
183+
std::string address;
184+
if (std::string(proxy_path).find(localhost_prefix) == std::string::npos) {
185+
// proxy path is not a localhost address and is therefore a unix domain socket (UDS)
186+
address += "unix:";
187+
}
188+
address += proxy_path;
183189

184190
return ViamChannel(sdk::impl::create_viam_channel(address, grpc::InsecureChannelCredentials()),
185-
socket_path,
191+
proxy_path,
186192
ptr);
187193
}
188194

src/viam/sdk/rpc/server.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
/// @brief Defines the `Server` class.
44
#pragma once
55

6+
#include <chrono>
7+
68
#include <viam/sdk/common/grpc_fwd.hpp>
79
#include <viam/sdk/resource/resource.hpp>
810
#include <viam/sdk/resource/resource_api.hpp>

src/viam/sdk/tests/mocks/mock_robot.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,8 @@ ::grpc::Status MockRobotService::FrameSystemConfig(
299299
const ::viam::robot::v1::FrameSystemConfigRequest*,
300300
::viam::robot::v1::FrameSystemConfigResponse* response) {
301301
auto client_md = context->client_metadata();
302-
if (auto client_info = client_md.find("viam_client"); client_info == client_md.end()) {
302+
auto client_info = client_md.find("viam_client");
303+
if (client_info == client_md.end()) {
303304
return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION,
304305
"viam_client info not properly set in metadata");
305306
}
@@ -314,7 +315,8 @@ ::grpc::Status MockRobotService::TransformPose(::grpc::ServerContext* context,
314315
const ::viam::robot::v1::TransformPoseRequest*,
315316
::viam::robot::v1::TransformPoseResponse* response) {
316317
auto client_md = context->client_metadata();
317-
if (auto client_info = client_md.find("viam_client"); client_info == client_md.end()) {
318+
auto client_info = client_md.find("viam_client");
319+
if (client_info == client_md.end()) {
318320
return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION,
319321
"viam_client info not properly set in metadata");
320322
}
@@ -327,7 +329,8 @@ ::grpc::Status MockRobotService::GetMachineStatus(
327329
const ::viam::robot::v1::GetMachineStatusRequest*,
328330
::viam::robot::v1::GetMachineStatusResponse* response) {
329331
auto client_md = context->client_metadata();
330-
if (auto client_info = client_md.find("viam_client"); client_info == client_md.end()) {
332+
auto client_info = client_md.find("viam_client");
333+
if (client_info == client_md.end()) {
331334
return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION,
332335
"viam_client info not properly set in metadata");
333336
}
@@ -341,7 +344,8 @@ ::grpc::Status MockRobotService::GetOperations(::grpc::ServerContext* context,
341344
const ::viam::robot::v1::GetOperationsRequest*,
342345
::viam::robot::v1::GetOperationsResponse* response) {
343346
auto client_md = context->client_metadata();
344-
if (auto client_info = client_md.find("viam_client"); client_info == client_md.end()) {
347+
auto client_info = client_md.find("viam_client");
348+
if (client_info == client_md.end()) {
345349
return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION,
346350
"viam_client info not properly set in metadata");
347351
}

0 commit comments

Comments
 (0)