diff --git a/flake.lock b/flake.lock index 098516f..c8f0ae8 100644 --- a/flake.lock +++ b/flake.lock @@ -36,11 +36,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1672633908, - "narHash": "sha256-sP0BMp4DprVCBjcTYPsTPwkJMsc45vM0FxHdDx6qE8U=", + "lastModified": 1673606088, + "narHash": "sha256-wdYD41UwNwPhTdMaG0AIe7fE1bAdyHe6bB4HLUqUvck=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a4379d2b0deefedc8dba360897557707ea9ee9a7", + "rev": "37b97ae3dd714de9a17923d004a2c5b5543dfa6d", "type": "github" }, "original": { @@ -51,11 +51,11 @@ "nixpkgs-mozilla": { "flake": false, "locked": { - "lastModified": 1664789696, - "narHash": "sha256-UGWJHQShiwLCr4/DysMVFrYdYYHcOqAOVsWNUu+l6YU=", + "lastModified": 1672878308, + "narHash": "sha256-0+fl6PHokhtSV+w58z2QD2rTf8QhcOGsT9o4LwHHZHE=", "owner": "mozilla", "repo": "nixpkgs-mozilla", - "rev": "80627b282705101e7b38e19ca6e8df105031b072", + "rev": "d38863db88e100866b3e494a651ee4962b762fcc", "type": "github" }, "original": { @@ -66,11 +66,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1672633908, - "narHash": "sha256-sP0BMp4DprVCBjcTYPsTPwkJMsc45vM0FxHdDx6qE8U=", + "lastModified": 1673606088, + "narHash": "sha256-wdYD41UwNwPhTdMaG0AIe7fE1bAdyHe6bB4HLUqUvck=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a4379d2b0deefedc8dba360897557707ea9ee9a7", + "rev": "37b97ae3dd714de9a17923d004a2c5b5543dfa6d", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 52afa67..7d245b5 100644 --- a/flake.nix +++ b/flake.nix @@ -21,7 +21,7 @@ }; toolchain = (pkgs.rustChannelOf { rustToolchain = ./rust-toolchain; - sha256 = "sha256-DzNEaW724O8/B8844tt5AVHmSjSQ3cmzlU4BP90oRlY="; + sha256 = "sha256-Zk2rxv6vwKFkTTidgjPm6gDsseVmmljVt201H7zuDkk="; }).rust; in { defaultPackage = naersk'.buildPackage ./.; diff --git a/src/build.rs b/src/build.rs index a199b93..bdaefde 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,21 +1,33 @@ -//! Support to dynamic library, require in user crate a small `build.rs` script, -//! that link to generated Rust library a filename with GHC version suffix, e.g. -//! `libNAME-ghcVERSION.so`, `libNAME-ghcVERSION.dylib` or `NAME-ghcVERSION.dll` -//! -//! Version is the one of `ghc` in `$PATH`, but could be overide with -//! `$CABAL_PACK_GHC_VERSION` env variable! +//! Support to both static and dynamic library, require in user crate a small +//! `build.rs` script. //! //! This build file was written with the constraint in mind of no-dependency to //! keep user setup simple and be easily mergeable with an existing `build.rs` //! automation! fn main() { + // Support to static library require that library name is prefixed by `C` + // https://gitlab.haskell.org/ghc/ghc/-/issues/22564#note_469030 let path = format!("target/{}", std::env::var("PROFILE").unwrap()); #[cfg(target_family = "windows")] let prefix = ""; #[cfg(target_family = "unix")] let prefix = "lib"; let name = env!("CARGO_PKG_NAME"); + #[cfg(target_family = "windows")] + let ext = "lib"; + #[cfg(target_family = "unix")] + let ext = "a"; + let source = format!("{prefix}{name}.{ext}"); + let target = format!("{prefix}C{name}.{ext}"); + symlink(&path, &source, &target); + + // Support to dynamic library require to generated a filename with GHC + // version suffix, e.g. `libNAME-ghcVERSION.so`, `libNAME-ghcVERSION.dylib` + // or `NAME-ghcVERSION.dll` + // + // Version is the one of `ghc` in `$PATH`, but could be overide with + // `$CABAL_PACK_GHC_VERSION` env variable! let suffix = format!( "-ghc{}", std::env::var("CABAL_PACK_GHC_VERSION") @@ -39,12 +51,17 @@ fn main() { let ext = "so"; let source = format!("{prefix}{name}.{ext}"); let target = format!("{prefix}{name}{suffix}.{ext}"); + symlink(&path, &source, &target); +} + +fn symlink(path: &str, source: &str, target: &str) { if !std::path::Path::new(&format!("{path}/{target}")).exists() { + std::fs::create_dir_all(path).unwrap(); std::env::set_current_dir(path).unwrap(); std::fs::OpenOptions::new() .create(true) .write(true) - .open(&source) + .open(source) .unwrap(); #[cfg(target_family = "windows")] std::os::windows::fs::symlink_file(source, target).unwrap(); diff --git a/src/cabal.rs b/src/cabal.rs index d48e0b3..75c6c9d 100644 --- a/src/cabal.rs +++ b/src/cabal.rs @@ -1,8 +1,5 @@ /// Generate user `.cabal`, taking `--enable-nix` option into account pub(crate) fn generate(name: &str, module: &str, version: &str, enable_nix: bool) -> String { - let lib_name = name.replace('-', "_"); // When a lib is created, "-" is replaced by "_" - let package_name = name.replace('_', "-"); // cabal does not expect "_" for packages names - let build_type = if enable_nix { " build-type: Simple" @@ -20,7 +17,7 @@ custom-setup -- `haskell.nix` tell GHC linker where to find the `libNAME.a` by setting -- automatically `extra-lib-dirs`: -- https://input-output-hk.github.io/haskell.nix/tutorials/pkg-map.html - extra-libraries: {lib_name} + extra-libraries: {name} -- Cross-compilation to target `x86_64-w64-mingw32-cc` thrown a lot of -- `undefined reference to 'X'` errors during linking stage ... @@ -35,7 +32,7 @@ custom-setup format!( " -- Libraries that are bundled with the package. - extra-bundled-libraries: {lib_name}" + extra-bundled-libraries: {name}" ) }; @@ -52,7 +49,7 @@ custom-setup -- documentation, see: http://haskell.org/cabal/users-guide/ -- -- The name of the package. -name: {package_name} +name: {module} -- The package version. -- See the Haskell package versioning policy (PVP) for standards diff --git a/src/errors.rs b/src/errors.rs index aa8f0e5..67564a9 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -30,9 +30,8 @@ pub(crate) enum Error { * please back up it before re-running `cargo cabal init --overwrite` command */ CabalFilesExist(String), - /** `build.rs` file already exist, but `crates-type = [ "cdylib" ]` target - * need to generate one, please either remove this option or back up it - * before re-running `cargo cabal init --overwrite` command + /** `build.rs` file already exist, but `cargo-cabal` need to generate one, + * please back up it before re-running `cargo cabal init --overwrite` command */ BuildFileExist, /** `flake.nix` file already exist, but `--enable-nix` option need to @@ -40,6 +39,4 @@ pub(crate) enum Error { * re-running `cargo cabal init --overwrite` command */ FlakeFileExist, - /// `{0}` is an invalid crate name, it should be prefixed by `C` like `C{0}` - InvalidCrateName(String) } diff --git a/src/main.rs b/src/main.rs index 68d7d49..17fc47a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -285,7 +285,7 @@ mod errors; mod flake; mod hsbindgen; -use crate::cargo::{get_crate_type, CrateType}; +use crate::cargo::{get_crate_type}; use ansi_term::Colour; use clap::{arg, Parser, Subcommand}; use errors::Error; @@ -373,14 +373,8 @@ fn init( clean(name)?; } - // Check that crate name is prefixed by `C` ... - // https://gitlab.haskell.org/ghc/ghc/-/issues/22564#note_469030 - name.starts_with('C') - .then_some(()) - .ok_or_else(|| Error::InvalidCrateName(name.to_owned()))?; - // Check that project have a `crate-type` target ... - let crate_type = get_crate_type(root).ok_or(Error::NoCargoLibTarget)?; + get_crate_type(root).ok_or(Error::NoCargoLibTarget)?; // Check that `cargo cabal init` have not been already run ... let cabal = format!("{name}.cabal"); @@ -392,11 +386,9 @@ fn init( .then_some(()) .ok_or_else(|| Error::CabalFilesExist(name.to_owned()))?; // ... and that no existing file would conflict ... - if crate_type == CrateType::DynLib { - (!Path::new("build.rs").exists()) - .then_some(()) - .ok_or(Error::BuildFileExist)?; - } + (!Path::new("build.rs").exists()) + .then_some(()) + .ok_or(Error::BuildFileExist)?; if enable_nix { (!Path::new("flake.rs").exists()) .then_some(()) @@ -414,11 +406,9 @@ fn init( fs::write("hsbindgen.toml", hsbindgen::generate(module)) .map_err(|_| Error::FailedToWriteFile("hsbindgen.toml".to_owned()))?; - // If `crate-type = [ "cdylib" ]` then a custom `build.rs` is needed ... - if crate_type == CrateType::DynLib { - fs::write("build.rs", include_str!("build.rs")) - .map_err(|_| Error::FailedToWriteFile("build.rs".to_owned()))?; - } + // A custom `build.rs` is needed by both static and dynamic libraries targets ... + fs::write("build.rs", include_str!("build.rs")) + .map_err(|_| Error::FailedToWriteFile("build.rs".to_owned()))?; // `--enable-nix` CLI option generate a `flake.nix` rather than a `Setup.lhs` if enable_nix {