getdeps: add rust_static_library to build Rust crate

Reviewed By: simpkins

Differential Revision: D16945510

fbshipit-source-id: a7a88cd94235e3f8c01235d7e7e500c90bde3b38
This commit is contained in:
Zeyi (Rice) Fan 2019-09-26 15:47:14 -07:00 committed by Facebook Github Bot
parent 2cd2ffbd58
commit 951b9e95f5
6 changed files with 237 additions and 0 deletions

View File

@ -0,0 +1,143 @@
include(FBCMakeParseArgs)
# This function creates an interface library target based on the static library
# built by Cargo. It will call Cargo to build a staticlib and generate a CMake
# interface library with it.
#
# You need to set `lib:crate-type = ["staticlib"]` in your Cargo.toml to make
# Cargo build static library.
#
# ```cmake
# rust_static_library(<TARGET> [CRATE <CRATE_NAME>])
# ```
#
# Parameters:
# - TARGET:
# Name of the target name. This function will create an interface library
# target with this name.
# - CRATE_NAME:
# Name of the crate. This parameter is optional. If unspecified, it will
# fallback to `${TARGET}`.
#
# This function creates two targets:
# - "${TARGET}": an interface library target contains the static library built
# from Cargo.
# - "${TARGET}.cargo": an internal custom target that invokes Cargo.
#
# If you are going to use this static library from C/C++, you will need to
# write header files for the library (or generate with cbindgen) and bind these
# headers with the interface library.
#
function(rust_static_library TARGET)
fb_cmake_parse_args(ARG "" "CRATE" "" "${ARGN}")
if(DEFINED ARG_CRATE)
set(crate_name "${ARG_CRATE}")
else()
set(crate_name "${TARGET}")
endif()
set(cargo_target "${TARGET}.cargo")
set(target_dir $<IF:$<CONFIG:Debug>,debug,release>)
set(cargo_cmd cargo build $<IF:$<CONFIG:Debug>,,--release> -p ${crate_name})
set(staticlib_name "${CMAKE_STATIC_LIBRARY_PREFIX}${crate_name}${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(rust_staticlib "${CMAKE_CURRENT_BINARY_DIR}/${target_dir}/${staticlib_name}")
if(WIN32)
# compatibility for cmd.exe
set(
cargo_cmd
set CARGO_TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR}&& ${cargo_cmd}
)
else()
set(
cargo_cmd
CARGO_TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR} ${cargo_cmd}
)
endif()
add_custom_target(
${cargo_target} ALL
COMMAND ${cargo_cmd}
COMMENT "Building Rust crate '${crate_name}'..."
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
add_library(${TARGET} INTERFACE)
add_dependencies(${TARGET} ${cargo_target})
set_target_properties(
${TARGET}
PROPERTIES
INTERFACE_STATICLIB_OUTPUT_PATH "${rust_staticlib}"
INTERFACE_INSTALL_LIBNAME
"${CMAKE_STATIC_LIBRARY_PREFIX}${crate_name}_rs${CMAKE_STATIC_LIBRARY_SUFFIX}"
)
target_link_libraries(
${TARGET}
INTERFACE "$<BUILD_INTERFACE:${rust_staticlib}>"
)
endfunction()
# This function installs the interface target generated from the function
# `rust_static_library`. Use this function if you want to export your Rust
# target to external CMake targets.
#
# ```cmake
# install_rust_static_library(
# <TARGET>
# INSTALL_DIR <INSTALL_DIR>
# [EXPORT <EXPORT_NAME>]
# )
# ```
#
# Parameters:
# - TARGET: Name of the Rust static library target.
# - EXPORT_NAME: Name of the exported target.
# - INSTALL_DIR: Path to the directory where this library will be installed.
#
function(install_rust_static_library TARGET)
fb_cmake_parse_args(ARG "" "EXPORT;INSTALL_DIR" "" "${ARGN}")
get_property(
staticlib_output_path
TARGET "${TARGET}"
PROPERTY INTERFACE_STATICLIB_OUTPUT_PATH
)
get_property(
staticlib_output_name
TARGET "${TARGET}"
PROPERTY INTERFACE_INSTALL_LIBNAME
)
if(NOT DEFINED staticlib_output_path)
message(FATAL_ERROR "Not a rust_static_library target.")
endif()
if(NOT DEFINED ARG_INSTALL_DIR)
message(FATAL_ERROR "Missing required argument.")
endif()
if(DEFINED ARG_EXPORT)
set(install_export_args EXPORT "${ARG_EXPORT}")
endif()
set(install_interface_dir "${ARG_INSTALL_DIR}")
if(NOT IS_ABSOLUTE "${install_interface_dir}")
set(install_interface_dir "\${_IMPORT_PREFIX}/${install_interface_dir}")
endif()
target_link_libraries(
${TARGET} INTERFACE
"$<INSTALL_INTERFACE:${install_interface_dir}/${staticlib_output_name}>"
)
install(
TARGETS ${TARGET}
${install_export_args}
LIBRARY DESTINATION ${ARG_INSTALL_DIR}
)
install(
FILES ${staticlib_output_path}
RENAME ${staticlib_output_name}
DESTINATION ${ARG_INSTALL_DIR}
)
endfunction()

View File

@ -0,0 +1,17 @@
# CMake configuration file for Mercurial
#
# This provides the Mercurial::* targets, which you can depend on by adding it
# to your target_link_libraries().
@PACKAGE_INIT@
set_and_check(MERCURIAL_CMAKE_DIR "@PACKAGE_CMAKE_INSTALL_DIR@")
include("${MERCURIAL_CMAKE_DIR}/mercurial-targets.cmake")
set(Mercurial_FOUND TRUE)
check_required_components(Mercurial)
if(Mercurial_FOUND AND NOT mercurial_FIND_QUIETLY)
message(STATUS "Found Mercurial: ${PACKAGE_PREFIX_DIR}")
endif()

42
CMakeLists.txt Normal file
View File

@ -0,0 +1,42 @@
cmake_minimum_required(VERSION 3.7)
# CMake include directories
set(
CMAKE_MODULE_PATH
"${CMAKE_CURRENT_SOURCE_DIR}/CMake"
"${CMAKE_CURRENT_SOURCE_DIR}/build/fbcode_builder/CMake"
${CMAKE_MODULE_PATH}
)
set(CMAKE_INSTALL_DIR lib/cmake/mercurial)
# Find dependencies
set(CMAKE_THREAD_PREFER_PTHREAD ON)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
find_package(Gflags MODULE REQUIRED)
find_package(folly CONFIG REQUIRED)
include(RustStaticLibrary)
include(CMakePackageConfigHelpers)
add_subdirectory(lib)
# install module & CMake configs
install(
EXPORT mercurial
NAMESPACE Mercurial::
FILE mercurial-targets.cmake
DESTINATION "${CMAKE_INSTALL_DIR}"
)
configure_package_config_file(
CMake/mercurial-config.cmake.in
mercurial-config.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_DIR}
PATH_VARS
CMAKE_INSTALL_DIR
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/mercurial-config.cmake
DESTINATION ${CMAKE_INSTALL_DIR}
)

1
lib/CMakeLists.txt Normal file
View File

@ -0,0 +1 @@
add_subdirectory(revisionstore)

View File

@ -0,0 +1,31 @@
rust_static_library(rust_revisionstore CRATE revisionstore)
install_rust_static_library(
rust_revisionstore
EXPORT mercurial
INSTALL_DIR lib
)
add_library(revisionstore RevisionStore.cpp)
set_target_properties(
revisionstore
PROPERTIES
PUBLIC_HEADER
RevisionStore.h
)
target_include_directories(revisionstore PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
target_link_libraries(
revisionstore
PRIVATE
rust_revisionstore
Folly::folly
)
install(
TARGETS revisionstore
EXPORT mercurial
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
PUBLIC_HEADER DESTINATION "include/scm/hg/lib/revisionstore/"
)

View File

@ -31,3 +31,6 @@ rand = "0.6"
rand_chacha = "0.1.0"
quickcheck = "0.6.2"
types = { path = "../types", default-features = false, features = ["for-tests"] }
[lib]
crate-type = ["staticlib", "lib"]