for better OOB experience, I' suggest to stick with cargo (unless you are author of build tools who want to integrate rustc to your tool.)
cargo is not only a build tool, but also a package manager. it gives you smooth experience to use libraries from crates.io, which is the default registry of cargo, but you can use custom registries if needed.
with cargo, using third party crates is almost as easy as using the standard library. using your original example:
> cargo new hello
> cd hello
> cargo add windows-sys --features Win32_Foundation
> notepad src/main.rs
// main.rs
use windows_sys::Win32::Foundation::{GetLastError, SetLastError};
fn main() {
unsafe {
SetLastError(1234);
assert_eq!(GetLastError(), 1234);
}
}
> cargo run
there's a small inconvenience when it comes to the windows/windows-sys crates, namely, you must enable subsets of APIs explicitly using features, and there's a ton of them. but at least, microsoft provides a search interface:
because the Windows API set is so large, even the windows-sys crate, which contains only declarations of FFI types and function signatures, and linkage information, the compile time would be unmanageable if all the APIs are enabled unconditionally. bummer, but it is what it is. it's a trade off for the completeness of the full Windows API set.
using rustc directly is possible, but it won't be as easy, unless your code is very simple, e.g., only uses the standard library (i.e. std, alloc, core). anything beyond that is rather involved, e.g., you can pass the --verbose flag to see the the full command line of how rustc is invoked.
notably, direct access of OS APIs (bypasisng the standard library) needs to use third party crates, e.g. the libc crate, or even lower level, like nix for Posix systems, windows-sys for Windows.