-
Notifications
You must be signed in to change notification settings - Fork 135
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
Add support for compilation to windows #39
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @KolbyML - nice to see you here! Stoked to get another contributor on the project. I'm also pretty new to Rust, so i'm still learning the best way to go about things. I left a couple of thoughts here on your code that should be worth a stab at refactoring.
Also, I have zero windows experience - so I'm afraid I can't help much in that area. I agree it'd be nice to have trin support multiple platforms. It might also be useful to look into some circleci mechanism / build tool that can make sure all merged code is cross-platform compatible, since I don't have an easy way to test the code I write. But, given my limited windows experience/knowledge, I'll leave it up to @carver to see what he thinks is the best way to go about cross-platform support.
fn find_assigned_ip() -> Option<IpAddr> { | ||
let adapters = ipconfig::get_adapters().unwrap(); | ||
|
||
for adapter in adapters.iter() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For me, too many nested if statements can be a bit of a code smell. Especially in rust where they have quite a few handy mechanisms like .map()
/ .filter()
/ .is_empty()
. I'd give this another go and see if you can trade out some of these nested ifs for something "flatter".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I tried to work out a solution using a filter, but I just couldn't figure a good one out for this here is a picture of what I tried
You guys can problem come up with a better solution using a filter, but from what I could come up with using my limited knowledge of rust I think the first attempt I had at this problem was a lot cleaner, but maybe I just think that way cause I am just not as familiar with Rust.
Let me know what you think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would of course remove the prints by the way just there cause I was testing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also pretty new to rust, so it's tough for me to look at this and see a solution that's obviously better. Also, my compiler won't compile this code since I'm not on windows, which makes it harder since I usually like to tinker around with these things to see what does/doesn't work. This is the best I can do, but honestly, i'm not sure if it even works - but maybe it'll spark an idea on your end or maybe not.
ipconfig::get_adapters()
.filter(|adapter| !adapter.gateways().is_empty())
.map(|adapter| adapter.ip_addresses())
.flatten()
.find_map(|ip_addr| IpAddr::V4(_) = ip_addr)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks I will take a look at it again tomorrow, from just looking at it, it seems like it will work. I haven't seen flatten() before so I will read up on it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hopefully it works haha, yeah I hadn't seen it before either - but just came across it while browsing https://doc.rust-lang.org/std/iter/trait.Iterator.html#provided-methods hoping to stumble across something useful
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool! Maybe give the flat approach one more try - but if nothing works, I think the nested approach should be ok in this scenario.
Though, I'm a little nervous about the added complexity cross-platform support introduces to our code. If we go ahead, I don't have a way to test that the code I write is cross-compatible. But, maybe there's a CI solution that'll help?
OK - just found this - https://github.com/rust-embedded/cross - seems like it'll solve my concerns and is worth integrating into our workflow / ci if we go ahead with cross-platform support. @carver any thoughts?
fn find_assigned_ip() -> Option<IpAddr> { | ||
let adapters = ipconfig::get_adapters().unwrap(); | ||
|
||
for adapter in adapters.iter() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also pretty new to rust, so it's tough for me to look at this and see a solution that's obviously better. Also, my compiler won't compile this code since I'm not on windows, which makes it harder since I usually like to tinker around with these things to see what does/doesn't work. This is the best I can do, but honestly, i'm not sure if it even works - but maybe it'll spark an idea on your end or maybe not.
ipconfig::get_adapters()
.filter(|adapter| !adapter.gateways().is_empty())
.map(|adapter| adapter.ip_addresses())
.flatten()
.find_map(|ip_addr| IpAddr::V4(_) = ip_addr)
#[cfg(windows)] | ||
fn get_listener_result(ipc_path: &str) -> tokio::io::Result<uds_windows::UnixListener> { | ||
uds_windows::UnixListener::bind(ipc_path) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, I think this is definitely an improvement!
I will look into the first thing and also I will look into Cl. I know Bitcoins travis builds compile for all platforms, so we can probably do something like that with Cl |
Ok I just added a ci job to cross-compile the windows build |
In this case, I'd agree that the nested approach seems cleaner. CI's also looking good. But it seems now that you'll need to rebase this branch against master to get rid of the merge conflicts. Since, I'm fairly unfamiliar with windows and new to rust, I'd still like to get another pair of 👀 on this before merging if @carver or @SamWilsn get the chance |
Ok so I rewrote the CI to compile natively on Windows Server for the build because cross-compilation is no longer supported to windows because of the addition of RocksDB as it doesn't support the gnu toolchain for windows. Anyways compiling it natively is ideal for testing the windows build because then you can run cargo test on it, I was planning to do it later anyway. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sweet, it's great to have a windows build! Sorry it took so long to get my eyes on it. :/
Note that we often give a sort of "best-effort" approval on the team, which means "After you make the mentioned changes, using your best judgement, go ahead and merge. I will only review again if you ask me to." Request Changes is only used if I specifically want to comment on your new implementation before merging.
.circleci/config.yml
Outdated
# Force a failure on clippy warnings | ||
flags: "-- --deny warnings" | ||
with_cache: false | ||
# Run the commands without using the orbs since Clippy needs a little longer then 10 minutes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This note shocked me (that clippy needs so much time). After digging in, it looks like it's really the build time that is taking so long. The note would have been clearer to me if it said something like:
# Run the commands without using the orbs since Clippy needs a little longer then 10 minutes | |
# Run the sub-commands of the orb jobs separately, since the combined steps for Clippy can be long enough to trigger a timeout (>10min). Building the source is the main contributor. |
.circleci/config.yml
Outdated
- run: | ||
name: Install target toolchain | ||
command: rustup toolchain install stable-x86_64-pc-windows-msvc | ||
# Run the commands without using the orbs since Clippy needs a little longer then 10 minutes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same thing here, naturally.
command: rustup component add clippy | ||
- run: | ||
name: Run Clippy | ||
# Remove the first two lines of gitconfig as work around |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a workaround for what?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rust-lang/cargo#2078
rust-lang/cargo#2422
https://app.circleci.com/pipelines/github/carver/trin/147/workflows/d059c7c6-d759-4f79-a96c-99c16ba078ab/jobs/177
Here is some context on it.
Updating crates.io index
error: failed to get `base64` as a dependency of package `trin v0.1.0 (C:\Users\circleci\project)`
Caused by:
failed to load source for dependency `base64`
Caused by:
Unable to update registry `https://github.com/rust-lang/crates.io-index`
Caused by:
failed to fetch `https://github.com/rust-lang/crates.io-index`
Caused by:
failed to authenticate when downloading repository: ssh://git@github.com/rust-lang/crates.io-index
* attempted ssh-agent authentication, but no usernames succeeded: `git`
if the git CLI succeeds then `net.git-fetch-with-cli` may help here
https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli
Caused by:
error authenticating: failed connecting agent; class=Ssh (23)
So that was the "fix" I could find from googling it.
src/portalnet/socket.rs
Outdated
|
||
#[cfg(windows)] | ||
fn find_assigned_ip() -> Option<IpAddr> { | ||
let adapters = ipconfig::get_adapters().unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presumably unwrap is panicking here on a failure. I think we want to return None
instead.
So currently two parts of the code only support Unix. Most notably is the interfaces library and currently, the std::net library doesn't support Unix domain socket server on windows which was added to windows in 2018. So I wrote windows equivalent functions using libraries that support windows. I also added a circleci build to test if Trin builds to Windows, I assume we could also add a cross-compile for MacOS in the future.
I think Trin being cross-platform would be important in the future if it ever hits production. Also I use Windows as my host platform so it would be nice if I could build trin natively.
Original post which was way too long: https://hastebin.com/opewikujef.sql