From 988eb4627076bcc31af075b4e5823a73d9ed08a1 Mon Sep 17 00:00:00 2001 From: Lukas Fittl Date: Mon, 1 Jan 2024 12:05:53 -0800 Subject: [PATCH 1/4] Add support for running on Windows --- .gitattributes | 1 + .github/workflows/main.yml | 7 +++++-- Cargo.lock | 2 ++ Cargo.toml | 2 ++ build.rs | 41 +++++++++++++++++++++++++------------- libpg_query | 2 +- 6 files changed, 38 insertions(+), 17 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b11351b --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +tests/data/* binary diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 37595ea..783c1ef 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,14 +11,17 @@ name: Continuous integration jobs: ci: env: - RUSTFLAGS: ${{ matrix.rust == 'nightly' && '-Z sanitizer=leak' || '' }} - runs-on: ubuntu-latest + RUSTFLAGS: ${{ matrix.rust == 'nightly' && matrix.os == 'ubuntu-latest' && '-Z sanitizer=leak' || '' }} strategy: fail-fast: false matrix: rust: - stable - nightly + os: + - ubuntu-latest + - windows-latest + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 diff --git a/Cargo.lock b/Cargo.lock index fde4156..e4e5e80 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -393,9 +393,11 @@ name = "pg_query" version = "5.0.0" dependencies = [ "bindgen", + "cc", "clippy", "easy-parallel", "fs_extra", + "glob", "itertools", "pretty_assertions", "prost", diff --git a/Cargo.toml b/Cargo.toml index c73e21a..f8399ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,8 @@ bindgen = "0.66.1" clippy = { version = "0.0.302", optional = true } prost-build = "0.10.4" fs_extra = "1.2.0" +cc = "1.0.83" +glob = "0.3.1" [dev-dependencies] easy-parallel = "3.2.0" diff --git a/build.rs b/build.rs index 65765d0..9a68551 100644 --- a/build.rs +++ b/build.rs @@ -2,6 +2,7 @@ #![cfg_attr(feature = "clippy", plugin(clippy))] use fs_extra::dir::CopyOptions; +use glob::glob; use std::env; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; @@ -12,12 +13,11 @@ static LIBRARY_NAME: &str = "pg_query"; fn main() -> Result<(), Box> { let out_dir = PathBuf::from(env::var("OUT_DIR")?); let build_path = Path::new(".").join(SOURCE_DIRECTORY); - let makefile_path = build_path.join("Makefile"); let out_header_path = out_dir.join(LIBRARY_NAME).with_extension("h"); let out_protobuf_path = out_dir.join("protobuf"); + let target = env::var("TARGET").unwrap(); // Configure cargo through stdout - println!("cargo:rerun-if-changed={}", makefile_path.display()); // Includes version number println!("cargo:rustc-link-search=native={}", out_dir.display()); println!("cargo:rustc-link-lib=static={LIBRARY_NAME}"); @@ -35,18 +35,31 @@ fn main() -> Result<(), Box> { fs_extra::copy_items(&source_paths, &out_dir, ©_options)?; // Compile the C library. - let mut make = Command::new("make"); - - make.env_remove("PROFILE").arg("-C").arg(&out_dir).arg("build"); - - if env::var("PROFILE").unwrap() == "debug" { - make.arg("DEBUG=1"); - } - - let status = make.stdin(Stdio::null()).stdout(Stdio::inherit()).stderr(Stdio::inherit()).status()?; - - if !status.success() { - return Err("libpg_query compilation failed".into()); + if target.contains("msvc") { + // Rust on Windows may not have "make" or "nmake" installed + cc::Build::new() + .files(glob(out_dir.join("src/*.c").to_str().unwrap()).unwrap().map(|p| p.unwrap())) + .files(glob(out_dir.join("src/postgres/*.c").to_str().unwrap()).unwrap().map(|p| p.unwrap())) + .file(out_dir.join("vendor/protobuf-c/protobuf-c.c")) + .file(out_dir.join("vendor/xxhash/xxhash.c")) + .file(out_dir.join("protobuf/pg_query.pb-c.c")) + .include(out_dir.join(".")) + .include(out_dir.join("./vendor")) + .include(out_dir.join("./src/postgres/include")) + .include(out_dir.join("./src/include")) + .include(out_dir.join("./src/postgres/include/port/win32")) + .include(out_dir.join("./src/postgres/include/port/win32_msvc")) + .compile(LIBRARY_NAME); + } else { + let mut make = Command::new("make"); + make.env_remove("PROFILE").arg("-C").arg(&out_dir).arg("build"); + if env::var("PROFILE").unwrap() == "debug" { + make.arg("DEBUG=1"); + } + let status = make.stdin(Stdio::null()).stdout(Stdio::inherit()).stderr(Stdio::inherit()).status()?; + if !status.success() { + return Err("libpg_query compilation failed".into()); + } } // Generate bindings for Rust diff --git a/libpg_query b/libpg_query index 2a00188..1ec3894 160000 --- a/libpg_query +++ b/libpg_query @@ -1 +1 @@ -Subproject commit 2a0018867c20011fc7166767083c05965241140b +Subproject commit 1ec38940e5c6f09a4c1d17a46d839a881c4f2db7 From dfd52b8ca33119dc2597b7219ab99c9f547b4721 Mon Sep 17 00:00:00 2001 From: Lukas Fittl Date: Sat, 6 Jan 2024 21:42:23 -0800 Subject: [PATCH 2/4] Always build C library using "cc" crate This avoids unnecessarily going through the Makefile logic, which isn't necessary when we have build.rs. --- build.rs | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/build.rs b/build.rs index 9a68551..355f525 100644 --- a/build.rs +++ b/build.rs @@ -35,32 +35,28 @@ fn main() -> Result<(), Box> { fs_extra::copy_items(&source_paths, &out_dir, ©_options)?; // Compile the C library. - if target.contains("msvc") { - // Rust on Windows may not have "make" or "nmake" installed - cc::Build::new() - .files(glob(out_dir.join("src/*.c").to_str().unwrap()).unwrap().map(|p| p.unwrap())) - .files(glob(out_dir.join("src/postgres/*.c").to_str().unwrap()).unwrap().map(|p| p.unwrap())) - .file(out_dir.join("vendor/protobuf-c/protobuf-c.c")) - .file(out_dir.join("vendor/xxhash/xxhash.c")) - .file(out_dir.join("protobuf/pg_query.pb-c.c")) - .include(out_dir.join(".")) - .include(out_dir.join("./vendor")) - .include(out_dir.join("./src/postgres/include")) - .include(out_dir.join("./src/include")) - .include(out_dir.join("./src/postgres/include/port/win32")) - .include(out_dir.join("./src/postgres/include/port/win32_msvc")) - .compile(LIBRARY_NAME); - } else { - let mut make = Command::new("make"); - make.env_remove("PROFILE").arg("-C").arg(&out_dir).arg("build"); - if env::var("PROFILE").unwrap() == "debug" { - make.arg("DEBUG=1"); - } - let status = make.stdin(Stdio::null()).stdout(Stdio::inherit()).stderr(Stdio::inherit()).status()?; - if !status.success() { - return Err("libpg_query compilation failed".into()); + let mut build = cc::Build::new(); + build + .files(glob(out_dir.join("src/*.c").to_str().unwrap()).unwrap().map(|p| p.unwrap())) + .files(glob(out_dir.join("src/postgres/*.c").to_str().unwrap()).unwrap().map(|p| p.unwrap())) + .file(out_dir.join("vendor/protobuf-c/protobuf-c.c")) + .file(out_dir.join("vendor/xxhash/xxhash.c")) + .file(out_dir.join("protobuf/pg_query.pb-c.c")) + .include(out_dir.join(".")) + .include(out_dir.join("./vendor")) + .include(out_dir.join("./src/postgres/include")) + .include(out_dir.join("./src/include")) + .warnings(false); // Avoid unnecessary warnings, as they are already considered as part of libpg_query development + if env::var("PROFILE").unwrap() == "debug" || env::var("DEBUG").unwrap() == "1" { + build.define("USE_ASSERT_CHECKING", None); + } + if target.contains("windows") { + build.include(out_dir.join("./src/postgres/include/port/win32")); + if target.contains("msvc") { + build.include(out_dir.join("./src/postgres/include/port/win32_msvc")); } } + build.compile(LIBRARY_NAME); // Generate bindings for Rust bindgen::Builder::default() From e7836dce9550da2bd62fe72da8c5412bb89c7a9f Mon Sep 17 00:00:00 2001 From: Lukas Fittl Date: Sun, 7 Jan 2024 10:08:46 -0800 Subject: [PATCH 3/4] Don't use actions-rs/toolchain@v1, it's unmaintained See https://github.com/actions-rs/toolchain/issues/216 --- .github/workflows/main.yml | 61 +++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 783c1ef..6979aeb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,7 +24,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: recursive @@ -34,39 +34,51 @@ jobs: path: | ~/.cargo/registry ~/.cargo/git - key: ${{ runner.os }}-${{ matrix.backend }}-cargo-${{ hashFiles('**/Cargo.toml') }} + key: ${{ matrix.os }}-${{ matrix.rust }}-cargo-${{ hashFiles('**/Cargo.toml') }} + + - name: Install rustup if needed + run: | + if ! command -v rustup &>/dev/null; then + curl --proto '=https' --tlsv1.2 --retry 10 --retry-connrefused --location --silent --show-error --fail "https://sh.rustup.rs" | sh -s -- --default-toolchain none -y + echo "${CARGO_HOME:-$HOME/.cargo}/bin" >> $GITHUB_PATH + fi + if: runner.os != 'Windows' + shell: bash - name: Install toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: ${{ matrix.rust }} - override: true + run: rustup toolchain install ${{ matrix.rust }} --profile minimal --no-self-update + shell: bash + + - name: Default to nightly if requested + run: rustup default nightly + if: matrix.rust == 'nightly' - name: Build pg_query - uses: actions-rs/cargo@v1 - with: - command: build + run: cargo build - name: Run tests - uses: actions-rs/cargo@v1 - with: - command: test + run: cargo test check_style: name: Check file formatting and style runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: recursive - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal - components: clippy, rustfmt - override: true + - name: Install rustup if needed + run: | + if ! command -v rustup &>/dev/null; then + curl --proto '=https' --tlsv1.2 --retry 10 --retry-connrefused --location --silent --show-error --fail "https://sh.rustup.rs" | sh -s -- --default-toolchain none -y + echo "${CARGO_HOME:-$HOME/.cargo}/bin" >> $GITHUB_PATH + fi + if: runner.os != 'Windows' + shell: bash + + - name: Install toolchain + run: rustup toolchain install stable --component clippy --component rustfmt --profile minimal --no-self-update + shell: bash - name: Cache cargo registry uses: actions/cache@v2 @@ -77,12 +89,7 @@ jobs: key: clippy-cargo-${{ hashFiles('**/Cargo.toml') }} - name: Check file formatting - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check + run: cargo fmt --all -- --check - name: Run clippy - uses: actions-rs/cargo@v1 - with: - command: clippy + run: cargo clippy From 462988d1f4a4df6e095995c3bdacaba89243b9aa Mon Sep 17 00:00:00 2001 From: Lukas Fittl Date: Sun, 7 Jan 2024 10:09:19 -0800 Subject: [PATCH 4/4] On Windows, test 64-bit GNU and 32-bit MSVC as well --- .github/workflows/main.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6979aeb..b8a55e3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,6 +21,11 @@ jobs: os: - ubuntu-latest - windows-latest + include: + - rust: stable-x86_64-pc-windows-gnu + os: windows-latest + - rust: stable-i686-pc-windows-msvc + os: windows-latest runs-on: ${{ matrix.os }} steps: