From 0da3d3e5cb72578cb84272acc25a259d414a19ec Mon Sep 17 00:00:00 2001 From: Be Date: Tue, 26 Jul 2022 02:26:32 -0500 Subject: [PATCH] handle file paths to libraries Typically pkgconfig files specify cflags for linking with -L and -l, however, pkgconfig files can also specify paths to library files. For example, building Qt5 statically on macOS generates the following pkgconfig file. Notice the absolute path to libqtpcre.a in Libs.private: prefix=/Users/be/qt5-installed exec_prefix=${prefix} libdir=${prefix}/lib includedir=${prefix}/include host_bins=${prefix}/bin qt_config=debug_and_release release debug build_all c++11 c++14 c++17 c++1z concurrent dbus no-pkg-config reduce_exports release_tools static stl Name: Qt5 Core Description: Qt Core module Version: 5.15.5 Libs: -L${libdir} -lQt5Core Libs.private: -framework DiskArbitration -framework IOKit -lm -framework AppKit -framework Security -framework ApplicationServices -framework CoreServices -framework CoreFoundation -framework Foundation -lz /Users/be/sw/qt-everywhere-src-5.15.5/qtbase/lib/libqtpcre2.a Cflags: -DQT_CORE_LIB -I${includedir}/QtCore -I${includedir} Building Qt5 statically on macOS with vcpkg generates this pkgconfig file which has a handful of file paths for libraries: prefix=${pcfiledir}/../.. exec_prefix=${prefix} libdir=${prefix}/lib includedir=${prefix}/include/qt5 host_bins=${prefix}/tools/qt5/bin qt_config=release c++11 c++14 c++17 c++1z concurrent dbus no-pkg-config reduce_exports static stl properties animation textcodec big_codecs codecs itemmodel proxymodel concatenatetablesproxymodel textdate datestring doubleconversion filesystemiterator filesystemwatcher gestures identityproxymodel library mimetype process statemachine regularexpression settings sharedmemory sortfilterproxymodel stringlistmodel systemsemaphore temporaryfile translation transposeproxymodel xmlstream xmlstreamreader xmlstreamwriter Name: Qt5 Core Description: Qt Core module Version: 5.15.3 Libs: -L"${libdir}" -lQt5Core -L"${prefix}/lib" -L"${prefix}/lib/manual-link" -framework DiskArbitration -framework IOKit -lm -framework AppKit -framework Security -framework ApplicationServices -framework CoreServices -framework CoreFoundation -framework Foundation ${prefix}/lib/libz.a -ldouble-conversion ${prefix}/lib/libicui18n.a ${prefix}/lib/libicutu.a ${prefix}/lib/libicuuc.a ${prefix}/lib/libicuio.a ${prefix}/lib/libicudata.a ${prefix}/lib/libpcre2-16.a -lzstd ${prefix}/lib/libbz2.a ${prefix}/lib/libpng16.a ${prefix}/lib/libicui18n.a ${prefix}/lib/libicutu.a ${prefix}/lib/libicuuc.a ${prefix}/lib/libicuio.a ${prefix}/lib/libicudata.a ${prefix}/lib/libzstd.a Cflags: -DQT_CORE_LIB -I"${includedir}/QtCore" -I"${includedir}" --- Cargo.toml | 3 ++- src/lib.rs | 32 +++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 270a6de..e9586de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,5 +13,6 @@ Cargo build scripts. """ keywords = ["build-dependencies"] -[dev-dependencies] +[dependencies] lazy_static = "1" +regex = "1.6.0" diff --git a/src/lib.rs b/src/lib.rs index a28304e..986a212 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -568,6 +568,15 @@ impl Library { } fn parse_libs_cflags(&mut self, name: &str, output: &[u8], config: &Config) { + #[cfg(windows)] + lazy_static::lazy_static! { + static ref LIB_BASENAME: regex::Regex = regex::Regex::new(r"^(.*)\.(lib|dll)$").unwrap(); + } + #[cfg(not(windows))] + lazy_static::lazy_static! { + static ref LIB_BASENAME: regex::Regex = regex::Regex::new(r"^lib(.*)\.(a|so|dylib)").unwrap(); + } + let mut is_msvc = false; if let Ok(target) = env::var("TARGET") { if target.contains("msvc") { @@ -669,7 +678,28 @@ impl Library { self.include_paths.push(PathBuf::from(inc)); } } - _ => (), + _ => { + let path = std::path::Path::new(part); + if path.is_file() { + // Cargo doesn't have a means to directly specify a file path to link, + // so split up the path into the parent directory and library name. + if let Some(dir) = path.parent() { + let link_search = format!("rustc-link-search={}", dir.display()); + config.print_metadata(&link_search); + } + if let Some(file_name) = path.file_name() { + // libQt5Core.a becomes Qt5Core + // libQt5Core.so.5 becomes Qt5Core + if let Some(captures) = + LIB_BASENAME.captures(&file_name.to_string_lossy()) + { + let lib_basename = captures.get(1).unwrap().as_str(); + let link_lib = format!("rustc-link-lib={}", lib_basename); + config.print_metadata(&link_lib); + } + } + } + } } }