diff --git a/clamav-sys/README.md b/clamav-sys/README.md index 869cff4ed0..0a7a549afc 100644 --- a/clamav-sys/README.md +++ b/clamav-sys/README.md @@ -62,3 +62,13 @@ with newer ClamAV versions. No attempt at preserving downward compatibility (using a `libclamav-sys` with a version number greater than ClamAV's) is made. + +## Packaging + +In order to execute `cargo package` or `cargo publish`, there must be an +installed copy of the ClamAV include headers and libraries available. For +Unix-like environments, this means that the `pkg-config` utility must be able +to locate the `libclamav` package. As such, ensure that `PKG_CONFIG_PATH` is +set correctly when packaging. It is not critical that the installed copy +exactly match the version in the source tree, as compilation during packaging +is done only as a verification step. diff --git a/clamav-sys/build.rs b/clamav-sys/build.rs index 84d46f0d4e..e4b7defb25 100644 --- a/clamav-sys/build.rs +++ b/clamav-sys/build.rs @@ -139,6 +139,7 @@ fn generate_bindings( bindings = bindings.allowlist_var(constant); } + // TODO: this wrapper probably isn't necessary. clamav.h could simply be located bindings = bindings .header("wrapper.h") // Tell cargo to invalidate the built crate whenever any of the @@ -166,25 +167,32 @@ fn cargo_common() { } fn main() -> anyhow::Result<()> { + cargo_common(); + let mut include_paths = vec![]; // Test whether being built as part of ClamAV source let local_include_path = local_clamav_include_path(); + if let Some(path) = &local_include_path { + eprintln!("Local ClamAV include path: {path:?}",); + } + eprintln!( + "Building as part of ClamAV: {:?}", + building_under_clamav_cmake() + ); + eprintln!("Maintainer mode: {:?}", in_maintainer_mode()); // Generate temporary path for the generated "internal" module let mut output_path_intmod = PathBuf::from(env::var("OUT_DIR")?); output_path_intmod.push("sys.rs"); - if let Some(include_path) = &local_include_path { - // It seems we're being compiled from within the ClamAV source tree. - // Confirm that clamav.h is there, too - - include_paths.push(include_path.clone()); - - build_internal::bindgen_internal(&output_path_intmod)?; + // Find headers + if let Some(path) = &local_include_path { + include_paths.push(path.clone()); } else { - // This crate is being referenced from an external project. Utilize the - // system-installed copy of libclamav (as located using pkg-config). + // This crate is being referenced from an external project that doesn't + // have access to the ClamAV source tree. Utilize the system-installed + // copy of libclamav (as located using pkg-config). #[cfg(not(windows))] { @@ -226,7 +234,11 @@ fn main() -> anyhow::Result<()> { include_paths.push(openssl_include); } }; + } + if building_under_clamav_cmake() { + build_internal::bindgen_internal(&output_path_intmod)?; + } else { // Build a vestigial `sys` module, as there will be no access to // internal APIs. let mut fh = std::fs::File::create(&output_path_intmod)?; @@ -236,8 +248,7 @@ fn main() -> anyhow::Result<()> { // Write the bindings to the $OUT_DIR/bindings.rs file. let mut output_path = PathBuf::from(env::var("OUT_DIR").unwrap()); output_path.push("bindings.rs"); - if local_include_path.is_none() || (local_include_path.is_some() && in_maintainer_mode()) { - cargo_common(); + if !building_under_clamav_cmake() || (local_include_path.is_some() && in_maintainer_mode()) { generate_bindings( &output_path, &|builder: bindgen::Builder| -> bindgen::Builder { @@ -250,14 +261,19 @@ fn main() -> anyhow::Result<()> { builder }, ); - // And place a copy in the source tree (for potential check-in) - std::fs::copy(&output_path, BINDGEN_OUTPUT_FILE)?; } else { - // Otherwise, just copy the pre-generated file to the specified - // location. + // If building within ClamAV and not in maintainer mode, just copy the + // "cached" version, as libclang may not be available. std::fs::copy(BINDGEN_OUTPUT_FILE, &output_path)?; } + if in_maintainer_mode() { + // Copy the pre-generated file to the specified location. This should + // *not* be done when packaging `clamav-sys`, as it will touch the + // source tree, and `cargo package` will report an error. + std::fs::copy(&output_path, BINDGEN_OUTPUT_FILE)?; + } + Ok(()) } @@ -282,6 +298,16 @@ fn local_clamav_include_path() -> Option { None } +/// Return whether "maintiner mode" has been enabled in a ClamAV build. pub(crate) fn in_maintainer_mode() -> bool { env::var("MAINTAINER_MODE").unwrap_or_default() == "ON" } + +/// Return whether or not this crate's build is being performed as part of a ClamAV build +pub(crate) fn building_under_clamav_cmake() -> bool { + // Note, PROJECT_NAME is examined rather than CMAKE_PROJECT_NAME, as it's + // *possible* for a ClamAV build to be embedded within another CMake-based + // build, which would have a global CMAKE_PROJECT_NAME that is *not* + // "ClamAV" + env::var("PROJECT_NAME").unwrap_or_default() == "ClamAV" +} diff --git a/cmake/FindRust.cmake b/cmake/FindRust.cmake index 3f29331178..e38cc6fab0 100644 --- a/cmake/FindRust.cmake +++ b/cmake/FindRust.cmake @@ -287,8 +287,8 @@ function(add_rust_library) if("${CMAKE_OSX_ARCHITECTURES}" MATCHES "^(arm64;x86_64|x86_64;arm64)$") add_custom_command( OUTPUT "${OUTPUT}" - COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "PROJECT_NAME='${PROJECT_NAME}'" "CMAKE_PROJECT_NAME='${CMAKE_PROJECT_NAME}'" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "MAINTAINER_MODE=${MAINTAINER_MODE}" "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --target=x86_64-apple-darwin - COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "PROJECT_NAME='${PROJECT_NAME}'" "CMAKE_PROJECT_NAME='${CMAKE_PROJECT_NAME}'" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "MAINTAINER_MODE=${MAINTAINER_MODE}" "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --target=aarch64-apple-darwin + COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "PROJECT_NAME=${PROJECT_NAME}" "CMAKE_PROJECT_NAME=${CMAKE_PROJECT_NAME}" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "MAINTAINER_MODE=${MAINTAINER_MODE}" "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --target=x86_64-apple-darwin + COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "PROJECT_NAME=${PROJECT_NAME}" "CMAKE_PROJECT_NAME=${CMAKE_PROJECT_NAME}" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "MAINTAINER_MODE=${MAINTAINER_MODE}" "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --target=aarch64-apple-darwin COMMAND ${CMAKE_COMMAND} -E make_directory "${ARGS_BINARY_DIRECTORY}/${RUST_COMPILER_TARGET}/${CARGO_BUILD_TYPE}" COMMAND lipo -create ${ARGS_BINARY_DIRECTORY}/x86_64-apple-darwin/${CARGO_BUILD_TYPE}/lib${ARGS_TARGET}.a ${ARGS_BINARY_DIRECTORY}/aarch64-apple-darwin/${CARGO_BUILD_TYPE}/lib${ARGS_TARGET}.a -output "${OUTPUT}" WORKING_DIRECTORY "${ARGS_SOURCE_DIRECTORY}" @@ -297,14 +297,14 @@ function(add_rust_library) elseif("${CMAKE_OSX_ARCHITECTURES}" MATCHES "^(arm64)$") add_custom_command( OUTPUT "${OUTPUT}" - COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "PROJECT_NAME='${PROJECT_NAME}'" "CMAKE_PROJECT_NAME='${CMAKE_PROJECT_NAME}'" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "MAINTAINER_MODE=${MAINTAINER_MODE}" "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --target=aarch64-apple-darwin + COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "PROJECT_NAME=${PROJECT_NAME}" "CMAKE_PROJECT_NAME=${CMAKE_PROJECT_NAME}" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "MAINTAINER_MODE=${MAINTAINER_MODE}" "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --target=aarch64-apple-darwin WORKING_DIRECTORY "${ARGS_SOURCE_DIRECTORY}" DEPENDS ${LIB_SOURCES} COMMENT "Building ${ARGS_TARGET} in ${ARGS_BINARY_DIRECTORY} with: ${cargo_EXECUTABLE} ${MY_CARGO_ARGS_STRING}") elseif("${CMAKE_OSX_ARCHITECTURES}" MATCHES "^(x86_64)$") add_custom_command( OUTPUT "${OUTPUT}" - COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "PROJECT_NAME='${PROJECT_NAME}'" "CMAKE_PROJECT_NAME='${CMAKE_PROJECT_NAME}'" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "MAINTAINER_MODE=${MAINTAINER_MODE}" "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --target=x86_64-apple-darwin + COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "PROJECT_NAME=${PROJECT_NAME}" "CMAKE_PROJECT_NAME=${CMAKE_PROJECT_NAME}" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "MAINTAINER_MODE=${MAINTAINER_MODE}" "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --target=x86_64-apple-darwin COMMAND ${CMAKE_COMMAND} -E make_directory "${ARGS_BINARY_DIRECTORY}/${RUST_COMPILER_TARGET}/${CARGO_BUILD_TYPE}" WORKING_DIRECTORY "${ARGS_SOURCE_DIRECTORY}" DEPENDS ${LIB_SOURCES} @@ -312,7 +312,7 @@ function(add_rust_library) else() add_custom_command( OUTPUT "${OUTPUT}" - COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "PROJECT_NAME='${PROJECT_NAME}'" "CMAKE_PROJECT_NAME='${CMAKE_PROJECT_NAME}'" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "MAINTAINER_MODE=${MAINTAINER_MODE}" "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} + COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=build" "PROJECT_NAME=${PROJECT_NAME}" "CMAKE_PROJECT_NAME=${CMAKE_PROJECT_NAME}" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "MAINTAINER_MODE=${MAINTAINER_MODE}" "CARGO_INCLUDE_DIRECTORIES=\"${ARGS_INCLUDE_DIRECTORIES}\"" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} WORKING_DIRECTORY "${ARGS_SOURCE_DIRECTORY}" DEPENDS ${LIB_SOURCES} COMMENT "Building ${ARGS_TARGET} in ${ARGS_BINARY_DIRECTORY} with: ${cargo_EXECUTABLE} ${MY_CARGO_ARGS_STRING}") @@ -362,7 +362,7 @@ function(add_rust_test) list(JOIN MY_CARGO_ARGS " " MY_CARGO_ARGS_STRING) if(ARGS_PRECOMPILE_TESTS) - list(APPEND ARGS_PRECOMPILE_ENVIRONMENT "CARGO_CMD=test" "PROJECT_NAME='${PROJECT_NAME}'" "CMAKE_PROJECT_NAME='${CMAKE_PROJECT_NAME}'" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}") + list(APPEND ARGS_PRECOMPILE_ENVIRONMENT "CARGO_CMD=test" "PROJECT_NAME=${PROJECT_NAME}" "CMAKE_PROJECT_NAME=${CMAKE_PROJECT_NAME}" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}") add_custom_target(${ARGS_NAME}_tests ALL COMMAND ${CMAKE_COMMAND} -E env ${ARGS_PRECOMPILE_ENVIRONMENT} ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --color always --no-run DEPENDS ${ARGS_PRECOMPILE_DEPENDS} @@ -372,7 +372,7 @@ function(add_rust_test) add_test( NAME ${ARGS_NAME} - COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=test" "PROJECT_NAME='${PROJECT_NAME}'" "CMAKE_PROJECT_NAME='${CMAKE_PROJECT_NAME}'" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --color always + COMMAND ${CMAKE_COMMAND} -E env "CARGO_CMD=test" "PROJECT_NAME=${PROJECT_NAME}" "CMAKE_PROJECT_NAME=${CMAKE_PROJECT_NAME}" "CARGO_TARGET_DIR=${ARGS_BINARY_DIRECTORY}" "RUSTFLAGS=${RUSTFLAGS}" ${cargo_EXECUTABLE} ${MY_CARGO_ARGS} --color always WORKING_DIRECTORY ${ARGS_SOURCE_DIRECTORY} ) endfunction()