Skip to content
This repository was archived by the owner on Oct 1, 2020. It is now read-only.

Commit e7a4b6a

Browse files
authored
Merge pull request #25 from georust/mkirk/pkg-config
use pkg-config by default, fall back to source build automatically
2 parents cad00f6 + 3697b6c commit e7a4b6a

File tree

5 files changed

+109
-160
lines changed

5 files changed

+109
-160
lines changed

.travis.yml

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,37 +10,40 @@ rust:
1010
os:
1111
- linux
1212
- osx
13-
# by default, test vanilla setup on all three channels
1413
env:
1514
global:
16-
- PROJ_FEATURES=""
15+
- INSTALL_PROJ_FIRST=1 _PROJ_SYS_TEST_EXPECT_BUILD_FROM_SRC=0
1716

1817
# test both features on Linux stable, but only pkg_config on macOS stable
1918
jobs:
2019
include:
2120
- os: linux
22-
env: PROJ_FEATURES="--features bundled_proj"
23-
- os: linux
24-
env: PROJ_FEATURES="--features pkg_config"
21+
env: INSTALL_PROJ_FIRST=0 _PROJ_SYS_TEST_EXPECT_BUILD_FROM_SRC=1
2522
- os: osx
26-
env: PROJ_FEATURES="--features pkg_config"
23+
env: INSTALL_PROJ_FIRST=0 _PROJ_SYS_TEST_EXPECT_BUILD_FROM_SRC=1
24+
# verify we can build from src even if its already installed
25+
- os: linux
26+
env: INSTALL_PROJ_FIRST=1 PROJ_FEATURES="--features bundled_proj" _PROJ_SYS_TEST_EXPECT_BUILD_FROM_SRC=1
2727
- os: osx
28-
env: PROJ_FEATURES="--features bundled_proj"
28+
env: INSTALL_PROJ_FIRST=1 PROJ_FEATURES="--features bundled_proj" _PROJ_SYS_TEST_EXPECT_BUILD_FROM_SRC=1
2929

3030
before_install:
3131
- |
32-
if [ "$TRAVIS_OS_NAME" == "linux" ] && [ "$PROJ_FEATURES" != "--features bundled_proj" ]; then
33-
sudo apt-get update
34-
sudo apt-get -y install pkg-config
35-
wget https://download.osgeo.org/proj/proj-7.1.0.tar.gz
36-
tar -xzvf proj-7.1.0.tar.gz
37-
pushd proj-7.1.0 && ./configure --prefix=/usr && make && sudo make install && popd
38-
fi
39-
- |
40-
if [ "$TRAVIS_OS_NAME" == "osx" ] && [ "$PROJ_FEATURES" != "--features bundled_proj" ]; then
41-
brew update
42-
brew upgrade pkg-config
43-
brew upgrade proj
32+
if [[ $INSTALL_PROJ_FIRST == "1" ]]; then
33+
case $TRAVIS_OS_NAME in
34+
"linux")
35+
sudo apt-get update
36+
sudo apt-get -y install pkg-config
37+
wget https://download.osgeo.org/proj/proj-7.1.0.tar.gz
38+
tar -xzvf proj-7.1.0.tar.gz
39+
pushd proj-7.1.0 && ./configure --prefix=/usr && make && sudo make install && popd
40+
;;
41+
"osx")
42+
brew update
43+
brew upgrade pkg-config
44+
brew upgrade proj
45+
;;
46+
esac
4447
fi
4548
4649
script:

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ tar = "0.4.26"
2121

2222
[features]
2323
nobuild = []
24-
pkg_config = []
2524
bundled_proj = []
25+
# `pkg_config` feature is deprecated and does nothing
26+
pkg_config = []
2627

2728
[package.metadata.docs.rs]
2829
features = [ "nobuild" ] # This feature will be enabled during the docs.rs build

README.md

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,30 @@
11
[![Build Status](https://travis-ci.org/georust/proj-sys.svg?branch=master)](https://travis-ci.org/georust/proj-sys)
22

33
# Low-level bindings for PROJ v7.1.x
4-
**This is a [`*-sys`](https://doc.rust-lang.org/cargo/reference/build-scripts.html#a-sys-packages) crate; you shouldn't use its API directly.** The [`proj`](https://github.com/georust/proj) crate is designed for general use.
54

6-
A guide to the functions can be found here: https://proj.org/development/reference/functions.html. Run `cargo doc (optionally --open)` to generate the crate documentation.
5+
**This is a
6+
[`*-sys`](https://doc.rust-lang.org/cargo/reference/build-scripts.html#-sys-packages)
7+
crate; you shouldn't use its API directly.** See the
8+
[`proj`](https://github.com/georust/proj) crate for general use.
79

8-
## Requirements
10+
A guide to the functions can be found here:
11+
https://proj.org/development/reference/functions.html.
912

10-
By default, `libproj` (via `PROJ v7.1.x`) must be present on your system. While this crate may be backwards-compatible with older PROJ 7 and PROJ 6 versions, this is neither tested or supported.
13+
By default, the crate will search for an existing `libproj` (via `PROJ v7.1.x`)
14+
installation on your system using
15+
[pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/).
1116

12-
## Optional Features
13-
Enable these in your `Cargo.toml` like so:
17+
If an acceptable installation is not found, proj-sys will attempt to build
18+
libproj from source bundled in the crate.
1419

15-
`proj-sys = { version = "0.18.1", features = ["bundled_proj"] }`
16-
`proj-sys = { version = "0.18.1", features = ["pkg_config"] }`
20+
## Features
1721

18-
Note that these features are **mutually exclusive**.
19-
20-
1. `bundled_proj` (Linux and macOS targets):
21-
- allow the crate to internally build and depend on a bundled `libproj`. Note that SQLite3 and `libtiff` must be present on your system if you wish to use this feature, and that it builds `libproj` **without** its native network functionality; you will have to implement your own set of callbacks if you wish to make use of them (see the [`proj`](https://crates.io/crates/proj) crate for an example).
22-
2. `pkg_config` (Linux and macOS targets)
23-
- uses [`pkg-config`](https://en.wikipedia.org/wiki/Pkg-config) to add search paths to the build script. Requires `pkg-config` to be installed (available on Homebrew, Macports, apt etc.)
22+
`bundled_proj` - forces building libproj from source even if an acceptable
23+
version could be found on your system. Note that SQLite3 and `libtiff` must be
24+
present on your system if you wish to use this feature, and that it builds
25+
`libproj` **without** its native network functionality; you will have to
26+
implement your own set of callbacks if you wish to make use of them (see the
27+
[`proj`](https://crates.io/crates/proj) crate for an example).
2428

2529
## License
2630

build.rs

Lines changed: 43 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,53 @@
11
use bindgen;
2-
#[cfg(all(
3-
not(feature = "pkg_config"),
4-
feature = "bundled_proj",
5-
not(feature = "nobuild")
6-
))]
72
use cmake;
8-
#[cfg(all(
9-
not(feature = "pkg_config"),
10-
feature = "bundled_proj",
11-
not(feature = "nobuild")
12-
))]
133
use flate2::read::GzDecoder;
14-
#[cfg(all(
15-
not(feature = "pkg_config"),
16-
feature = "bundled_proj",
17-
not(feature = "nobuild")
18-
))]
194
use std::fs::File;
205

21-
#[cfg(all(
22-
feature = "pkg_config",
23-
not(feature = "bundled_proj"),
24-
not(feature = "nobuild")
25-
))]
266
use pkg_config;
277
use std::env;
288
use std::path::PathBuf;
29-
#[cfg(all(
30-
not(feature = "pkg_config"),
31-
feature = "bundled_proj",
32-
not(feature = "nobuild")
33-
))]
349
use tar::Archive;
3510

36-
#[cfg(all(
37-
feature = "pkg_config",
38-
not(feature = "bundled_proj"),
39-
not(feature = "nobuild")
40-
))]
4111
const MINIMUM_PROJ_VERSION: &str = "7.1.0";
4212

4313
#[cfg(feature = "nobuild")]
4414
fn main() {} // Skip the build script on docs.rs
4515

46-
// We sometimes need additional search paths, which we get using pkg-config
47-
#[cfg(all(
48-
feature = "pkg_config",
49-
not(feature = "nobuild"),
50-
not(feature = "bundled_proj")
51-
))]
52-
fn main() {
53-
let pk = pkg_config::Config::new()
16+
#[cfg(not(feature = "nobuild"))]
17+
fn main() -> Result<(), Box<dyn std::error::Error>> {
18+
let include_path = if cfg!(feature = "bundled_proj") {
19+
eprintln!("feature flags specified source build");
20+
build_from_source()?
21+
} else {
22+
pkg_config::Config::new()
5423
.atleast_version(MINIMUM_PROJ_VERSION)
5524
.probe("proj")
56-
.expect(&format!(
57-
"Your PROJ version may be too old. You need at least version {}",
58-
MINIMUM_PROJ_VERSION
59-
));
60-
// Tell cargo to tell rustc to link the system proj
61-
// shared library.
62-
println!("cargo:rustc-link-search=native={:?}", pk.link_paths[0]);
63-
println!("cargo:rustc-link-lib=proj");
64-
let include_path = pk.include_paths[0].to_string_lossy();
65-
66-
// The bindgen::Builder is the main entry point
67-
// to bindgen, and lets you build up options for
68-
// the resulting bindings.
69-
let bindings = bindgen::Builder::default()
70-
.clang_arg(format!("-I{}", include_path))
71-
.trust_clang_mangling(false)
72-
.blacklist_type("max_align_t")
73-
// The input header we would like to generate
74-
// bindings for.
75-
.header("wrapper.h")
76-
// Finish the builder and generate the bindings.
77-
.generate()
78-
// Unwrap the Result and panic on failure.
79-
.expect("Unable to generate bindings");
25+
.and_then(|pk| {
26+
eprintln!("found acceptable libproj already installed at: {:?}", pk.link_paths[0]);
27+
if let Ok(val) = &env::var("_PROJ_SYS_TEST_EXPECT_BUILD_FROM_SRC") {
28+
if val != "0" {
29+
panic!("for testing purposes: existing package was found, but should not have been");
30+
}
31+
}
8032

81-
// Write the bindings to the $OUT_DIR/bindings.rs file.
82-
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
83-
bindings
84-
.write_to_file(out_path.join("bindings.rs"))
85-
.expect("Couldn't write bindings!");
86-
}
33+
// Tell cargo to tell rustc to link the system proj
34+
// shared library.
35+
println!("cargo:rustc-link-search=native={:?}", pk.link_paths[0]);
36+
println!("cargo:rustc-link-lib=proj");
8737

88-
// Vanilla
89-
#[cfg(all(
90-
not(feature = "pkg_config"),
91-
not(feature = "nobuild"),
92-
not(feature = "bundled_proj")
93-
))]
94-
fn main() {
95-
println!("cargo:rustc-link-lib=proj");
38+
Ok(pk.include_paths[0].clone())
39+
})
40+
.or_else(|err| {
41+
eprintln!("pkg-config unable to find existing libproj installation: {}", err);
42+
build_from_source()
43+
})?
44+
};
9645

9746
// The bindgen::Builder is the main entry point
9847
// to bindgen, and lets you build up options for
9948
// the resulting bindings.
10049
let bindings = bindgen::Builder::default()
50+
.clang_arg(format!("-I{}", include_path.to_string_lossy()))
10151
.trust_clang_mangling(false)
10252
.blacklist_type("max_align_t")
10353
// The input header we would like to generate
@@ -110,25 +60,29 @@ fn main() {
11060

11161
// Write the bindings to the $OUT_DIR/bindings.rs file.
11262
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
113-
bindings
114-
.write_to_file(out_path.join("bindings.rs"))
115-
.expect("Couldn't write bindings!");
63+
bindings.write_to_file(out_path.join("bindings.rs"))?;
64+
65+
Ok(())
11666
}
11767

118-
#[cfg(all(
119-
not(feature = "pkg-config"),
120-
not(feature = "nobuild"),
121-
feature = "bundled_proj"
122-
))]
123-
fn main() {
124-
// Build PROJ from the included tar
68+
// returns the path of "inlude" for the built proj
69+
fn build_from_source() -> Result<std::path::PathBuf, Box<dyn std::error::Error>> {
70+
eprintln!("building libproj from source");
71+
if let Ok(val) = &env::var("_PROJ_SYS_TEST_EXPECT_BUILD_FROM_SRC") {
72+
if val == "0" {
73+
panic!(
74+
"for testing purposes: package was building from source but should not have been"
75+
);
76+
}
77+
}
78+
12579
// NOTE: The PROJ build expects Sqlite3 to be present on the system.
12680
let path = "PROJSRC/proj-7.1.0.tar.gz";
12781
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
128-
let tar_gz = File::open(path).expect("Couldn't open PROJ source tar");
82+
let tar_gz = File::open(path)?;
12983
let tar = GzDecoder::new(tar_gz);
13084
let mut archive = Archive::new(tar);
131-
archive.unpack("PROJSRC/proj").expect("Couldn't unpack tar");
85+
archive.unpack("PROJSRC/proj")?;
13286
let mut config = cmake::Config::new("PROJSRC/proj/proj-7.1.0");
13387
config.define("BUILD_SHARED_LIBS", "OFF");
13488
config.define("BUILD_TESTING", "OFF");
@@ -168,12 +122,5 @@ fn main() {
168122
println!("cargo:warning=proj-sys: Not configuring an explicit C++ standard library on this target.");
169123
}
170124

171-
bindgen::builder()
172-
.header(proj.join("include").join("proj.h").to_str().unwrap())
173-
.trust_clang_mangling(false)
174-
.blacklist_type("max_align_t")
175-
.generate()
176-
.expect("Unable to generate bindings")
177-
.write_to_file(out_path.join("bindings.rs"))
178-
.expect("Couldn't write bindings!");
125+
Ok(proj.join("include"))
179126
}

src/lib.rs

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,30 @@
33
#![allow(non_snake_case)]
44
#![doc(html_logo_url = "https://raw.githubusercontent.com/georust/meta/master/logo/logo.png")]
55
//! # Low-level bindings for PROJ v7.1.x
6-
//! **This is a [`*-sys`](https://doc.rust-lang.org/cargo/reference/build-scripts.html#a-sys-packages) crate; you shouldn't use its API directly.** The [`proj`](https://github.com/georust/proj) crate is designed for general use.
7-
//!
8-
//! A guide to the functions can be found on [proj.org](https://proj.org/development/reference/functions.html). Run `cargo doc (optionally --open)` to generate the crate documentation.
9-
//!
10-
//! ## Requirements
11-
//!
12-
//! By default, `libproj` (via `PROJ v7.1.x`) must be present on your system. While this crate may be backwards-compatible with older PROJ 7 and PROJ 6 versions, this is neither tested or supported.
13-
//!
14-
//! ## Optional Features
15-
//! Enable these in your `Cargo.toml` like so:
16-
//!
17-
//! `proj-sys = { version = "0.18.2", features = ["bundled_proj"] }`
18-
//! `proj-sys = { version = "0.18.2", features = ["pkg_config"] }`
19-
//!
20-
//! Note that these features are **mutually exclusive**.
21-
//!
22-
//! 1. `bundled_proj` (Linux and macOS targets):
23-
//! - allow the crate to internally build and depend on a bundled `libproj`. Note that SQLite3 and `libtiff` must be present on your system if you wish to use this feature, and that it builds `libproj` **without** its native network functionality; you will have to implement your own set of callbacks if you wish to make use of them (see the [`proj`](https://crates.io/crates/proj) crate for an example).
24-
//! 2. `pkg_config` (Linux and macOS targets)
25-
//! - uses [`pkg-config`](https://en.wikipedia.org/wiki/Pkg-config) to add search paths to the build script. Requires `pkg-config` to be installed (available on Homebrew, Macports, apt etc.)
26-
//!
27-
//! ## License
28-
//!
29-
//! Licensed under either of
30-
//!
31-
//! * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
32-
//! * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
33-
//!
34-
//! at your option.
35-
6+
//!
7+
//! **This is a
8+
//! [`*-sys`](https://doc.rust-lang.org/cargo/reference/build-scripts.html#-sys-packages)
9+
//! crate; you shouldn't use its API directly.** See the
10+
//! [`proj`](https://github.com/georust/proj) crate for general use.
11+
//!
12+
//! A guide to the functions can be found here:
13+
//! https://proj.org/development/reference/functions.html.
14+
//!
15+
//! By default, the crate will search for an existing `libproj` (via `PROJ v7.1.x`)
16+
//! installation on your system using
17+
//! [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/).
18+
//!
19+
//! If an acceptable installation is not found, proj-sys will attempt to build
20+
//! libproj from source bundled in the crate.
21+
//!
22+
//! ## Features
23+
//!
24+
//! `bundled_proj` - forces building libproj from source even if an acceptable
25+
//! version could be found on your system. Note that SQLite3 and `libtiff` must be
26+
//! present on your system if you wish to use this feature, and that it builds
27+
//! `libproj` **without** its native network functionality; you will have to
28+
//! implement your own set of callbacks if you wish to make use of them (see the
29+
//! [`proj`](https://crates.io/crates/proj) crate for an example).
3630
3731
#[cfg(not(feature = "nobuild"))]
3832
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

0 commit comments

Comments
 (0)