Skip to content
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

feat: support build on windows #47

Merged
merged 1 commit into from
Mar 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ rustflags = ["-C", "target-feature=+crt-static"]
[target.riscv64gc-unknown-linux-gnu]
linker = "riscv64-linux-gnu-gcc"
rustflags = ["-C", "target-feature=+crt-static"]

[target.x86_64-pc-windows-msvc]
linker = "link"
rustflags = ["-C", "target-feature=+crt-static"]
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,5 @@ web/front/*.sw?
# dist
server/web/dist
client/web/dist

/libcs/msvc-build/target
27 changes: 27 additions & 0 deletions BuildOnWindows.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# 构建指南(Windows)

## 1.环境准备
### webrtc编译环境(webrtc版本差异会导致所依赖的msvc工具差异):
(google搜索Windows编译webrtc能找到详细步骤)</br>
安装visual studio2022,</br>
MSVC版本: v143, </br>
Windows11 SDK(10.0.22621.0) </br>
启用C++ ATL和MFC支持 </br>
勾选【基于Windows的clang(llvm)工具】


### msquic编译环境:
[msquic构建文档](https://github.com/microsoft/msquic/blob/main/docs/BUILD.md) </br>
根据构建文档安装依赖项(.Net Core,Cmake,Perl)


### 本项目编译所需环境:
配置cl(msvc编译器)工具环境,使其能在powershell中调用</br>
配置clang(llvm)工具环境,使其能在powershell中调用</br>
配置INCLUDE和LIB环境,分别包含msvc工具的include/lib目录,和Windows SDK的include/lib目录下的所有子目录
安装powershell 7


## 编译
启动powershell 7,在powershell执行根目录下的build.ps1构建脚本</br>
(如果是首次构建,为了初始化msquic项目,需要在管理员模式执行powershell 7)
3 changes: 2 additions & 1 deletion bin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ description.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
libloading = "0.8.2"
clap = { version = "4.4.17", features = ["derive"] }
env_logger = "0.10.1"
log = "0.4.20"
Expand All @@ -23,4 +24,4 @@ url = "2.5.0"
webrtc = "0.9.0"
serde_yaml = "0.9.30"
notify = { version = "6.1.1", default-features = false, features = ["macos_kqueue"] }
futures = "0.3.30"
futures = "0.3.30"
18 changes: 13 additions & 5 deletions bin/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ use std::process::Command;

fn main() {
let target = env::var("TARGET").unwrap();
println!("cargo:rerun-if-changed=libcs/release/{target}");
println!("cargo:rustc-link-search=libcs/release/{target}");
println!("cargo:rustc-link-lib=static=cs");
println!("cargo:rustc-link-lib=static=webrtc");
println!("cargo:rustc-link-lib=static=msquic");
let os = env::var("CARGO_CFG_TARGET_OS").unwrap();
match os.as_str() {
"linux" => {
println!("cargo:rerun-if-changed=libcs/release/{target}");
println!("cargo:rustc-link-search=libcs/release/{target}");
println!("cargo:rustc-link-lib=static=cs");
println!("cargo:rustc-link-lib=static=webrtc");
println!("cargo:rustc-link-lib=static=msquic");
let output = Command::new(format!(
"{}-linux-gnu-gcc",
env::var("CARGO_CFG_TARGET_ARCH").unwrap()
Expand All @@ -42,6 +42,11 @@ fn main() {
println!("cargo:rustc-link-lib=static=stdc++");
}
"macos" => {
println!("cargo:rerun-if-changed=libcs/release/{target}");
println!("cargo:rustc-link-search=libcs/release/{target}");
println!("cargo:rustc-link-lib=static=cs");
println!("cargo:rustc-link-lib=static=webrtc");
println!("cargo:rustc-link-lib=static=msquic");
println!("cargo:rustc-link-lib=dylib=resolv");
println!("cargo:rustc-link-lib=dylib=c++");
println!("cargo:rustc-link-lib=dylib=c++abi");
Expand All @@ -51,6 +56,9 @@ fn main() {
println!("cargo:rustc-link-lib=framework=CoreMedia");
println!("cargo:rustc-link-lib=framework=AVFoundation");
}
"windows"=>{
//do nothing
}
os => {
panic!("Unsupported OS: {}", os)
}
Expand Down
97 changes: 69 additions & 28 deletions bin/src/cs_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,28 @@

/* automatically generated by rust-bindgen 0.69.1 */

use std::env::temp_dir;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
#[repr(C)]
pub struct __BindgenComplex<T> {
pub re: T,
pub im: T,
}

pub type wchar_t = ::std::os::raw::c_int;
pub type max_align_t = f64;

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct _GoString_ {
pub p: *const ::std::os::raw::c_char,
pub n: isize,
}

#[test]
fn bindgen_test_layout__GoString_() {
const UNINIT: ::std::mem::MaybeUninit<_GoString_> = ::std::mem::MaybeUninit::uninit();
Expand All @@ -48,23 +56,24 @@ fn bindgen_test_layout__GoString_() {
unsafe { ::std::ptr::addr_of!((*ptr).p) as usize - ptr as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(_GoString_),
"::",
stringify!(p)
"Offset of field: ",
stringify!(_GoString_),
"::",
stringify!(p)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).n) as usize - ptr as usize },
8usize,
concat!(
"Offset of field: ",
stringify!(_GoString_),
"::",
stringify!(n)
"Offset of field: ",
stringify!(_GoString_),
"::",
stringify!(n)
)
);
}

pub type GoInt8 = ::std::os::raw::c_schar;
pub type GoUint8 = ::std::os::raw::c_uchar;
pub type GoInt16 = ::std::os::raw::c_short;
Expand Down Expand Up @@ -108,20 +117,20 @@ fn bindgen_test_layout_GoInterface() {
unsafe { ::std::ptr::addr_of!((*ptr).t) as usize - ptr as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(GoInterface),
"::",
stringify!(t)
"Offset of field: ",
stringify!(GoInterface),
"::",
stringify!(t)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).v) as usize - ptr as usize },
8usize,
concat!(
"Offset of field: ",
stringify!(GoInterface),
"::",
stringify!(v)
"Offset of field: ",
stringify!(GoInterface),
"::",
stringify!(v)
)
);
}
Expand Down Expand Up @@ -150,36 +159,68 @@ fn bindgen_test_layout_GoSlice() {
unsafe { ::std::ptr::addr_of!((*ptr).data) as usize - ptr as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(GoSlice),
"::",
stringify!(data)
"Offset of field: ",
stringify!(GoSlice),
"::",
stringify!(data)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).len) as usize - ptr as usize },
8usize,
concat!(
"Offset of field: ",
stringify!(GoSlice),
"::",
stringify!(len)
"Offset of field: ",
stringify!(GoSlice),
"::",
stringify!(len)
)
);
assert_eq!(
unsafe { ::std::ptr::addr_of!((*ptr).cap) as usize - ptr as usize },
16usize,
concat!(
"Offset of field: ",
stringify!(GoSlice),
"::",
stringify!(cap)
"Offset of field: ",
stringify!(GoSlice),
"::",
stringify!(cap)
)
);
}


#[cfg(not(target_os = "windows"))]
extern "C" {
pub fn RunServer(args: GoSlice);
}

#[cfg(not(target_os = "windows"))]
extern "C" {
pub fn RunClient(args: GoSlice);
}

#[cfg(target_os = "windows")]
const DLL_DATA: &'static [u8] = include_bytes!("../../libcs/msvc-build/target/gt.dll");

#[cfg(target_os = "windows")]
pub fn InitGtDll() {
let mut dll_file = File::create( temp_dir().join("gt.dll")).expect("Failed to create DLL file");
dll_file.write_all(DLL_DATA).expect("Failed to write DLL data to file");
}

#[cfg(target_os = "windows")]
fn RunServer(args: GoSlice) {
unsafe {
let lib = libloading::Library::new( temp_dir().join("gt.dll")).unwrap();
let func: libloading::Symbol<unsafe extern fn(GoSlice)> = lib.get(b"RunServer").unwrap();
func(args);
}
}

#[cfg(target_os = "windows")]
fn RunClient(args: GoSlice) {
unsafe {
let lib = libloading::Library::new( temp_dir().join("gt.dll")).unwrap();
let func: libloading::Symbol<unsafe extern fn(GoSlice)> = lib.get(b"RunClient").unwrap();
func(args);
}
}
5 changes: 5 additions & 0 deletions bin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ enum Commands {
}

fn main() {
#[cfg(target_os = "windows")]
{
cs::InitGtDll();
}

env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
let cli = Cli::parse();
if let Some(signal) = cli.signal {
Expand Down
92 changes: 92 additions & 0 deletions build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
$WORD_DIR = $PSScriptRoot
$WEBRTC_DIR="$WORD_DIR/libcs/dep/_google-webrtc"
$MSQUIC_DIR="$WORD_DIR/libcs/dep/_msquic"
$WEBRTC_OUT_DIR="$WEBRTC_DIR/src/out/release/obj"
$MSQUIC_OUT_DIR="$MSQUIC_DIR/build/windows/x64_schannel/obj/Release"
$MSVC_BUILD_DIR="$WORD_DIR/libcs/msvc-build"
$RUST_TARGET_DIR="$WORD_DIR/target/x86_64-pc-windows-msvc/release"

$env:CC="clang"
$env:CXX="clang++"
$env:CXXFLAGS="-I$WEBRTC_DIR/src -I$WEBRTC_DIR/src/third_party/abseil-cpp -I$MSQUIC_DIR/src/inc -std=c++17 -DWEBRTC_WIN -DQUIC_API_ENABLE_PREVIEW_FEATURES -DNOMINMAX"
$env:CGO_LDFLAGS="-L$MSQUIC_DIR/build/windows/x64_schannel/obj/Release -L$WEBRTC_DIR/src/out/release/obj -lmsquic.lib -lwebrtc.lib"
$env:CARGO_CFG_TARGET_OS="windows"

Set-Location $WORD_DIR
function complie_webrtc{
Set-Location "$WEBRTC_DIR/src"
gn gen out/release --args="clang_use_chrome_plugins=false is_clang=true enable_libaom=false is_component_build=false is_debug=false libyuv_disable_jpeg=true libyuv_include_tests=false rtc_build_examples=false rtc_build_tools=false rtc_enable_grpc=false rtc_enable_protobuf=false rtc_include_builtin_audio_codecs=false rtc_include_dav1d_in_internal_decoder_factory=false rtc_include_ilbc=false rtc_include_internal_audio_device=false rtc_include_tests=false rtc_use_h264=false rtc_use_x11=false treat_warnings_as_errors=false use_custom_libcxx=false use_gold=false use_lld=true use_rtti=true use_sysroot=false"
ninja -C out/release
Set-Location $WORD_DIR
}
if (!(Test-Path -Path "$WEBRTC_OUT_DIR/webrtc.lib")){
complie_webrtc
}


function complie_msquic{
Set-Location $MSQUIC_DIR
&./scripts/prepare-machine.ps1
&./scripts/build.ps1 -Config Release -Clean -Static -DisableTest -DisableTools -StaticCRT
Set-Location $WORD_DIR
}
if (!(Test-Path -Path "$MSQUIC_OUT_DIR/msquic.lib")){
if (!([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Host "请以管理员权限运行此脚本"
exit
}
complie_msquic
}


function release_gt_dylib{
Set-Location ./libcs
go build -tags release -trimpath -ldflags "-s -w" -buildmode=c-archive -o release/gt.lib ./lib/export
Set-Location ./msvc-build

# 检查target目录是否存在
$directory = "$WORD_DIR/libcs/msvc-build/target"
if (-not (Test-Path -Path $directory -PathType Container)) {
New-Item -Path $directory -ItemType Directory -Force
Write-Host "目录已创建:$directory"
} else {
Write-Host "目录已存在:$directory"
}

cl /LD /MT /Fe:./target/gt.dll gt.cpp /link /DEF:gt.def "../release/gt.lib" "$MSQUIC_OUT_DIR\msquic.lib" "$WEBRTC_OUT_DIR\webrtc.lib" ntdll.lib
Set-Location $WORD_DIR
}
function release_gt_lib{
Set-Location ./libcs
go build -tags release -trimpath -ldflags "-s -w" -buildmode=c-archive -o release/gt.lib ./lib/export
Set-Location ./msvc-build

# 检查target目录是否存在
$directory = "$WORD_DIR/libcs/msvc-build/target"
if (-not (Test-Path -Path $directory -PathType Container)) {
New-Item -Path $directory -ItemType Directory -Force
Write-Host "目录已创建:$directory"
} else {
Write-Host "目录已存在:$directory"
}
Set-Location $WORD_DIR
}
release_gt_dylib


function release_gt_exe{
cargo build --target x86_64-pc-windows-msvc -r
}
release_gt_exe


function release_gt_with_dll{
# 设置要打包的文件和文件夹路径
$filesToCompress = @("$RUST_TARGET_DIR/gt.exe", "$MSVC_BUILD_DIR/target/gt.dll")

# 设置自解压文件的输出路径和名称
$outputFile = "$RUST_TARGET_DIR/gt-manager.exe"

# 使用 7-Zip 创建自解压文件
& 7z a -sfx"D:\Tools\7-Zip\7z.sfx" $outputFile $filesToCompress
}
2 changes: 2 additions & 0 deletions libcs/conn/msquic/quic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,10 @@ const char *StringStatus(QUIC_STATUS status) {
return "stream limit reached";
case QUIC_STATUS_ALPN_IN_USE:
return "alpn in use";
#ifndef _WIN64
case QUIC_STATUS_ADDRESS_NOT_AVAILABLE:
return "address not available";
#endif
case QUIC_STATUS_CLOSE_NOTIFY:
return "close notify";
case QUIC_STATUS_BAD_CERTIFICATE:
Expand Down
Loading
Loading