From b74dd9b602201c70a270eb98abad6478ff14a17f Mon Sep 17 00:00:00 2001 From: Vincent PRELAT Date: Wed, 3 Mar 2021 09:01:08 +0100 Subject: [PATCH 1/5] add support of vcpkg with msvc toolchain --- proj-sys/Cargo.toml | 4 +++ proj-sys/build.rs | 76 ++++++++++++++++++++++++++++++++------------- 2 files changed, 58 insertions(+), 22 deletions(-) diff --git a/proj-sys/Cargo.toml b/proj-sys/Cargo.toml index 2a1a0c48..e0996ed8 100644 --- a/proj-sys/Cargo.toml +++ b/proj-sys/Cargo.toml @@ -19,6 +19,10 @@ cmake = "0.1" flate2 = "1.0.14" tar = "0.4.26" +[target.'cfg(target_env = "msvc")'.build-dependencies] +vcpkg = "0.2.11" +winapi-build = "0.1.1" + [features] nobuild = [] bundled_proj = [] diff --git a/proj-sys/build.rs b/proj-sys/build.rs index fa321b51..a473ec31 100644 --- a/proj-sys/build.rs +++ b/proj-sys/build.rs @@ -3,6 +3,10 @@ use cmake; use flate2::read::GzDecoder; use std::fs::File; +#[cfg(target_env = "msvc")] +use vcpkg; +#[cfg(target_env = "msvc")] +use build; use pkg_config; use std::env; use std::path::PathBuf; @@ -10,6 +14,55 @@ use tar::Archive; const MINIMUM_PROJ_VERSION: &str = "7.2.1"; +#[cfg(target_env = "msvc")] +fn try_vcpkg() -> Result> { + build::link("shell32", true); + build::link("ole32", true); + let lib = vcpkg::Config::new() + .emit_includes(true) + .find_package("proj"); + + if let Err(_e) = lib { + return try_pkg_config() + } + + let include_path = lib.unwrap() + .include_paths[0] + .clone(); + + Ok(include_path) +} + +#[cfg(not(target_env = "msvc"))] +fn try_vcpkg() -> Result> { + try_pkg_config() +} + +fn try_pkg_config() -> Result> { + pkg_config::Config::new() + .atleast_version(MINIMUM_PROJ_VERSION) + .probe("proj") + .and_then(|pk| { + eprintln!("found acceptable libproj already installed at: {:?}", pk.link_paths[0]); + if let Ok(val) = &env::var("_PROJ_SYS_TEST_EXPECT_BUILD_FROM_SRC") { + if val != "0" { + panic!("for testing purposes: existing package was found, but should not have been"); + } + } + + // Tell cargo to tell rustc to link the system proj + // shared library. + println!("cargo:rustc-link-search=native={:?}", pk.link_paths[0]); + println!("cargo:rustc-link-lib=proj"); + + Ok(pk.include_paths[0].clone()) + }) + .or_else(|err| { + eprintln!("pkg-config unable to find existing libproj installation: {}", err); + build_from_source() + }) +} + #[cfg(feature = "nobuild")] fn main() {} // Skip the build script on docs.rs @@ -19,28 +72,7 @@ fn main() -> Result<(), Box> { eprintln!("feature flags specified source build"); build_from_source()? } else { - pkg_config::Config::new() - .atleast_version(MINIMUM_PROJ_VERSION) - .probe("proj") - .and_then(|pk| { - eprintln!("found acceptable libproj already installed at: {:?}", pk.link_paths[0]); - if let Ok(val) = &env::var("_PROJ_SYS_TEST_EXPECT_BUILD_FROM_SRC") { - if val != "0" { - panic!("for testing purposes: existing package was found, but should not have been"); - } - } - - // Tell cargo to tell rustc to link the system proj - // shared library. - println!("cargo:rustc-link-search=native={:?}", pk.link_paths[0]); - println!("cargo:rustc-link-lib=proj"); - - Ok(pk.include_paths[0].clone()) - }) - .or_else(|err| { - eprintln!("pkg-config unable to find existing libproj installation: {}", err); - build_from_source() - })? + try_vcpkg()? }; // The bindgen::Builder is the main entry point From b665fd351d3d825214e26627bf9fd2a5fbe472a2 Mon Sep 17 00:00:00 2001 From: Vincent PRELAT Date: Wed, 10 Mar 2021 11:27:20 +0100 Subject: [PATCH 2/5] add CI msvc --- .github/workflows/test.yml | 87 ++++++++++++++++++++++++++++++++++++++ proj-sys/build.rs | 1 + 2 files changed, 88 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3869255e..497aa776 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,6 +16,7 @@ jobs: - proj-sys-ubuntu - proj-macos - proj-sys-macos + - proj-sys-windows steps: - name: Mark the job as a success if: success() @@ -119,3 +120,89 @@ jobs: uses: actions/checkout@v2 - run: brew install proj - run: cargo test ${{ matrix.features }} + + proj-sys-windows: + name: proj-sys windows + if: "!contains(github.event.head_commit.message, '[skip ci]')" + runs-on: windows-latest + env: + _PROJ_SYS_TEST_EXPECT_BUILD_FROM_SRC: 0 + strategy: + fail-fast: false + matrix: + config: + - { + target: "x86_64-pc-windows-msvc", + VCPKG_DEFAULT_TRIPLET: "x64-windows-static", + RUSTFLAGS: "-Ctarget-feature=+crt-static", + features: "", + } + - { + target: "x86_64-pc-windows-msvc", + VCPKG_DEFAULT_TRIPLET: "x64-windows-static-md", + features: "", + } + - { + target: "x86_64-pc-windows-msvc", + VCPKG_DEFAULT_TRIPLET: "x64-windows", + VCPKGRS_DYNAMIC: 1, + # "cargo test --doc" broken with dynamic lib on CI machine (missing dll) + features: "--all-targets", + } + # - { + # target: "i686-pc-windows-msvc", + # VCPKG_DEFAULT_TRIPLET: "x86-windows-static", + # RUSTFLAGS: "-Ctarget-feature=+crt-static", + # features: "", + # } + # - { + # target: "i686-pc-windows-msvc", + # VCPKG_DEFAULT_TRIPLET: "x86-windows-static-md", + # features: "", + # } + # - { + # target: "i686-pc-windows-msvc", + # VCPKG_DEFAULT_TRIPLET: "x86-windows", + # VCPKGRS_DYNAMIC: 1, + # features: "--all-targets", + # } + steps: + - uses: actions/checkout@v2 + - name: Install vcpkg + run: | + git clone https://github.com/Microsoft/vcpkg.git vcp + # PROJ version 7.2.1 - https://github.com/microsoft/vcpkg/search?q=proj4&type=commits + git -C vcp checkout 8fe4184c6a17e237d8b864b6d10e0b520334a093 + vcp\bootstrap-vcpkg.bat -disableMetrics + - name: Set env + shell: bash + run: echo "VCPKG_ROOT=${{ github.workspace }}\vcp" >> $GITHUB_ENV + - name: Install LLVM and Clang + uses: KyleMayes/install-llvm-action@v1 + with: + version: "10.0" + directory: ${{ runner.temp }}/llvm + - name: Set LIBCLANG_PATH + run: echo "LIBCLANG_PATH=$((gcm clang).source -replace "clang.exe")" >> $env:GITHUB_ENV + - name: install proj lib + env: + VCPKG_DEFAULT_TRIPLET: "${{ matrix.config.VCPKG_DEFAULT_TRIPLET }}" + shell: bash + run: | + set -ex + echo VCPKG_ROOT=${VCPKG_ROOT} + ${VCPKG_ROOT}/vcpkg install proj + - name: Run integration tests + env: + VCPKG_DEFAULT_TRIPLET: "${{ matrix.config.VCPKG_DEFAULT_TRIPLET }}" + RUSTFLAGS: ${{ matrix.config.RUSTFLAGS }} + shell: bash + run: | + set -ex + rustup target add ${{ matrix.config.target }} + rustc --version + cargo --version + echo dyn=${{ matrix.config.VCPKGRS_DYNAMIC }} + if [ '${{ matrix.config.VCPKGRS_DYNAMIC }}' != '' ] ; then export VCPKGRS_DYNAMIC=1 ; fi + cargo build --target ${{ matrix.config.target }} ${{ matrix.config.features }} + cargo test --target ${{ matrix.config.target }} ${{ matrix.config.features }} diff --git a/proj-sys/build.rs b/proj-sys/build.rs index a473ec31..5c47fa2f 100644 --- a/proj-sys/build.rs +++ b/proj-sys/build.rs @@ -23,6 +23,7 @@ fn try_vcpkg() -> Result> { .find_package("proj"); if let Err(_e) = lib { + eprintln!("vcpkg proj library not found, trying pkg_config"); return try_pkg_config() } From 0faa5b883c0f62b9191519d731e7c2035c98e0a4 Mon Sep 17 00:00:00 2001 From: Vincent PRELAT Date: Wed, 10 Mar 2021 14:47:21 +0100 Subject: [PATCH 3/5] test assert_relative_eq, add epsilon for small changes in grid --- src/proj.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/proj.rs b/src/proj.rs index 14095111..a63dd408 100644 --- a/src/proj.rs +++ b/src/proj.rs @@ -1036,8 +1036,8 @@ mod test { let t = proj .convert(MyPoint::new(4760096.421921, 3744293.729449)) .unwrap(); - assert_relative_eq!(t.x(), 1450880.2910605003); - assert_relative_eq!(t.y(), 1141263.0111604529); + assert_relative_eq!(t.x(), 1450880.2910605003, epsilon = 1e-8); + assert_relative_eq!(t.y(), 1141263.0111604529, epsilon = 1e-8); } #[test] // Carry out a projection from geodetic coordinates @@ -1066,8 +1066,8 @@ mod test { let t = stereo70 .project(MyPoint::new(500119.70352012233, 500027.77896348457), true) .unwrap(); - assert_relative_eq!(t.x(), 0.43633200013698786); - assert_relative_eq!(t.y(), 0.8028510000110507); + assert_relative_eq!(t.x(), 0.43633200013698786, epsilon = 1e-14); + assert_relative_eq!(t.y(), 0.8028510000110507, epsilon = 1e-14); } #[test] // Carry out an inverse projection to geodetic coordinates @@ -1159,8 +1159,8 @@ mod test { MyPoint::new(4760197.421921, 3744394.729449), ]; ft_to_m.convert_array(&mut v).unwrap(); - assert_relative_eq!(v[0].x(), 1450880.2910605003f64); - assert_relative_eq!(v[1].y(), 1141293.7960220198); + assert_relative_eq!(v[0].x(), 1450880.2910605003f64, epsilon = 1e-8); + assert_relative_eq!(v[1].y(), 1141293.7960220198, epsilon = 1e-8); } #[test] @@ -1173,8 +1173,8 @@ mod test { // 👽 let usa_m = MyPoint::new(-115.797615, 37.2647978); let usa_ft = to_feet.convert(usa_m).unwrap(); - assert_eq!(6693625.67217475, usa_ft.x()); - assert_eq!(3497301.5918027186, usa_ft.y()); + assert_relative_eq!(6693625.67217475, usa_ft.x(),epsilon = 1e-8); + assert_relative_eq!(3497301.5918027186, usa_ft.y(), epsilon = 1e-8); } #[test] From ec20eb3404cdebe95d54e83a1a7051d2a33a1adb Mon Sep 17 00:00:00 2001 From: Vincent PRELAT Date: Fri, 23 Apr 2021 17:16:09 +0200 Subject: [PATCH 4/5] put main function at top and correct vcpkg function --- proj-sys/build.rs | 107 +++++++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 53 deletions(-) diff --git a/proj-sys/build.rs b/proj-sys/build.rs index 5c47fa2f..9bb4fcdc 100644 --- a/proj-sys/build.rs +++ b/proj-sys/build.rs @@ -3,10 +3,6 @@ use cmake; use flate2::read::GzDecoder; use std::fs::File; -#[cfg(target_env = "msvc")] -use vcpkg; -#[cfg(target_env = "msvc")] -use build; use pkg_config; use std::env; use std::path::PathBuf; @@ -14,29 +10,69 @@ use tar::Archive; const MINIMUM_PROJ_VERSION: &str = "7.2.1"; +#[cfg(feature = "nobuild")] +fn main() {} // Skip the build script on docs.rs + +#[cfg(not(feature = "nobuild"))] +fn main() -> Result<(), Box> { + let include_path = if cfg!(feature = "bundled_proj") { + eprintln!("feature flags specified source build"); + build_from_source()? + } else { + configure_pkg()? + }; + + // The bindgen::Builder is the main entry point + // to bindgen, and lets you build up options for + // the resulting bindings. + let bindings = bindgen::Builder::default() + .clang_arg(format!("-I{}", include_path.to_string_lossy())) + .trust_clang_mangling(false) + .size_t_is_usize(true) + .blacklist_type("max_align_t") + // The input header we would like to generate + // bindings for. + .header("wrapper.h") + // Finish the builder and generate the bindings. + .generate() + // Unwrap the Result and panic on failure. + .expect("Unable to generate bindings"); + + // Write the bindings to the $OUT_DIR/bindings.rs file. + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings.write_to_file(out_path.join("bindings.rs"))?; + + Ok(()) +} + +#[cfg(target_env = "msvc")] +fn configure_pkg() -> Result> { + try_vcpkg() +} + +#[cfg(not(target_env = "msvc"))] +fn configure_pkg() -> Result> { + try_pkg_config() +} + #[cfg(target_env = "msvc")] fn try_vcpkg() -> Result> { + use vcpkg; + use build; + build::link("shell32", true); build::link("ole32", true); let lib = vcpkg::Config::new() .emit_includes(true) .find_package("proj"); - if let Err(_e) = lib { - eprintln!("vcpkg proj library not found, trying pkg_config"); - return try_pkg_config() + match lib { + Ok(include_path) => Ok(include_path.include_paths[0].clone()), + Err(e) => { + eprintln!("vcpkg error: {}, trying pkg_config", e); + try_pkg_config() + } } - - let include_path = lib.unwrap() - .include_paths[0] - .clone(); - - Ok(include_path) -} - -#[cfg(not(target_env = "msvc"))] -fn try_vcpkg() -> Result> { - try_pkg_config() } fn try_pkg_config() -> Result> { @@ -64,41 +100,6 @@ fn try_pkg_config() -> Result> { }) } -#[cfg(feature = "nobuild")] -fn main() {} // Skip the build script on docs.rs - -#[cfg(not(feature = "nobuild"))] -fn main() -> Result<(), Box> { - let include_path = if cfg!(feature = "bundled_proj") { - eprintln!("feature flags specified source build"); - build_from_source()? - } else { - try_vcpkg()? - }; - - // The bindgen::Builder is the main entry point - // to bindgen, and lets you build up options for - // the resulting bindings. - let bindings = bindgen::Builder::default() - .clang_arg(format!("-I{}", include_path.to_string_lossy())) - .trust_clang_mangling(false) - .size_t_is_usize(true) - .blacklist_type("max_align_t") - // The input header we would like to generate - // bindings for. - .header("wrapper.h") - // Finish the builder and generate the bindings. - .generate() - // Unwrap the Result and panic on failure. - .expect("Unable to generate bindings"); - - // Write the bindings to the $OUT_DIR/bindings.rs file. - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindings.write_to_file(out_path.join("bindings.rs"))?; - - Ok(()) -} - // returns the path of "inlude" for the built proj fn build_from_source() -> Result> { eprintln!("building libproj from source"); From e8ae779a830ad0d1423b90dbf2014ef27a99fd14 Mon Sep 17 00:00:00 2001 From: Vincent PRELAT Date: Fri, 23 Apr 2021 17:27:01 +0200 Subject: [PATCH 5/5] remove vcpkg checkout, use always last version --- .github/workflows/test.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 497aa776..1f1e6659 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -171,8 +171,6 @@ jobs: - name: Install vcpkg run: | git clone https://github.com/Microsoft/vcpkg.git vcp - # PROJ version 7.2.1 - https://github.com/microsoft/vcpkg/search?q=proj4&type=commits - git -C vcp checkout 8fe4184c6a17e237d8b864b6d10e0b520334a093 vcp\bootstrap-vcpkg.bat -disableMetrics - name: Set env shell: bash