Skip to content

RSDK-10366 - rust utils for windows #416

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 95 commits into from
May 16, 2025

Conversation

stuqdog
Copy link
Member

@stuqdog stuqdog commented Apr 18, 2025

Adds support for tcp-based rust-utils, updates rust-utils downloading for x86_64 windows.

Tested tcp connection on mac successfully.

Tested on windows: with a properly built viam_rust_utils.lib at the root of the directory, I am able to connect as a client via webRTC. Without a viam_rust_utils.lib at the root of the directory, I instead link in the stubs that were previously being linked, and abort() out whenever making a rust-utils call (as we were doing previously). edit: with the recent update to rust-utils, we now successfully download rust-utils if it's not in the root, so long as we're on x86_64.

@stuqdog stuqdog requested a review from a team as a code owner April 18, 2025 15:03
@stuqdog stuqdog requested review from njooma and lia-viam and removed request for a team April 18, 2025 15:03
CMakeLists.txt Outdated
Comment on lines 269 to 283
elseif(NOT WIN32 OR (CMAKE_SYSTEM_PROCESSOR STREQUAL "X86") OR (CMAKE_SYSTEM_PROCESSOR STREQUAL "X64")) # TODO(RSDK-10366): Currently, rust_utils is not published for windows aarch, so don't even try downloading
set(lvru_system_name ${CMAKE_SYSTEM_NAME})
if (CMAKE_SYSTEM_NAME STREQUAL "Cygwin")
set(lvru_system_name "windows")
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set(lvru_system_name "macosx")
endif()
set(lvru_system_processor ${CMAKE_SYSTEM_PROCESSOR})
if ((CMAKE_SYSTEM_PROCESSOR STREQUAL "X86") OR (CMAKE_SYSTEM_PROCESSOR STREQUAL "X64"))
set(lvru_system_processor "x86_64")
endif()
file(
DOWNLOAD
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}
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}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should hopefully download rust-utils on windows systems when building the SDK. However, it is currently untested. When I next have access to a windows laptop I will test and confirm. If it doesn't work and is not trivial to get working, I will remove all of this and update the README with instructions on building from source.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is reasonably easy to spin up a windows machine in GCP and RDP into it if you just need a quick test.

std::string address;
if (tcp_check.first != localhost_prefix.end()) {
// proxy path is not a localhost address and is therefore a UDS socket
address += "unix://";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In 62d40eb#diff-03661151ee3ff17fde17964451d2ea2fbd2322f2bd21f4851eade22a2aaad233R254, I found that using unix: enabled Windows support, while I couldn't get anything with unix:// to work on windows. Per the gRPC docs, the only difference between the two is that the latter form with unix:// is restricted to absolute paths, while unix: will accept either: https://grpc.github.io/grpc/cpp/md_doc_naming.html.

It might be worth considering just making the switch to unix: here now, in case client usage on Windows is ever required, this hard to find fact will not need to be rediscovered.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah good call, I'm happy to change this to unix:.

fwiw this PR is actually enabling windows client usage! The restriction was UDS support in tokio, but now that rust-utils will be using TCP sockets instead on windows, this PR enables us to use rust-utils on windows. but this change definitely still seems good, especially if tokio ever starts supporting UDS on windows.

uri, entity, type, payload, opts.allows_insecure_downgrade(), float_timeout.count(), ptr);
if (socket_path == NULL) {
if (proxy_path == NULL) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nullptr is preferred, or just invert the check: if (!proxy_path) {

free_rust_runtime(ptr);
throw Exception(ErrorCondition::k_connection, "Unable to establish connecting path");
}

std::string address("unix://");
address += socket_path;
std::string localhost_prefix("127.0.0.1");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are other forms of localhost, like ::1. Probably not important?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the address we get back from rust-utils is consistently of the form 127.0.0.1:{port} so I opted for that.

auto tcp_check = std::mismatch(localhost_prefix.begin(), localhost_prefix.end(), proxy_path);
std::string address;
if (tcp_check.first != localhost_prefix.end()) {
// proxy path is not a localhost address and is therefore a UDS socket
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

S socket is redundant. Maybe better to say it fully as unix domain socket (UDS).

std::string address("unix://");
address += socket_path;
std::string localhost_prefix("127.0.0.1");
auto tcp_check = std::mismatch(localhost_prefix.begin(), localhost_prefix.end(), proxy_path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why std::mismatch over just std::string::find? and comparing to npos? Is this doing something more than just checking for "127.0.0.1" as a substring?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no good reason why! I asked the internet how to find a substring in C++ and somehow the first thing I landed on was an SO post recommending std::mismatch 😅 I'll switch to std::string::find.

CMakeLists.txt Outdated
set(lvru_system_name ${CMAKE_SYSTEM_NAME})
if (CMAKE_SYSTEM_NAME STREQUAL "Cygwin")
set(lvru_system_name "windows")
endif()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe elseif here?

CMakeLists.txt Outdated
Comment on lines 269 to 283
elseif(NOT WIN32 OR (CMAKE_SYSTEM_PROCESSOR STREQUAL "X86") OR (CMAKE_SYSTEM_PROCESSOR STREQUAL "X64")) # TODO(RSDK-10366): Currently, rust_utils is not published for windows aarch, so don't even try downloading
set(lvru_system_name ${CMAKE_SYSTEM_NAME})
if (CMAKE_SYSTEM_NAME STREQUAL "Cygwin")
set(lvru_system_name "windows")
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set(lvru_system_name "macosx")
endif()
set(lvru_system_processor ${CMAKE_SYSTEM_PROCESSOR})
if ((CMAKE_SYSTEM_PROCESSOR STREQUAL "X86") OR (CMAKE_SYSTEM_PROCESSOR STREQUAL "X64"))
set(lvru_system_processor "x86_64")
endif()
file(
DOWNLOAD
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}
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}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is reasonably easy to spin up a windows machine in GCP and RDP into it if you just need a quick test.

@@ -1,3 +1,4 @@
#include <algorithm>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be down with the other C++ standard library includes around line 4-5

@stuqdog stuqdog requested a review from acmorrow April 18, 2025 16:55
Copy link
Member

@acmorrow acmorrow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

conan create . `
--build=missing `
-o "&:shared=False"
cmake . --preset conan-default
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rehashing an offline discussion, this type of invocation is suitable for release.yml but with conan.yml we do want to test that we can get a successful conan create, because that packages and tests the SDK conan package

@stuqdog stuqdog requested review from lia-viam and acmorrow May 9, 2025 12:32
Comment on lines 43 to 74
# TODO (RSDK-10666) Uncomment and fix
#build_windows:
#if: github.repository_owner == 'viamrobotics'
#needs: [prepare]
#runs-on: windows-latest
#strategy:
#fail-fast: false
#matrix:
#include:
#- target: x86_64-windows
#platform: windows_x86_64
#steps:
#- name: Checkout Code
#uses: actions/checkout@v4

#- name: Install dependencies
#uses: crazy-max/ghaction-chocolatey@v3
#with:
#args: install -y conan git

#- name: Create package
#shell: powershell
#run: |
#Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1
#refreshenv
#conan profile detect
#conan create . `
#--build=missing `
#-o "&:shared=False"
#env:
#CONAN_USER_HOME: c:/cache
#CONAN_USER_HOME_SHORT: c:/cache/conan_shortpaths
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure when we'll get around to fixing this so I don't know that I feel quite as strongly about leaving this in for future reference. Happy to just remove if preferred.

We can definitely try and fix now, but unless someone has a very clear picture of what's wrong I think I'd prefer to do that in a separate PR so we can lock in the wins here now.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think maybe just leave in the TODO/ticket number but the commented code can be removed, we can always consult this diff to see what you had written I believe

Comment on lines 43 to 74
# TODO (RSDK-10666) Uncomment and fix
#build_windows:
#if: github.repository_owner == 'viamrobotics'
#needs: [prepare]
#runs-on: windows-latest
#strategy:
#fail-fast: false
#matrix:
#include:
#- target: x86_64-windows
#platform: windows_x86_64
#steps:
#- name: Checkout Code
#uses: actions/checkout@v4

#- name: Install dependencies
#uses: crazy-max/ghaction-chocolatey@v3
#with:
#args: install -y conan git

#- name: Create package
#shell: powershell
#run: |
#Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1
#refreshenv
#conan profile detect
#conan create . `
#--build=missing `
#-o "&:shared=False"
#env:
#CONAN_USER_HOME: c:/cache
#CONAN_USER_HOME_SHORT: c:/cache/conan_shortpaths
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think maybe just leave in the TODO/ticket number but the commented code can be removed, we can always consult this diff to see what you had written I believe

@lia-viam
Copy link
Collaborator

lia-viam commented May 9, 2025

oh also were you able to run the release pipeline using this updated yaml?

@stuqdog
Copy link
Member Author

stuqdog commented May 9, 2025

oh also were you able to run the release pipeline using this updated yaml?

More or less! I didn't try running the release pipeline because it involves updating version number and I didn't want to do that and change the rules for when/how the release workflow runs and so on, but the release pipeline as it's written now was run under the Conan script to make sure it ran successfully, and I confirmed that cmake_install.cmake does exist at the build-conan/build path that we try to install from.

Copy link
Member

@acmorrow acmorrow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is working I think you should merge it more or less as is, though I have a few comments and questions here and there that I'd appreciate your taking a look at. I don't think any of them amount to something requiring another round of review.

Comment on lines 87 to 91
conan create . `
--build=missing `
-o "&:shared=False" `
-s:h compiler.cppstd=17 `
-s:h compiler.runtime=static
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect you need to keep:

            --build=missing `
            -o "&:shared=False" `

Comment on lines 55 to 58
- name: Install dependencies
uses: crazy-max/ghaction-chocolatey@v3
with:
args: install -y conan git
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still surprised you need this. Chocolatey is pre-installed on windows builders, from what I know. The tflite cpu build uses choco to install conan without doing anything special to install choco itself:

https://github.com/viam-modules/mlmodel-tflite/blob/main/bin/setup.ps1#L5

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you're probably right that it's not necessary! I kept it in just because we needed to do a choco install some way or another, it seemed totally innocuous to include, and I didn't want to do another round of testing to confirm. If you think there's a good reason to switch to a choco install invocation instead, let me know!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without knowing exactly what it does, it likely is innocuous until "crazy max"'s repo ends up being a vector for / victim of a supply chain attack.

At least when run on windows, all it actually seems to do is call choco with args:

https://github.com/crazy-max/ghaction-chocolatey/blob/master/src/main.ts#L22

So, from a risk / reward ratio it looks to me like it shouldn't stay. However, I'm fine with leaving it in for now since I know there has been a lot of back and forth on this and testing is slow. If you end up leaving it in, could you please file a ticket to remove it and add a TODO here before merging?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh that's a good point! this is reason enough to just make the change now imo, tested and it works.

Comment on lines +67 to +68
cmake . --preset conan-default
cmake --build --preset=conan-release --target ALL_BUILD install -j 8
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious: but why direct invocation of cmake here rather than conan build?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reasons that weren't entirely clear, the conan build invocation resulted in a number of undefined symbols coming from the libraries that we were importing in the CMakeLists.txt. @lia-viam and I spent a short time trying to debug and then just determined that the cmake invocation was good enough to get releases built. Will fix in RSDK-10666.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to remember if we were in fact using conan build or that was with conan create ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recall having issues with both, but there was so much back and forth and problem solving that it's hard for me to speak to with total confidence. at any rate I think this seems like a reasonable thing to revisit in the above-linked ticket.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe throw a # TODO(RSDK-10666): ... on there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

install(
IMPORTED_RUNTIME_ARTIFACTS viam_rust_utils
LIBRARY COMPONENT viam-cpp-sdk_runtime
FILES ${viam_rust_utils_file} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT viam-cpp-sdk_runtime
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. I may try it out myself after this merges to understand better, because it doesn't align with my understanding of how this ought to be working.

@@ -377,7 +381,7 @@ int main(int argc, char* argv[]) try {
});

// Print out the top 5 (or fewer) label/score pairs.
for (size_t i = 0; i != std::min(5UL, scored_labels.size()); ++i) {
for (size_t i = 0; i != std::min<std::size_t>(5UL, scored_labels.size()); ++i) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or just make the 5 a size_t? I'd expect std::min(size_t{5}, scored_labels.size()) to do the right thing.

# rust-utils doesn't build in CI on windows other than x86_64, so confirm that we're either not
# windows, or if we are windows that we're AMD64, or else that the user has provided their own
# build of rust_utils.
if (NOT WIN32 OR num_viam_rust_utils_files GREATER 0 OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this test just look only at num_viam_rust_utils_files now? I'd assume that if it is greater than zero then one was found and it should be used.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may be wrong, but is this a correct assumption? I thought num_viam_rust_utils_files was evaluated before we downloaded, in order to determine if we should download a rust_utils file. So the not WIN32 or AMD64 cases are important for the cases where the user hasn't provided a rust-utils file but we can download one for them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, you are right, I got myself tangled up. I was reacting to having complex logic to decide whether to use rust utils or build the stub here. It just feels like it would be better if all of that tortured logic was isolated up in the top level CMakeLists.txt and this file had a way of making a simple yes/no decision about whether to use the library or build the stubs.

Actually, I wonder if if (TARGET... is what I'm after: https://cmake.org/cmake/help/latest/command/if.html#target

Again, I know you are eager to land this, but could you please add a TODO (doesn't need a ticket, leave it for someone to clean up later).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

went ahead and switched to if (TARGET viam_rust_utils), confirmed that it builds correctly both with a user-provided rust-utils file and without one.

Copy link
Member

@acmorrow acmorrow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a few requests for additional comments / TODO's tickets before merge, but no need to post an update with those.

Comment on lines 55 to 58
- name: Install dependencies
uses: crazy-max/ghaction-chocolatey@v3
with:
args: install -y conan git
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without knowing exactly what it does, it likely is innocuous until "crazy max"'s repo ends up being a vector for / victim of a supply chain attack.

At least when run on windows, all it actually seems to do is call choco with args:

https://github.com/crazy-max/ghaction-chocolatey/blob/master/src/main.ts#L22

So, from a risk / reward ratio it looks to me like it shouldn't stay. However, I'm fine with leaving it in for now since I know there has been a lot of back and forth on this and testing is slow. If you end up leaving it in, could you please file a ticket to remove it and add a TODO here before merging?

Comment on lines +67 to +68
cmake . --preset conan-default
cmake --build --preset=conan-release --target ALL_BUILD install -j 8
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe throw a # TODO(RSDK-10666): ... on there.

# rust-utils doesn't build in CI on windows other than x86_64, so confirm that we're either not
# windows, or if we are windows that we're AMD64, or else that the user has provided their own
# build of rust_utils.
if (NOT WIN32 OR num_viam_rust_utils_files GREATER 0 OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, you are right, I got myself tangled up. I was reacting to having complex logic to decide whether to use rust utils or build the stub here. It just feels like it would be better if all of that tortured logic was isolated up in the top level CMakeLists.txt and this file had a way of making a simple yes/no decision about whether to use the library or build the stubs.

Actually, I wonder if if (TARGET... is what I'm after: https://cmake.org/cmake/help/latest/command/if.html#target

Again, I know you are eager to land this, but could you please add a TODO (doesn't need a ticket, leave it for someone to clean up later).

@stuqdog stuqdog merged commit 8d813ed into viamrobotics:main May 16, 2025
13 checks passed
@stuqdog stuqdog deleted the RSDK-10366-rust-utils-for-windows branch May 16, 2025 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants