From f680de7b256d22323dc99b793b14dfcdd791408f Mon Sep 17 00:00:00 2001 From: Kevin Nakamura Date: Mon, 8 Feb 2021 12:38:29 +0900 Subject: [PATCH] Implement "static" feature flag for FTD2XX static linking. This sets the default configuration to dynamically link with FTD2XX on all platforms. --- .github/workflows/ci.yml | 2 +- Cargo.toml | 3 +++ README.md | 47 ++++++++++++++++++++++++--------- build.rs | 56 +++++++++++++++++++++++++++++++++++++--- tests/lib.rs | 4 +-- 5 files changed, 94 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73a4e04..f9440ff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,7 +85,7 @@ jobs: with: toolchain: stable target: ${{ matrix.target }} - - run: cargo test --target ${{ matrix.target }} + - run: cargo test --features=static --target ${{ matrix.target }} windows_test: name: Windows Unit Tests diff --git a/Cargo.toml b/Cargo.toml index 8520972..f1a503c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,5 +28,8 @@ bindgen = { version = "~0.57.0", optional = true } [dev-dependencies] version-sync = "~0.9.1" +[features] +static = [] + [badges] maintenance = { status = "passively-maintained" } diff --git a/README.md b/README.md index b2abc8a..350bc78 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,14 @@ the unsafe C bindings. ## Usage Simply add this crate as a dependency in your `Cargo.toml`. The static library is distributed in this crate with permission from FTDI. +The default feature set will use dynamic linking. ```toml [dependencies] libftd2xx-ffi = "~0.6.0" ``` +### Bindgen The default feature set will use pre-generated bindings. This is only available for Windows x86_64 and Linux x86_64 platforms. @@ -33,28 +35,49 @@ libftd2xx-ffi = { version = "~0.6.0", features = ["bindgen"] } Bindgen has additional dependencies that must be installed in order to compile successfully, see the [bindgen requirements] page for more details. +### Static Linking +Static linking the FTD2XX library into this crate can be done by using +the ["static"] feature flag. +```toml +[dependencies] +libftd2xx-ffi = { version = "~0.6.0", features = ["static"] } +``` +For GNU/Linux users, no further work is needed. Technically this may be preferred. +However there may be license incompatibilities (static linking with GPL code). +If in doubt, check the FTDI driver license terms. + +On Windows, we rely on MSVC and a manually set the "LIBMSVC_PATH" environment variable. +For example a possible 2019 Community installation path may be: +``` +C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\lib\ +``` +This brings in legacy_stdio_definitions.lib and user32.lib. It seems to play nicely with rust, +but you may end up with multiple defined symbol errors if using this crate as a c/c++ dependency. + ## Supported Targets ### Tested Targets -* `x86_64-pc-windows-msvc` (dynamic linking only) -* `x86_64-unknown-linux-gnu` (static linking only) -* `x86_64-unknown-linux-musl` (static linking only) +* `i686-pc-windows-msvc` (dynamic + static) +* `i686-unknown-linux-gnu` (dynamic + static) +* `i686-unknown-linux-musl` (static) +* `x86_64-pc-windows-msvc` (dynamic + static) +* `x86_64-unknown-linux-gnu` (dynamic + static) +* `x86_64-unknown-linux-musl` (static) ### Untested Targets These targets are provided, but they are untested. Use at your own risk. -* `aarch64-unknown-linux-gnu` (static linking only) -* `aarch64-unknown-linux-musl` (static linking only) -* `arm-unknown-linux-gnueabihf` (static linking only) -* `arm-unknown-linux-musleabihf` (static linking only) -* `armv7-unknown-linux-gnueabihf` (static linking only) -* `armv7-unknown-linux-musleabihf` (static linking only) -* `i686-pc-windows-msvc` (dynamic linking only) -* `i686-unknown-linux-gnu` (static linking only) -* `i686-unknown-linux-musl` (static linking only) +* `aarch64-unknown-linux-gnu` (dynamic + static) +* `aarch64-unknown-linux-musl` (dynamic + static) +* `arm-unknown-linux-gnueabihf` (dynamic + static) +* `arm-unknown-linux-musleabihf` (dynamic + static) +* `armv7-unknown-linux-gnueabihf` (dynamic + static) +* `armv7-unknown-linux-musleabihf` (dynamic + static) +* `i686-unknown-linux-musl` (dynamic) +* `x86_64-unknown-linux-musl` (dynamic) ## References diff --git a/build.rs b/build.rs index 2f5ed9f..3165b1c 100644 --- a/build.rs +++ b/build.rs @@ -3,8 +3,26 @@ use std::env; fn search_path<'a>() -> &'a str { match env::var("CARGO_CFG_TARGET_OS").unwrap().as_str() { "windows" => match env::var("CARGO_CFG_TARGET_ARCH").unwrap().as_str() { - "x86_64" => "vendor/windows/amd64", - "x86" => "vendor/windows/i386", + "x86_64" => { + #[cfg(not(feature = "static"))] + { + "vendor\\windows\\amd64" + } + #[cfg(feature = "static")] + { + "vendor\\windows\\Static\\amd64" + } + } + "x86" => { + #[cfg(not(feature = "static"))] + { + "vendor\\windows\\i386" + } + #[cfg(feature = "static")] + { + "vendor\\windows\\Static\\i386" + } + } target_arch => panic!("Target architecture not supported: {}", target_arch), }, "linux" => match env::var("CARGO_CFG_TARGET_ARCH").unwrap().as_str() { @@ -66,6 +84,36 @@ fn clang_args() -> &'static [&'static str] { } } +#[cfg(not(feature = "static"))] +fn linker_options() { + println!("cargo:rustc-link-lib=dylib=ftd2xx"); +} + +#[cfg(feature = "static")] +fn linker_options() { + println!("cargo:rustc-link-lib=static=ftd2xx"); + + match env::var("CARGO_CFG_TARGET_OS").unwrap().as_str() { + "windows" => { + let libmsvc_path = if let Some(libmsvc_path) = env::var_os("LIBMSVC_PATH") { + match env::var("CARGO_CFG_TARGET_ARCH").unwrap().as_str() { + "x86_64" => format!("{}{}", libmsvc_path.into_string().unwrap(), "\\x64"), + "x86" => format!("{}{}", libmsvc_path.into_string().unwrap(), "\\x64"), + target_arch => panic!("Target architecture not supported: {}", target_arch), + } + } else { + panic!("LIBMSVC_PATH environment variable not found."); + }; + + println!("cargo:rustc-link-search=native={}", libmsvc_path); + println!("cargo:rustc-link-lib=static=legacy_stdio_definitions"); + println!("cargo:rustc-link-lib=user32"); + } + "linux" => {} + target_os => panic!("Target OS not supported: {}", target_os), + } +} + fn main() { let cwd = env::current_dir().unwrap(); let mut header = cwd.clone(); @@ -77,8 +125,10 @@ fn main() { "cargo:rustc-link-search=native={}", search.to_str().unwrap() ); - println!("cargo:rustc-link-lib=static=ftd2xx"); + linker_options(); + println!("cargo:rerun-if-changed={}", header.to_str().unwrap()); + println!("cargo:rerun-if-env-changed=LIBMSVC_PATH"); #[cfg(feature = "bindgen")] { diff --git a/tests/lib.rs b/tests/lib.rs index 65a1579..2a6057a 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,8 +1,8 @@ -use libftd2xx_ffi::FT_GetLibraryVersion; - #[test] #[cfg(not(windows))] fn version() { + use libftd2xx_ffi::FT_GetLibraryVersion; + let mut dw_library_ver = 0; let ft_status = unsafe { FT_GetLibraryVersion(&mut dw_library_ver) };