CMake linking fixes and rework

This commit is contained in:
Luke Street
2026-02-20 22:30:21 -07:00
parent 03b14e33c2
commit 44ce6acbfb
3 changed files with 63 additions and 121 deletions
+14 -17
View File
@@ -41,7 +41,9 @@ set(NOD_IMPORT_ARGS NO_DEFAULT_FEATURES)
if (NOD_FEATURES)
list(APPEND NOD_IMPORT_ARGS FEATURES ${NOD_FEATURES})
endif()
if (DEFINED BUILD_SHARED_LIBS AND NOT BUILD_SHARED_LIBS)
list(APPEND NOD_IMPORT_ARGS CRATE_TYPES staticlib)
endif()
# Import the nod-ffi crate using Corrosion.
corrosion_import_crate(
MANIFEST_PATH "${CMAKE_CURRENT_SOURCE_DIR}/nod-ffi/Cargo.toml"
@@ -52,37 +54,32 @@ corrosion_import_crate(
if (NOD_COMPRESS_BZIP2)
nod_require_bzip2(_nod_bzip2_target)
target_link_libraries(nod_ffi INTERFACE "${_nod_bzip2_target}")
if (TARGET bz2_static)
corrosion_add_target_local_rustflags(
nod_ffi
"-L$<TARGET_LINKER_FILE_DIR:bz2_static>"
"-lstatic=bz2"
)
if (TARGET _cargo-build_nod_ffi)
add_dependencies(_cargo-build_nod_ffi bz2_static)
endif()
else()
nod_resolve_corrosion_link_input(_nod_bzip2_rust_link "${_nod_bzip2_target}" "bz2")
corrosion_link_libraries(nod_ffi "${_nod_bzip2_rust_link}")
endif()
nod_resolve_corrosion_link_input(_nod_bzip2_rust_link "${_nod_bzip2_target}" "bz2")
# Global flags are needed since the #[link] directives are in the `nod` dependency crate,
# not in nod-ffi itself.
corrosion_add_target_rustflags(nod_ffi "-L" "$<TARGET_LINKER_FILE_DIR:${_nod_bzip2_rust_link}>")
add_dependencies(_cargo-build_nod_ffi "${_nod_bzip2_rust_link}")
endif()
if (NOD_COMPRESS_LZMA)
nod_require_liblzma(_nod_liblzma_target)
target_link_libraries(nod_ffi INTERFACE "${_nod_liblzma_target}")
nod_resolve_corrosion_link_input(_nod_liblzma_rust_link "${_nod_liblzma_target}" "lzma")
corrosion_link_libraries(nod_ffi "${_nod_liblzma_rust_link}")
corrosion_add_target_rustflags(nod_ffi "-L" "$<TARGET_LINKER_FILE_DIR:${_nod_liblzma_rust_link}>")
add_dependencies(_cargo-build_nod_ffi "${_nod_liblzma_rust_link}")
endif()
if (NOD_COMPRESS_ZLIB)
nod_require_zlib(_nod_zlib_target)
target_link_libraries(nod_ffi INTERFACE "${_nod_zlib_target}")
nod_resolve_corrosion_link_input(_nod_zlib_rust_link "${_nod_zlib_target}" "z")
corrosion_link_libraries(nod_ffi "${_nod_zlib_rust_link}")
corrosion_add_target_rustflags(nod_ffi "-L" "$<TARGET_LINKER_FILE_DIR:${_nod_zlib_rust_link}>")
add_dependencies(_cargo-build_nod_ffi "${_nod_zlib_rust_link}")
endif()
if (NOD_COMPRESS_ZSTD)
nod_require_zstd(_nod_zstd_target)
target_link_libraries(nod_ffi INTERFACE "${_nod_zstd_target}")
nod_resolve_corrosion_link_input(_nod_zstd_rust_link "${_nod_zstd_target}" "zstd")
corrosion_link_libraries(nod_ffi "${_nod_zstd_rust_link}")
corrosion_add_target_rustflags(nod_ffi "-L" "$<TARGET_LINKER_FILE_DIR:${_nod_zstd_rust_link}>")
add_dependencies(_cargo-build_nod_ffi "${_nod_zstd_rust_link}")
endif()
target_sources(nod_ffi INTERFACE
+37 -100
View File
@@ -17,16 +17,6 @@ function(nod_first_available_target out_var)
set("${out_var}" "" PARENT_SCOPE)
endfunction()
function(nod_bind_interface_target interface_target implementation_target)
if (NOT TARGET "${interface_target}")
add_library("${interface_target}" INTERFACE IMPORTED GLOBAL)
set_target_properties(
"${interface_target}"
PROPERTIES INTERFACE_LINK_LIBRARIES "${implementation_target}"
)
endif()
endfunction()
# Corrosion's target-based rustflags path uses TARGET_LINKER_FILE_BASE_NAME,
# which can produce invalid names for imported namespaced targets. For imported
# targets, create a local imported wrapper with a controlled OUTPUT_NAME.
@@ -54,6 +44,13 @@ function(nod_resolve_corrosion_link_input out_var input_link rust_link_name)
endif()
endforeach()
if (_loc AND IS_ABSOLUTE "${_loc}")
# Derive OUTPUT_NAME from the actual filename to ensure
# the correct -l flag is passed on all platforms.
# (e.g. zlib.lib on MSVC vs libz.a on Unix)
get_filename_component(_stem "${_loc}" NAME_WE)
if (NOT MSVC AND _stem MATCHES "^lib(.+)$")
set(_stem "${CMAKE_MATCH_1}")
endif()
set(_wrapper_target "nod_corrosion_link_${rust_link_name}")
if (NOT TARGET "${_wrapper_target}")
add_library("${_wrapper_target}" UNKNOWN IMPORTED GLOBAL)
@@ -62,7 +59,7 @@ function(nod_resolve_corrosion_link_input out_var input_link rust_link_name)
"${_wrapper_target}"
PROPERTIES
IMPORTED_LOCATION "${_loc}"
OUTPUT_NAME "${rust_link_name}"
OUTPUT_NAME "${_stem}"
)
set("${out_var}" "${_wrapper_target}" PARENT_SCOPE)
return()
@@ -73,24 +70,23 @@ function(nod_resolve_corrosion_link_input out_var input_link rust_link_name)
endfunction()
function(nod_require_bzip2 out_target)
nod_first_available_target(_bzip2_target bz2_static bz2 BZip2::BZip2)
nod_first_available_target(_bzip2_target bz2_static BZip2::BZip2 bz2)
if (_bzip2_target)
if (NOT TARGET BZip2::BZip2)
nod_bind_interface_target(BZip2::BZip2 "${_bzip2_target}")
endif()
message(STATUS "nod: Linking bzip2 target ${_bzip2_target}")
set("${out_target}" "${_bzip2_target}" PARENT_SCOPE)
return()
endif()
# To force vendoring from the CLI, pass: -DCMAKE_DISABLE_FIND_PACKAGE_BZip2=ON
find_package(BZip2 QUIET)
nod_first_available_target(_bzip2_target bz2_static bz2 BZip2::BZip2)
nod_first_available_target(_bzip2_target bz2_static BZip2::BZip2 bz2)
if (_bzip2_target)
message(STATUS "nod: Linking bzip2 target ${_bzip2_target}")
set("${out_target}" "${_bzip2_target}" PARENT_SCOPE)
return()
endif()
message(STATUS "BZip2 not found; fetching bzip2 ${NOD_BZIP2_GIT_TAG}")
message(STATUS "nod: Fetching vendored bzip2 ${NOD_BZIP2_GIT_TAG}")
set(ENABLE_LIB_ONLY ON CACHE INTERNAL "")
set(ENABLE_APP OFF CACHE INTERNAL "")
set(ENABLE_TESTS OFF CACHE INTERNAL "")
@@ -104,47 +100,28 @@ function(nod_require_bzip2 out_target)
GIT_TAG "${NOD_BZIP2_GIT_TAG}"
)
FetchContent_MakeAvailable(nod_bzip2)
if (TARGET bz2_static)
# Make the static archive name match `#[link(name = "bz2")]` in Rust.
set_target_properties(
bz2_static
PROPERTIES
OUTPUT_NAME bz2
ARCHIVE_OUTPUT_NAME bz2
)
endif()
nod_first_available_target(_bzip2_target bz2_static bz2 BZip2::BZip2)
if (NOT _bzip2_target)
message(FATAL_ERROR "Unable to provide a usable BZip2 target after vendoring bzip2")
endif()
if (NOT TARGET BZip2::BZip2)
nod_bind_interface_target(BZip2::BZip2 "${_bzip2_target}")
endif()
set("${out_target}" "${_bzip2_target}" PARENT_SCOPE)
set_target_properties(bz2_static PROPERTIES OUTPUT_NAME bz2)
set("${out_target}" bz2_static PARENT_SCOPE)
endfunction()
function(nod_require_liblzma out_target)
nod_first_available_target(_lzma_target liblzma liblzma::liblzma LibLZMA::LibLZMA)
nod_first_available_target(_lzma_target LibLZMA::LibLZMA liblzma::liblzma liblzma)
if (_lzma_target)
if (NOT TARGET LibLZMA::LibLZMA)
nod_bind_interface_target(LibLZMA::LibLZMA "${_lzma_target}")
endif()
message(STATUS "nod: Linking lzma target ${_lzma_target}")
set("${out_target}" "${_lzma_target}" PARENT_SCOPE)
return()
endif()
# To force vendoring from the CLI, pass: -DCMAKE_DISABLE_FIND_PACKAGE_LibLZMA=ON
find_package(LibLZMA QUIET)
nod_first_available_target(_lzma_target liblzma liblzma::liblzma LibLZMA::LibLZMA)
nod_first_available_target(_lzma_target LibLZMA::LibLZMA liblzma::liblzma liblzma)
if (_lzma_target)
if (NOT TARGET LibLZMA::LibLZMA)
nod_bind_interface_target(LibLZMA::LibLZMA "${_lzma_target}")
endif()
message(STATUS "nod: Linking lzma target ${_lzma_target}")
set("${out_target}" "${_lzma_target}" PARENT_SCOPE)
return()
endif()
message(STATUS "LibLZMA not found; fetching xz ${NOD_XZ_GIT_TAG}")
message(STATUS "nod: Fetching vendored lzma ${NOD_XZ_GIT_TAG}")
set(XZ_NLS OFF CACHE INTERNAL "")
set(XZ_DOC OFF CACHE INTERNAL "")
set(XZ_DOXYGEN OFF CACHE INTERNAL "")
@@ -159,46 +136,30 @@ function(nod_require_liblzma out_target)
GIT_TAG "${NOD_XZ_GIT_TAG}"
)
FetchContent_MakeAvailable(nod_xz)
if (TARGET liblzma AND NOT TARGET liblzma::liblzma)
nod_bind_interface_target(liblzma::liblzma liblzma)
endif()
if (TARGET liblzma::liblzma AND NOT TARGET LibLZMA::LibLZMA)
nod_bind_interface_target(LibLZMA::LibLZMA liblzma::liblzma)
endif()
nod_first_available_target(_lzma_target liblzma liblzma::liblzma LibLZMA::LibLZMA)
if (NOT _lzma_target)
message(FATAL_ERROR "Unable to provide a usable LibLZMA target after vendoring xz")
endif()
if (NOT TARGET LibLZMA::LibLZMA)
nod_bind_interface_target(LibLZMA::LibLZMA "${_lzma_target}")
endif()
set("${out_target}" "${_lzma_target}" PARENT_SCOPE)
set("${out_target}" liblzma PARENT_SCOPE)
endfunction()
function(nod_require_zlib out_target)
nod_first_available_target(_zlib_target zlib zlibstatic ZLIB::ZLIB)
nod_first_available_target(_zlib_target ZLIB::ZLIBSTATIC ZLIB::ZLIB zlibstatic zlib)
if (_zlib_target)
if (NOT TARGET ZLIB::ZLIB)
nod_bind_interface_target(ZLIB::ZLIB "${_zlib_target}")
endif()
message(STATUS "nod: Linking zlib target ${_zlib_target}")
set("${out_target}" "${_zlib_target}" PARENT_SCOPE)
return()
endif()
# To force vendoring from the CLI, pass: -DCMAKE_DISABLE_FIND_PACKAGE_ZLIB=ON
find_package(ZLIB QUIET)
nod_first_available_target(_zlib_target zlib zlibstatic ZLIB::ZLIB)
nod_first_available_target(_zlib_target ZLIB::ZLIBSTATIC ZLIB::ZLIB zlibstatic zlib)
if (_zlib_target)
if (NOT TARGET ZLIB::ZLIB)
nod_bind_interface_target(ZLIB::ZLIB "${_zlib_target}")
endif()
message(STATUS "nod: Linking zlib target ${_zlib_target}")
set("${out_target}" "${_zlib_target}" PARENT_SCOPE)
return()
endif()
message(STATUS "ZLIB not found; fetching zlib ${NOD_ZLIB_GIT_TAG}")
message(STATUS "nod: Fetching vendored zlib ${NOD_ZLIB_GIT_TAG}")
set(ZLIB_BUILD_TESTING OFF CACHE INTERNAL "")
set(ZLIB_BUILD_SHARED OFF CACHE INTERNAL)
set(ZLIB_BUILD_STATIC ON CACHE INTERNAL)
set(ZLIB_INSTALL OFF CACHE INTERNAL "")
FetchContent_Declare(
nod_zlib
@@ -206,28 +167,17 @@ function(nod_require_zlib out_target)
GIT_TAG "${NOD_ZLIB_GIT_TAG}"
)
FetchContent_MakeAvailable(nod_zlib)
nod_first_available_target(_zlib_target zlib zlibstatic ZLIB::ZLIB)
if (NOT _zlib_target)
message(FATAL_ERROR "Unable to provide a usable ZLIB target after vendoring zlib")
endif()
if (NOT TARGET ZLIB::ZLIB)
nod_bind_interface_target(ZLIB::ZLIB "${_zlib_target}")
endif()
set("${out_target}" "${_zlib_target}" PARENT_SCOPE)
set("${out_target}" ZLIB::ZLIBSTATIC PARENT_SCOPE)
endfunction()
function(nod_require_zstd out_target)
nod_first_available_target(
_zstd_target
libzstd_static
libzstd_shared
zstd::libzstd_static
zstd::libzstd_shared
libzstd
zstd::libzstd
)
if (_zstd_target)
message(STATUS "nod: Linking zstd target ${_zstd_target}")
set("${out_target}" "${_zstd_target}" PARENT_SCOPE)
return()
endif()
@@ -236,22 +186,22 @@ function(nod_require_zstd out_target)
find_package(zstd QUIET)
nod_first_available_target(
_zstd_target
libzstd_static
libzstd_shared
zstd::libzstd_static
zstd::libzstd_shared
libzstd
zstd::libzstd
)
if (_zstd_target)
message(STATUS "nod: Linking zstd target ${_zstd_target}")
set("${out_target}" "${_zstd_target}" PARENT_SCOPE)
return()
endif()
message(STATUS "Zstandard not found; fetching zstd ${NOD_ZSTD_GIT_TAG}")
message(STATUS "nod: Fetching vendored zstd ${NOD_ZSTD_GIT_TAG}")
set(ZSTD_BUILD_STATIC ON CACHE INTERNAL "")
set(ZSTD_BUILD_SHARED OFF CACHE INTERNAL "")
set(ZSTD_BUILD_DICTBUILDER OFF CACHE INTERNAL "")
set(ZSTD_BUILD_PROGRAMS OFF CACHE INTERNAL "")
set(ZSTD_BUILD_TESTS OFF CACHE INTERNAL "")
set(ZSTD_BUILD_CONTRIB OFF CACHE INTERNAL "")
set(ZSTD_BUILD_TESTS OFF CACHE INTERNAL "")
FetchContent_Declare(
nod_zstd
GIT_REPOSITORY https://github.com/facebook/zstd.git
@@ -259,18 +209,5 @@ function(nod_require_zstd out_target)
SOURCE_SUBDIR build/cmake
)
FetchContent_MakeAvailable(nod_zstd)
nod_first_available_target(
_zstd_target
libzstd_static
libzstd_shared
zstd::libzstd_static
zstd::libzstd_shared
libzstd
zstd::libzstd
)
if (NOT _zstd_target)
message(FATAL_ERROR "Unable to provide a usable zstd target after vendoring zstd")
endif()
set("${out_target}" "${_zstd_target}" PARENT_SCOPE)
set("${out_target}" libzstd_static PARENT_SCOPE)
endfunction()
+12 -4
View File
@@ -138,7 +138,8 @@ mod zlib_raw {
pub const Z_OK: c_int = 0;
pub const Z_BUF_ERROR: c_int = -5;
#[link(name = "z")]
#[cfg_attr(not(target_env = "msvc"), link(name = "z"))]
#[cfg_attr(target_env = "msvc", link(name = "zlib", kind = "static"))]
unsafe extern "C" {
pub fn uncompress(
dest: *mut u8,
@@ -245,7 +246,12 @@ mod bzip2_raw {
macro_rules! abi_compat {
($(pub fn $name:ident($($arg:ident: $t:ty),*) -> $ret:ty,)*) => {
#[cfg(windows)]
#[cfg(all(windows, target_env = "msvc"))]
#[link(name = "bz2", kind = "static")]
unsafe extern "system" {
$(pub fn $name($($arg: $t),*) -> $ret;)*
}
#[cfg(all(windows, not(target_env = "msvc")))]
#[link(name = "bz2")]
unsafe extern "system" {
$(pub fn $name($($arg: $t),*) -> $ret;)*
@@ -386,7 +392,8 @@ mod zstd_raw {
pub const ZSTD_CONTENTSIZE_UNKNOWN: i32 = -1;
pub const ZSTD_CONTENTSIZE_ERROR: i32 = -2;
#[link(name = "zstd")]
#[cfg_attr(not(target_env = "msvc"), link(name = "zstd"))]
#[cfg_attr(target_env = "msvc", link(name = "zstd", kind = "static"))]
unsafe extern "C" {
pub fn ZSTD_compress(
dst: *mut c_void,
@@ -551,7 +558,8 @@ mod lzma_raw {
pub type lzma_allocator = c_void;
#[link(name = "lzma")]
#[cfg_attr(not(target_env = "msvc"), link(name = "lzma"))]
#[cfg_attr(target_env = "msvc", link(name = "lzma", kind = "static"))]
unsafe extern "C" {
pub fn lzma_raw_buffer_encode(
filters: *const lzma_filter,