From 1cbed9eec8dd8ac60c58f73d69c2bad35068d629 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Mon, 3 Nov 2025 07:29:44 +0100 Subject: [PATCH 1/2] Add Cygwin support Things are like with Windows+gnu, except the "meson-paths" logic is always used, and shared libs are prefixed with "cyg". --- src/build.rs | 2 +- src/build_targets.rs | 31 ++++++++++++++++++++++++++++--- src/install.rs | 2 +- src/target.rs | 2 +- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/build.rs b/src/build.rs index c758fca..d560fd1 100644 --- a/src/build.rs +++ b/src/build.rs @@ -182,7 +182,7 @@ fn build_implib_file( target: &target::Target, targetdir: &Path, ) -> anyhow::Result<()> { - if target.os == "windows" { + if target.os == "windows" || target.os == "cygwin" { ws.gctx().shell().status("Building", "implib")?; let def_path = targetdir.join(format!("{name}.def")); diff --git a/src/build_targets.rs b/src/build_targets.rs index 5628807..f3ba700 100644 --- a/src/build_targets.rs +++ b/src/build_targets.rs @@ -131,7 +131,9 @@ impl BuildTargets { pub fn shared_output_file_name(&self) -> Option { match self.lib_type() { LibType::Windows => { - if self.shared_lib.is_some() + if self.target.os == "cygwin" { + Some(format!("cyg{}.dll", self.name).into()) + } else if self.shared_lib.is_some() && self.use_meson_naming_convention && self.target.env == "gnu" { @@ -174,7 +176,7 @@ impl FileNames { let pdb = Some(targetdir.join(format!("lib{lib_name}.dSYM"))); (shared_lib, static_lib, None, pdb, None) } - "windows" => { + "windows" | "cygwin" => { let shared_lib = targetdir.join(format!("{lib_name}.dll")); let def = targetdir.join(format!("{lib_name}.def")); @@ -190,7 +192,7 @@ impl FileNames { (shared_lib, static_lib, Some(impl_lib), pdb, Some(def)) } else { let static_lib = targetdir.join(format!("lib{lib_name}.a")); - let impl_lib = if use_meson_naming_convention { + let impl_lib = if use_meson_naming_convention || target.os == "cygwin" { targetdir.join(format!("lib{lib_name}.dll.a")) } else { targetdir.join(format!("{lib_name}.dll.a")) @@ -326,4 +328,27 @@ mod test { assert_eq!(file_names.unwrap(), expected); } + + #[test] + fn cygwin() { + let target = Target { + is_target_overridden: false, + arch: String::from(""), + os: String::from("cygwin"), + env: String::from(""), + cfg: Vec::new(), + target: None, + }; + let file_names = FileNames::from_target(&target, "ferris", Path::new("/foo/bar"), false); + + let expected = FileNames { + static_lib: PathBuf::from("/foo/bar/libferris.a"), + shared_lib: PathBuf::from("/foo/bar/ferris.dll"), + impl_lib: Some(PathBuf::from("/foo/bar/libferris.dll.a")), + debug_info: None, + def: Some(PathBuf::from("/foo/bar/ferris.def")), + }; + + assert_eq!(file_names.unwrap(), expected); + } } diff --git a/src/install.rs b/src/install.rs index f093af0..cf65549 100644 --- a/src/install.rs +++ b/src/install.rs @@ -107,7 +107,7 @@ impl LibType { | ("emscripten", _) | ("hurd", _) => LibType::So, ("macos", _) | ("ios", _) | ("tvos", _) | ("visionos", _) => LibType::Dylib, - ("windows", _) => LibType::Windows, + ("windows", _) | ("cygwin", _) => LibType::Windows, _ => unimplemented!("The target {}-{} is not supported yet", os, env), } } diff --git a/src/target.rs b/src/target.rs index a622257..a5fe610 100644 --- a/src/target.rs +++ b/src/target.rs @@ -133,7 +133,7 @@ impl Target { lines.push(line); // Enable larger LC_RPATH and install_name entries lines.push("-Wl,-headerpad_max_install_names".to_string()); - } else if os == "windows" && env == "gnu" { + } else if (os == "windows" && env == "gnu") || (os == "cygwin") { // This is only set up to work on GNU toolchain versions of Rust lines.push(format!( "-Wl,--output-def,{}", From b07f9217d3e73ef3e73075a0b4d18325ff6edab3 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Mon, 3 Nov 2025 18:47:03 +0100 Subject: [PATCH 2/2] CI: add basics tests for Cygwin Upstream Cygwin doesn't have a rust build yet (WIP) so use MSYS2 which ships rust for the Cygwin target. For the example project don't run tests as those depend on inline-c which depends on target-lexicon v0.11, while 0.13.3 is needed for Cygwin support. /usr/local is not in the default pkgconf search path, so add it. Add separate jobs to avoid complicating the conditions of the existing matrix setup even more. --- .github/workflows/example-project.yml | 42 +++++++++++++++++++++++++++ .github/workflows/rust.yml | 24 +++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/.github/workflows/example-project.yml b/.github/workflows/example-project.yml index 4468aa5..4324c76 100644 --- a/.github/workflows/example-project.yml +++ b/.github/workflows/example-project.yml @@ -132,3 +132,45 @@ jobs: meson setup build meson compile -C build meson test -C build + + example-project-cygwin: + runs-on: windows-latest + + defaults: + run: + shell: msys2 {0} + + steps: + - name: Clone Git repository + uses: actions/checkout@v5 + + - name: Install rust + uses: msys2/setup-msys2@v2 + with: + update: true + msystem: MSYS + install: rust pkgconf gcc openssl-devel libopenssl make + + - name: Install cargo-c applet + run: cargo install --path . + + - name: Build C API for example project + working-directory: example-project + run: cargo cbuild --verbose --release + + - name: Install into /usr/local + working-directory: example-project + run: cargo cinstall --verbose --release --prefix=/usr/local + + - name: Test pkgconf + run: | + export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig + pkgconf --version + test "$(pkgconf --cflags example_project)" = "-I/usr/local/include/example-project-0.1" + test "$(pkgconf --libs example_project)" = "-L/usr/local/lib -lexample-project" + + - name: Test usage from C (using Makefile) + working-directory: example-project/usage-from-c + run: | + export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig + make diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index dcf8abf..d777125 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -90,5 +90,29 @@ jobs: run: | cargo test --verbose + cygwin-test: + needs: rustfmt-clippy + runs-on: windows-latest + + defaults: + run: + shell: msys2 {0} + + steps: + - name: Clone Git repository + uses: actions/checkout@v5 + + - name: Install rust and dependencies + uses: msys2/setup-msys2@v2 + with: + update: true + msystem: MSYS + install: rust openssl-devel libopenssl pkgconf + - name: Build + run: | + cargo build --verbose + - name: Run tests + run: | + cargo test --verbose