From 380d38229dcf3cb99642e27ebf19e0ff2fdff227 Mon Sep 17 00:00:00 2001 From: core Date: Tue, 10 Oct 2023 09:21:37 -0400 Subject: [PATCH] windows cross-compilation --- .forgejo/workflows/tfclient.yml | 30 ++++++++++++- .idea/dataSources.xml | 2 +- build_windows.sh | 18 ++++++++ nebula-ffi/build.rs | 77 +++++++++++++++++++++++---------- 4 files changed, 102 insertions(+), 25 deletions(-) create mode 100755 build_windows.sh diff --git a/.forgejo/workflows/tfclient.yml b/.forgejo/workflows/tfclient.yml index 1a45d41..94a9ea8 100644 --- a/.forgejo/workflows/tfclient.yml +++ b/.forgejo/workflows/tfclient.yml @@ -52,4 +52,32 @@ jobs: command: build args: --release --bin tfclient - name: Upload binary - run: sshpass -p "${{ secrets.TRIFID_DLCDN_PASSWORD }}" rsync --mkpath -e 'ssh -p ${{ secrets.TRIFID_DLCDN_PORT }} -o StrictHostKeyChecking=no' target/release/tfclient ${{ secrets.TRIFID_DLCDN_USER }}@${{ secrets.TRIFID_DLCDN_IP }}:${{ secrets.TRIFID_DLCDN_PATH }}/tfclient/arm64/$GITHUB_SHA/tfclient \ No newline at end of file + run: sshpass -p "${{ secrets.TRIFID_DLCDN_PASSWORD }}" rsync --mkpath -e 'ssh -p ${{ secrets.TRIFID_DLCDN_PORT }} -o StrictHostKeyChecking=no' target/release/tfclient ${{ secrets.TRIFID_DLCDN_USER }}@${{ secrets.TRIFID_DLCDN_IP }}:${{ secrets.TRIFID_DLCDN_PATH }}/tfclient/arm64/$GITHUB_SHA/tfclient + build_win64: + runs_on: docker + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Setup Go toolchain + uses: actions/setup-go@v4 + with: + go-version: '1.20' + - name: Setup Rust toolchain + uses: https://github.com/actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - name: Install cross-compilation toolchain + run: rustup target add x86_64-pc-windows-gnu + - name: Install additional dependencies + run: apt update && apt-get install -y libclang-dev clang sshpass rsync + - name: Compile release binary + uses: https://github.com/actions-rs/cargo@v1 + with: + command: build + args: --release --bin tfclient --target x86_64-pc-windows-gnu + - name: Compile release bundle + run: ./build_windows.sh + - name: Upload binary + run: sshpass -p "${{ secrets.TRIFID_DLCDN_PASSWORD }}" rsync --mkpath -e 'ssh -p ${{ secrets.TRIFID_DLCDN_PORT }} -o StrictHostKeyChecking=no' target/release/x86_64-pc-windows-gnu/tfclient.zip ${{ secrets.TRIFID_DLCDN_USER }}@${{ secrets.TRIFID_DLCDN_IP }}:${{ secrets.TRIFID_DLCDN_PATH }}/tfclient/win64/$GITHUB_SHA/tfclient.zip \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml index 1fec8e5..7074b84 100644 --- a/.idea/dataSources.xml +++ b/.idea/dataSources.xml @@ -1,7 +1,7 @@ - + postgresql true org.postgresql.Driver diff --git a/build_windows.sh b/build_windows.sh new file mode 100755 index 0000000..6bddd87 --- /dev/null +++ b/build_windows.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -e +cargo build --target x86_64-pc-windows-gnu --release --bin tfclient +rm -rf target/x86_64-pc-windows-gnu/release/tfclient_dist/ +mkdir -p target/x86_64-pc-windows-gnu/release/tfclient_dist/ +cp target/x86_64-pc-windows-gnu/release/tfclient.exe target/x86_64-pc-windows-gnu/release/tfclient_dist/tfclient.exe +echo "[*] Downloading WinTun" +mkdir -p target/x86_64-pc-windows-gnu/release/tfclient_dist/dist/windows/ +wget https://www.wintun.net/builds/wintun-0.14.1.zip -O /tmp/wintun.zip +echo "[*] Unzipping WinTun" +unzip -d target/x86_64-pc-windows-gnu/release/tfclient_dist/dist/windows/ /tmp/wintun.zip +echo "[*] Copying nebula.dll" +cp target/x86_64-pc-windows-gnu/release/nebula.dll target/x86_64-pc-windows-gnu/release/tfclient_dist/nebula.dll +echo "[*] Building zip bundle" +cd target/x86_64-pc-windows-gnu/release +zip -r tfclient.zip tfclient_dist/* +cd ../../../ +echo "[*] Windows production build success!" diff --git a/nebula-ffi/build.rs b/nebula-ffi/build.rs index f17d04d..d6167fe 100644 --- a/nebula-ffi/build.rs +++ b/nebula-ffi/build.rs @@ -3,6 +3,22 @@ use std::path::PathBuf; use bindgen::CargoCallbacks; use std::path::Path; +fn get_cargo_target_dir() -> Result> { + let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR")?); + let profile = std::env::var("PROFILE")?; + let mut target_dir = None; + let mut sub_path = out_dir.as_path(); + while let Some(parent) = sub_path.parent() { + if parent.ends_with(&profile) { + target_dir = Some(parent); + break; + } + sub_path = parent; + } + let target_dir = target_dir.ok_or("not found")?; + Ok(target_dir.to_path_buf()) +} + fn main() { // Find compiler: @@ -29,7 +45,7 @@ fn main() { let out_dir = env::var("OUT_DIR").unwrap(); let out_path = PathBuf::from(out_dir); - let out_file = LIBRARY_PREFIX.to_owned() + "nebula" + LIBRARY_EXTENSION; + let out_file = lib_name(); let out = out_path.join(out_file); let mut command = process::Command::new(compiler); @@ -49,6 +65,7 @@ fn main() { } println!("Go compile success"); + copy_if_windows(); print_link(); println!("cargo:rustc-link-search=native={}", env::var("OUT_DIR").unwrap()); @@ -63,7 +80,7 @@ fn main() { println!("Generating bindings"); let bindings = bindgen::Builder::default() - .header(out_path.join(LIBRARY_PREFIX.to_owned() + "nebula.h").display().to_string()) + .header(out_path.join(header_name()).display().to_string()) .parse_callbacks(Box::new(CargoCallbacks)) .generate() .expect("Error generating CFFI bindings"); @@ -74,15 +91,30 @@ fn main() { .expect("Couldn't write bindings!"); } -#[cfg(target_family = "unix")] -const LIBRARY_EXTENSION: & str = ".a"; -#[cfg(target_family = "unix")] -const LIBRARY_PREFIX: & str = "lib"; +fn lib_name() -> String { + if env::var("CARGO_CFG_TARGET_FAMILY").unwrap() == "windows" { + "nebula.dll".to_string() + } else { + "libnebula.a".to_string() + } +} +fn header_name() -> String { + if env::var("CARGO_CFG_TARGET_FAMILY").unwrap() == "windows" { + "nebula.h".to_string() + } else { + "libnebula.h".to_string() + } +} -#[cfg(target_family = "windows")] -const LIBRARY_EXTENSION: &str = ".dll"; -#[cfg(target_family = "windows")] -const LIBRARY_PREFIX: &str = ""; +fn copy_if_windows() { + let target_dir = get_cargo_target_dir().unwrap(); + let target_file = target_dir.join(lib_name()); + let out_dir = env::var("OUT_DIR").unwrap(); + let out_path = PathBuf::from(out_dir); + let out_file = lib_name(); + let out = out_path.join(out_file); + std::fs::copy(out, target_file).unwrap(); +} fn goarch() -> String { match env::var("CARGO_CFG_TARGET_ARCH").unwrap().as_str() { @@ -111,19 +143,18 @@ fn goos() -> String { }.to_string() } -#[cfg(target_family = "unix")] fn print_link() { - println!("cargo:rustc-link-lib=static=nebula"); + if env::var("CARGO_CFG_TARGET_FAMILY").unwrap() == "windows" { + println!("cargo:rustc-link-lib=dylib=nebula"); + } else { + println!("cargo:rustc-link-lib=static=nebula"); + } } -#[cfg(target_family = "unix")] + fn link_type() -> String { - "c-archive".to_string() -} -#[cfg(target_family = "windows")] -fn print_link() { - println!("cargo:rustc-link-lib=dylib=nebula"); -} -#[cfg(target_family = "windows")] -fn link_type() -> String { - "c-shared".to_string() -} + if env::var("CARGO_CFG_TARGET_FAMILY").unwrap() == "windows" { + "c-shared".to_string() + } else { + "c-archive".to_string() + } +} \ No newline at end of file