Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support static linking of ctranslate2 #148

Merged
merged 14 commits into from
May 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/ctranslate2-bindings/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/target
/Cargo.lock
/build
16 changes: 16 additions & 0 deletions crates/ctranslate2-bindings/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.7)

project(ctranslate2_bindings)

add_subdirectory(CTranslate2)

add_library(dummy
src/dummy.cc
)

target_link_libraries(dummy
PRIVATE ctranslate2
)

include(cmake/export_libs.cmake)
export_all_target_libs(dummy)
1 change: 1 addition & 0 deletions crates/ctranslate2-bindings/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ tokenizers = "0.13.3"
bindgen = "0.53.1"
cxx-build = "1.0"
cmake = "0.1"
rust-cxx-cmake-bridge = { path = "../rust-cxx-cmake-bridge" }
40 changes: 22 additions & 18 deletions crates/ctranslate2-bindings/build.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
use cmake::Config;
use rust_cxx_cmake_bridge::read_cmake_generated;

fn main() {
let mut config = Config::new("CTranslate2");
let mut config = Config::new(".");
config
.define("CMAKE_BUILD_TYPE", "Release")
.define("BUILD_CLI", "OFF")
.define("BUILD_SHARED_LIBS", "ON")
.define("CMAKE_INSTALL_RPATH_USE_LINK_PATH", "ON");
.define("CMAKE_INSTALL_RPATH_USE_LINK_PATH", "ON")
.define("BUILD_SHARED_LIBS", "OFF");

if cfg!(target_os = "macos") {
config
.define("CMAKE_OSX_ARCHITECTURES", "arm64")
.define("WITH_ACCELERATE", "ON")
.define("WITH_MKL", "OFF")
.define("OPENMP_RUNTIME", "NONE")
.define("WITH_RUY", "ON");
} else if cfg!(target_os = "linux") {
if cfg!(target_os = "linux") {
config
.define("WITH_CUDA", "ON")
.define("WITH_CUDNN", "ON")
Expand All @@ -24,16 +18,26 @@ fn main() {
.define("OPENMP_RUNTIME", "COMP")
.cxxflag("-msse4.1")
.define("CUDA_NVCC_FLAGS", "-Xfatbin=-compress-all")
.define("CUDA_ARCH_LIST", "Common");
}
.define("CUDA_ARCH_LIST", "Common")
} else if cfg!(target_os = "macos") {
config
.define("CMAKE_OSX_ARCHITECTURES", "arm64")
.define("WITH_ACCELERATE", "ON")
.define("WITH_MKL", "OFF")
.define("OPENMP_RUNTIME", "NONE")
.define("WITH_RUY", "ON")
} else {
panic!("Invalid target")
};

let dst = config.build();

println!(
"cargo:rustc-link-search=native={}",
dst.join("lib").display()
);
println!("cargo:rustc-link-lib=ctranslate2");
// Read static lib from generated deps.
let cmake_generated_libs_str = std::fs::read_to_string(
&format!("/{}/build/cmake_generated_libs", dst.display()).to_string(),
)
.unwrap();
read_cmake_generated(&cmake_generated_libs_str);

// Tell cargo to invalidate the built crate whenever the wrapper changes
println!("cargo:rerun-if-changed=include/ctranslate2.h");
Expand Down
25 changes: 25 additions & 0 deletions crates/ctranslate2-bindings/cmake/debug_cmake.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#! /bin/bash

set -e
set -x

UNAME="$(uname -s)"
case "${UNAME}" in
Linux*) MACHINE=linux;;
Darwin*) MACHINE=macos;;
*) exit 1;;
esac

rm -rf build
mkdir build && cd build

if [[ "$MACHINE" == "macos" ]]; then
CMAKE_EXTRA_OPTIONS='-DCMAKE_OSX_ARCHITECTURES=arm64 -DWITH_ACCELERATE=ON -DWITH_MKL=OFF -DOPENMP_RUNTIME=NONE -DWITH_RUY=ON'
elif [[ "$MACHINE" == "linux" ]]; then
CMAKE_EXTRA_OPTIONS='-DWITH_CUDA=ON -DWITH_CUDNN=ON -DWITH_MKL=ON -DWITH_DNNL=ON -DOPENMP_RUNTIME=COMP -DCUDA_NVCC_FLAGS=-Xfatbin=-compress-all -DCUDA_ARCH_LIST=Common -DCXXFLAGS=-msse4.1'
fi


cmake -DBULID_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -DBUILD_CLI=OFF -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON $CMAKE_EXTRA_OPTIONS ..

"$@"
98 changes: 98 additions & 0 deletions crates/ctranslate2-bindings/cmake/export_libs.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
################################################################################

# WARNING: to list the system libraries(ie IMPORTED) you MUST set:
# set_target_properties(your_lib PROPERTIES IMPORTED_GLOBAL TRUE)
# just after the find_package call
# cf https://gitlab.kitware.com/cmake/cmake/-/issues/17256
#
# https://stackoverflow.com/questions/32756195/recursive-list-of-link-libraries-in-cmake
# https://stackoverflow.com/questions/32197663/how-can-i-remove-the-the-location-property-may-not-be-read-from-target-error-i
function(_get_link_libraries OUTPUT_LIST TARGET)
list(APPEND VISITED_TARGETS ${TARGET})

# DO NOT switch on IMPORTED or not
# An INTERFACE library CAN have LINK_LIBRARIES!
# get_target_property(IMPORTED ${TARGET} IMPORTED)
set(LIBS "")
get_target_property(LIBS_1 ${TARGET} INTERFACE_LINK_LIBRARIES)
get_target_property(LIBS_2 ${TARGET} LINK_LIBRARIES)
list(APPEND LIBS ${LIBS_1} ${LIBS_2})

set(LIB_FILES "")

foreach(LIB ${LIBS})
if (TARGET ${LIB})
list(FIND VISITED_TARGETS ${LIB} VISITED)
if (${VISITED} EQUAL -1)
# OLD: get_target_property(LIB_FILE ${LIB} LOCATION)
# NEW:
_get_link_libraries(LINK_LIB_FILES ${LIB})
set(LIB_FILE ${LIB})
list(APPEND LIB_FILES ${LINK_LIB_FILES})
list(APPEND LIB_FILES ${LIB_FILE})
endif()
elseif(EXISTS ${LIB})
set(LIB_FILE ${LIB})
list(APPEND LIB_FILES ${LIB_FILE})
endif()
endforeach()

set(VISITED_TARGETS ${VISITED_TARGETS} PARENT_SCOPE)
set(${OUTPUT_LIST} ${LIB_FILES} PARENT_SCOPE)
endfunction()

################################################################################

function(export_all_target_libs TARGET)
# NOTE: get_target_property(CIRCUIT_LIB_LINK_LIBRARIES a_target LINK_LIBRARIES) is NOT transitive
# This function will return eg: "$<TARGET_FILE:rust_cxx>;$<TARGET_FILE:circuit_lib>;"
# b/c generator expression are evaluated LATER
# cf https://stackoverflow.com/questions/59226127/cmake-generator-expression-how-to-get-target-file-property-on-list-of-targets
set(ALL_LINK_LIBRARIES "")
_get_link_libraries(ALL_LINK_LIBRARIES ${TARGET})

message(STATUS "ALL_LINK_LIBRARIES : ${ALL_LINK_LIBRARIES}")

set(ALL_LIBS "")
set(ALL_EXTERNAL_LIBS "")
# TODO move that back into get_link_libraries
# NOTE: we MUST do it in 2 steps:
# - collect all the LINK_LIBRARIES recursively
# - loop on those and get their TARGET_FILE (if not INTERFACE_LIBRARY)
# That is b/c in get_link_libraries a INTERFACE_LIBRARY CAN have link_libraries
# but we CAN NOT evaluate generator expressions at this time.
foreach(LIB ${ALL_LINK_LIBRARIES})
# MUST skip INTERFACE else:
# CMake Error at src/CMakeLists.txt:136 (add_custom_command):
# Error evaluating generator expression:
# $<TARGET_FILE:rust_cxx>
# Target "rust_cxx" is not an executable or library.
# SHARED_LIBRARY,INTERFACE_LIBRARY,STATIC_LIBRARY
#
if (TARGET ${LIB})
get_target_property(LIB_TYPE ${LIB} TYPE)
message(STATUS "LIB_TYPE : ${LIB} = ${LIB_TYPE}")

if(NOT ${LIB_TYPE} STREQUAL "INTERFACE_LIBRARY")
set(LIB_FILE $<TARGET_FILE:${LIB}>)
list(APPEND ALL_LIBS ${LIB_FILE})
endif()
elseif(EXISTS ${LIB})
set(LIB_FILE ${LIB})
message(STATUS "LIB_TYPE : ${LIB} = EXTERNAL")
list(APPEND ALL_LIBS ${LIB_FILE})
endif()
endforeach() # LIB ${ALL_LIBS}

message(STATUS "ALL_LIBS : ${ALL_LIBS}")

# add_custom_command(ie echoing only to stdout) works but more difficult to get from build.rs
# b/c when there is "ninja: no work to do" it will NOT echo on the console
add_custom_command(
TARGET ${TARGET}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo ${ALL_LIBS} > ${CMAKE_CURRENT_BINARY_DIR}/cmake_generated_libs
# OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cmake_generated_libs
VERBATIM
)
endfunction(export_all_target_libs)
Empty file.
8 changes: 8 additions & 0 deletions crates/rust-cxx-cmake-bridge/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "rust-cxx-cmake-bridge"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
Loading