Skip to content

Commit

Permalink
More static fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
twistedfall committed Jul 21, 2024
1 parent 338be0b commit 3d4b091
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 76 deletions.
37 changes: 0 additions & 37 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,43 +94,6 @@ fn files_with_extension<'e>(dir: &Path, extension: impl AsRef<OsStr> + 'e) -> Re
})
}

/// Returns Some(new_file_name) if some parts of the filename were removed, None otherwise
fn cleanup_lib_filename(filename: &OsStr) -> Option<&OsStr> {
let mut new_filename = filename;
// used to check for the file extension (with dots stripped) and for the part of the filename
const LIB_EXTS: [&str; 7] = [".so.", ".a.", ".dll.", ".lib.", ".dylib.", ".framework.", ".tbd."];
let filename_path = Path::new(new_filename);
// strip lib extension from the filename
if let (Some(stem), Some(extension)) = (filename_path.file_stem(), filename_path.extension().and_then(OsStr::to_str)) {
if LIB_EXTS.iter().any(|e| e.trim_matches('.').eq_ignore_ascii_case(extension)) {
new_filename = stem;
}
}
if let Some(mut file) = new_filename.to_str() {
let orig_len = file.len();

// strip "lib" prefix from the filename unless targeting MSVC
if !*TARGET_ENV_MSVC {
file = file.strip_prefix("lib").unwrap_or(file);
}

// strip lib extension + suffix (e.g. .so.4.6.0) from the filename
LIB_EXTS.iter().for_each(|&inner_ext| {
if let Some(inner_ext_idx) = file.find(inner_ext) {
file = &file[..inner_ext_idx];
}
});
if orig_len != file.len() {
new_filename = OsStr::new(file);
}
}
if new_filename.len() != filename.len() {
Some(new_filename)
} else {
None
}
}

fn get_module_header_dir(header_dir: &Path) -> Option<PathBuf> {
let mut out = header_dir.join("opencv2.framework/Headers");
if out.exists() {
Expand Down
81 changes: 52 additions & 29 deletions build/cmake_probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,62 @@ use semver::Version;
use shlex::Shlex;

use super::library::Linkage;
use super::Result;
use super::{Result, TARGET_ENV_MSVC};

#[derive(Debug, PartialEq, Eq)]
pub struct LinkLib(pub Linkage, pub String);

impl LinkLib {
#[inline]
pub fn emit_cargo_rustc_link(&self) -> String {
let link_spec = self.0.as_cargo_rustc_link_spec();
let link_spec = if self.1.starts_with(link_spec) {
""
format!("cargo:rustc-link-lib={}{}", self.0.as_cargo_rustc_link_spec(), self.1)
}

/// Returns Some(new_file_name) with extra parts of the filename were removed, None in case of error
pub fn with_cleaned_up_lib_filename(self) -> Option<Self> {
return Some(self);
if matches!(self.0, Linkage::Static | Linkage::Framework) {
Some(self)
} else {
link_spec
};
format!("cargo:rustc-link-lib={link_spec}{}", self.1)
let mut new_filename = Path::new(&self.1).as_os_str();
// used to check for the file extension (with dots stripped) and for the part of the filename
const LIB_EXTS: [&str; 7] = [".so.", ".a.", ".dll.", ".lib.", ".dylib.", ".framework.", ".tbd."];
let filename_path = Path::new(new_filename);
// strip lib extension from the filename
if let (Some(stem), Some(extension)) = (filename_path.file_stem(), filename_path.extension().and_then(OsStr::to_str)) {
if LIB_EXTS.iter().any(|e| e.trim_matches('.').eq_ignore_ascii_case(extension)) {
new_filename = stem;
}
}
if let Some(mut file) = new_filename.to_str() {
let orig_len = file.len();

// strip "lib" prefix from the filename unless targeting MSVC
if !*TARGET_ENV_MSVC {
file = file.strip_prefix("lib").unwrap_or(file);
}

// strip lib extension + suffix (e.g. .so.4.6.0) from the filename
LIB_EXTS.iter().for_each(|&inner_ext| {
if let Some(inner_ext_idx) = file.find(inner_ext) {
file = &file[..inner_ext_idx];
}
});
if orig_len != file.len() {
new_filename = OsStr::new(file);
}
}
new_filename
.to_str()
.map(|new_filename| Self(self.0, new_filename.to_string()))
}
}
}

impl From<&str> for LinkLib {
fn from(value: &str) -> Self {
Self(Linkage::Default, value.to_string())
let (linkage, value) = Linkage::from_prefixed_str(value);
Self(linkage, value.to_string())
}
}

Expand All @@ -49,7 +84,8 @@ impl LinkSearch {

impl From<&str> for LinkSearch {
fn from(value: &str) -> Self {
Self(Linkage::Default, value.into())
let (linkage, value) = Linkage::from_prefixed_str(value);
Self(linkage, value.into())
}
}

Expand Down Expand Up @@ -190,43 +226,30 @@ impl<'r> CmakeProbe<'r> {
} else {
framework.to_string()
};
let framework_path = Path::new(&framework);
let has_extension = framework_path
.extension()
.and_then(OsStr::to_str)
.map_or(false, |ext| ext.eq_ignore_ascii_case("framework"));
let name = if has_extension {
framework
} else {
format!("{}.framework", framework)
};
link_libs.push(LinkLib(Linkage::Framework, name));
link_libs.push(LinkLib(Linkage::Framework, framework));
} else if !arg.starts_with('-') {
let path = Path::new(arg);
let linkage = if Self::is_library_static(path) {
let linkage = if Self::is_library_static_archive(path) {
Linkage::Static
} else {
Linkage::Default
};
if let Some(file) = path.file_name().and_then(super::cleanup_lib_filename) {
if let Some(parent) = path.parent().map(|p| p.to_owned()) {
let search_path = LinkSearch(linkage, parent);
let search_path = LinkSearch(Linkage::Default, parent);
if !link_paths.contains(&search_path) {
link_paths.push(search_path);
}
} else {
panic!("{}", arg.to_string());
}
let file = file.to_str().expect("Non-UTF8 filename");
link_libs.push(LinkLib(linkage, file.to_string()));
}
Linkage::Default
};
link_libs.push(LinkLib(linkage, path.to_str().expect("Non-UTF8 filename").to_string()));
} else {
eprintln!("=== Unexpected cmake compiler argument found: {arg}");
}
}
}

fn is_library_static(path: &Path) -> bool {
fn is_library_static_archive(path: &Path) -> bool {
path.extension().map_or(false, |ext| ext.eq_ignore_ascii_case("a"))
}

Expand Down
21 changes: 11 additions & 10 deletions build/library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use dunce::canonicalize;
use semver::Version;

use super::cmake_probe::{CmakeProbe, LinkLib, LinkSearch};
use super::{cleanup_lib_filename, get_version_from_headers, Result, MANIFEST_DIR, OUT_DIR, TARGET_VENDOR_APPLE};
use super::{get_version_from_headers, Result, MANIFEST_DIR, OUT_DIR, TARGET_VENDOR_APPLE};

struct PackageName;

Expand Down Expand Up @@ -103,6 +103,13 @@ impl Linkage {
Self::Framework => "framework=",
}
}

pub fn from_prefixed_str(s: &str) -> (Self, &str) {
[Self::Dynamic, Self::Static, Self::Framework]
.iter()
.find_map(|l| s.strip_prefix(l.as_cargo_rustc_link_spec()).map(|s| (*l, s)))
.unwrap_or((Self::Default, s))
}
}

#[derive(Debug)]
Expand All @@ -114,15 +121,9 @@ pub struct Library {

impl Library {
fn process_library_list(libs: impl IntoIterator<Item = LinkLib>) -> impl Iterator<Item = LinkLib> {
libs.into_iter().filter_map(|LinkLib(linkage, path)| {
let path = Path::new(&path);
if let Some(filename) = path.file_name() {
let filename = cleanup_lib_filename(filename).unwrap_or(filename);
filename.to_str().map(|f| LinkLib(linkage, f.to_owned()))
} else {
None
}
})
libs
.into_iter()
.filter_map(|link_lib| link_lib.with_cleaned_up_lib_filename())
}

fn version_from_include_paths(include_paths: impl IntoIterator<Item = impl AsRef<Path>>) -> Option<Version> {
Expand Down
1 change: 1 addition & 0 deletions tests/mat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use matches::assert_matches;
use opencv::core::{MatConstIterator, MatIter, Point, Point2d, Rect, Scalar, Size, Vec2b, Vec2s, Vec3d, Vec3f, Vec4w, Vector};
use opencv::prelude::*;
use opencv::{core, imgproc, Error, Result};

const PIXEL: &[u8] = include_bytes!("pixel.png");

#[test]
Expand Down

0 comments on commit 3d4b091

Please sign in to comment.