b34b46fa16
* Fix automerge-c tests on mac * Generate significantly smaller automerge-c builds This cuts the size of libautomerge_core.a from 25Mb to 1.6Mb on macOS and 53Mb to 2.7Mb on Linux. As a side-effect of setting codegen-units = 1 for all release builds the optimized wasm files are also 100kb smaller.
305 lines
9.7 KiB
CMake
305 lines
9.7 KiB
CMake
cmake_minimum_required(VERSION 3.23 FATAL_ERROR)
|
|
|
|
project(automerge-c VERSION 0.1.0
|
|
LANGUAGES C
|
|
DESCRIPTION "C bindings for the Automerge Rust library.")
|
|
|
|
set(LIBRARY_NAME "automerge")
|
|
|
|
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
|
|
|
option(BUILD_SHARED_LIBS "Enable the choice of a shared or static library.")
|
|
|
|
include(CTest)
|
|
|
|
include(CMakePackageConfigHelpers)
|
|
|
|
include(GNUInstallDirs)
|
|
|
|
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
|
|
|
string(MAKE_C_IDENTIFIER ${PROJECT_NAME} SYMBOL_PREFIX)
|
|
|
|
string(TOUPPER ${SYMBOL_PREFIX} SYMBOL_PREFIX)
|
|
|
|
set(CARGO_TARGET_DIR "${CMAKE_BINARY_DIR}/Cargo/target")
|
|
|
|
set(CBINDGEN_INCLUDEDIR "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR}")
|
|
|
|
set(CBINDGEN_TARGET_DIR "${CBINDGEN_INCLUDEDIR}/${PROJECT_NAME}")
|
|
|
|
find_program (
|
|
CARGO_CMD
|
|
"cargo"
|
|
PATHS "$ENV{CARGO_HOME}/bin"
|
|
DOC "The Cargo command"
|
|
)
|
|
|
|
if(NOT CARGO_CMD)
|
|
message(FATAL_ERROR "Cargo (Rust package manager) not found! "
|
|
"Please install it and/or set the CARGO_HOME "
|
|
"environment variable to its path.")
|
|
endif()
|
|
|
|
string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_LOWER)
|
|
|
|
# In order to build with -Z build-std, we need to pass target explicitly.
|
|
# https://doc.rust-lang.org/cargo/reference/unstable.html#build-std
|
|
execute_process (
|
|
COMMAND rustc -vV
|
|
OUTPUT_VARIABLE RUSTC_VERSION
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
string(REGEX REPLACE ".*host: ([^ \n]*).*" "\\1"
|
|
CARGO_TARGET
|
|
${RUSTC_VERSION}
|
|
)
|
|
|
|
if(BUILD_TYPE_LOWER STREQUAL debug)
|
|
set(CARGO_BUILD_TYPE "debug")
|
|
|
|
set(CARGO_FLAG --target=${CARGO_TARGET})
|
|
else()
|
|
set(CARGO_BUILD_TYPE "release")
|
|
|
|
if (NOT RUSTC_VERSION MATCHES "nightly")
|
|
set(RUSTUP_TOOLCHAIN nightly)
|
|
endif()
|
|
|
|
set(RUSTFLAGS -C\ panic=abort)
|
|
|
|
set(CARGO_FLAG -Z build-std=std,panic_abort --release --target=${CARGO_TARGET})
|
|
endif()
|
|
|
|
set(CARGO_FEATURES "")
|
|
|
|
set(CARGO_BINARY_DIR "${CARGO_TARGET_DIR}/${CARGO_TARGET}/${CARGO_BUILD_TYPE}")
|
|
|
|
set(BINDINGS_NAME "${LIBRARY_NAME}_core")
|
|
|
|
configure_file(
|
|
${CMAKE_MODULE_PATH}/Cargo.toml.in
|
|
${CMAKE_SOURCE_DIR}/Cargo.toml
|
|
@ONLY
|
|
NEWLINE_STYLE LF
|
|
)
|
|
|
|
set(INCLUDE_GUARD_PREFIX "${SYMBOL_PREFIX}")
|
|
|
|
configure_file(
|
|
${CMAKE_MODULE_PATH}/cbindgen.toml.in
|
|
${CMAKE_SOURCE_DIR}/cbindgen.toml
|
|
@ONLY
|
|
NEWLINE_STYLE LF
|
|
)
|
|
|
|
set(CARGO_OUTPUT
|
|
${CBINDGEN_TARGET_DIR}/${LIBRARY_NAME}.h
|
|
${CARGO_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${BINDINGS_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}
|
|
)
|
|
|
|
# \note cbindgen's naming behavior isn't fully configurable and it ignores
|
|
# `const fn` calls (https://github.com/eqrion/cbindgen/issues/252).
|
|
add_custom_command(
|
|
OUTPUT
|
|
${CARGO_OUTPUT}
|
|
COMMAND
|
|
# \note cbindgen won't regenerate its output header file after it's been removed but it will after its
|
|
# configuration file has been updated.
|
|
${CMAKE_COMMAND} -DCONDITION=NOT_EXISTS -P ${CMAKE_SOURCE_DIR}/cmake/file-touch.cmake -- ${CBINDGEN_TARGET_DIR}/${LIBRARY_NAME}.h ${CMAKE_SOURCE_DIR}/cbindgen.toml
|
|
COMMAND
|
|
${CMAKE_COMMAND} -E env CARGO_TARGET_DIR=${CARGO_TARGET_DIR} CBINDGEN_TARGET_DIR=${CBINDGEN_TARGET_DIR} RUSTUP_TOOLCHAIN=${RUSTUP_TOOLCHAIN} RUSTFLAGS=${RUSTFLAGS} ${CARGO_CMD} build ${CARGO_FLAG} ${CARGO_FEATURES}
|
|
COMMAND
|
|
# Compensate for cbindgen's translation of consecutive uppercase letters to "ScreamingSnakeCase".
|
|
${CMAKE_COMMAND} -DMATCH_REGEX=A_M\([^_]+\)_ -DREPLACE_EXPR=AM_\\1_ -P ${CMAKE_SOURCE_DIR}/cmake/file-regex-replace.cmake -- ${CBINDGEN_TARGET_DIR}/${LIBRARY_NAME}.h
|
|
COMMAND
|
|
# Compensate for cbindgen ignoring `std:mem::size_of<usize>()` calls.
|
|
${CMAKE_COMMAND} -DMATCH_REGEX=USIZE_ -DREPLACE_EXPR=\+${CMAKE_SIZEOF_VOID_P} -P ${CMAKE_SOURCE_DIR}/cmake/file-regex-replace.cmake -- ${CBINDGEN_TARGET_DIR}/${LIBRARY_NAME}.h
|
|
MAIN_DEPENDENCY
|
|
src/lib.rs
|
|
DEPENDS
|
|
src/actor_id.rs
|
|
src/byte_span.rs
|
|
src/change.rs
|
|
src/doc.rs
|
|
src/doc/list.rs
|
|
src/doc/map.rs
|
|
src/doc/utils.rs
|
|
src/index.rs
|
|
src/item.rs
|
|
src/items.rs
|
|
src/obj.rs
|
|
src/result.rs
|
|
src/sync.rs
|
|
src/sync/have.rs
|
|
src/sync/message.rs
|
|
src/sync/state.rs
|
|
${CMAKE_SOURCE_DIR}/build.rs
|
|
${CMAKE_MODULE_PATH}/Cargo.toml.in
|
|
${CMAKE_MODULE_PATH}/cbindgen.toml.in
|
|
WORKING_DIRECTORY
|
|
${CMAKE_SOURCE_DIR}
|
|
COMMENT
|
|
"Producing the bindings' artifacts with Cargo..."
|
|
VERBATIM
|
|
)
|
|
|
|
add_custom_target(${BINDINGS_NAME}_artifacts ALL
|
|
DEPENDS ${CARGO_OUTPUT}
|
|
)
|
|
|
|
add_library(${BINDINGS_NAME} STATIC IMPORTED GLOBAL)
|
|
|
|
target_include_directories(${BINDINGS_NAME} INTERFACE "${CBINDGEN_INCLUDEDIR}")
|
|
|
|
set_target_properties(
|
|
${BINDINGS_NAME}
|
|
PROPERTIES
|
|
# \note Cargo writes a debug build into a nested directory instead of
|
|
# decorating its name.
|
|
DEBUG_POSTFIX ""
|
|
DEFINE_SYMBOL ""
|
|
IMPORTED_IMPLIB ""
|
|
IMPORTED_LOCATION "${CARGO_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${BINDINGS_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}"
|
|
IMPORTED_NO_SONAME "TRUE"
|
|
IMPORTED_SONAME ""
|
|
LINKER_LANGUAGE C
|
|
PUBLIC_HEADER "${CBINDGEN_TARGET_DIR}/${LIBRARY_NAME}.h"
|
|
SOVERSION "${PROJECT_VERSION_MAJOR}"
|
|
VERSION "${PROJECT_VERSION}"
|
|
# \note Cargo exports all of the symbols automatically.
|
|
WINDOWS_EXPORT_ALL_SYMBOLS "TRUE"
|
|
)
|
|
|
|
target_compile_definitions(${BINDINGS_NAME} INTERFACE $<TARGET_PROPERTY:${BINDINGS_NAME},DEFINE_SYMBOL>)
|
|
|
|
set(UTILS_SUBDIR "utils")
|
|
|
|
add_custom_command(
|
|
OUTPUT
|
|
${CBINDGEN_TARGET_DIR}/${UTILS_SUBDIR}/enum_string.h
|
|
${CMAKE_BINARY_DIR}/src/${UTILS_SUBDIR}/enum_string.c
|
|
COMMAND
|
|
${CMAKE_COMMAND} -DPROJECT_NAME=${PROJECT_NAME} -DLIBRARY_NAME=${LIBRARY_NAME} -DSUBDIR=${UTILS_SUBDIR} -P ${CMAKE_SOURCE_DIR}/cmake/enum-string-functions-gen.cmake -- ${CBINDGEN_TARGET_DIR}/${LIBRARY_NAME}.h ${CBINDGEN_TARGET_DIR}/${UTILS_SUBDIR}/enum_string.h ${CMAKE_BINARY_DIR}/src/${UTILS_SUBDIR}/enum_string.c
|
|
MAIN_DEPENDENCY
|
|
${CBINDGEN_TARGET_DIR}/${LIBRARY_NAME}.h
|
|
DEPENDS
|
|
${CMAKE_SOURCE_DIR}/cmake/enum-string-functions-gen.cmake
|
|
WORKING_DIRECTORY
|
|
${CMAKE_SOURCE_DIR}
|
|
COMMENT
|
|
"Generating the enum string functions with CMake..."
|
|
VERBATIM
|
|
)
|
|
|
|
add_custom_target(${LIBRARY_NAME}_utilities
|
|
DEPENDS ${CBINDGEN_TARGET_DIR}/${UTILS_SUBDIR}/enum_string.h
|
|
${CMAKE_BINARY_DIR}/src/${UTILS_SUBDIR}/enum_string.c
|
|
)
|
|
|
|
add_library(${LIBRARY_NAME})
|
|
|
|
target_compile_features(${LIBRARY_NAME} PRIVATE c_std_99)
|
|
|
|
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
|
|
|
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
|
|
|
find_package(Threads REQUIRED)
|
|
|
|
set(LIBRARY_DEPENDENCIES Threads::Threads ${CMAKE_DL_LIBS})
|
|
|
|
if(WIN32)
|
|
list(APPEND LIBRARY_DEPENDENCIES Bcrypt userenv ws2_32)
|
|
else()
|
|
list(APPEND LIBRARY_DEPENDENCIES m)
|
|
endif()
|
|
|
|
target_link_libraries(${LIBRARY_NAME}
|
|
PUBLIC ${BINDINGS_NAME}
|
|
${LIBRARY_DEPENDENCIES}
|
|
)
|
|
|
|
# \note An imported library's INTERFACE_INCLUDE_DIRECTORIES property can't
|
|
# contain a non-existent path so its build-time include directory
|
|
# must be specified for all of its dependent targets instead.
|
|
target_include_directories(${LIBRARY_NAME}
|
|
PUBLIC "$<BUILD_INTERFACE:${CBINDGEN_INCLUDEDIR};${CMAKE_SOURCE_DIR}/${CMAKE_INSTALL_INCLUDEDIR}>"
|
|
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
|
)
|
|
|
|
add_dependencies(${LIBRARY_NAME} ${BINDINGS_NAME}_artifacts)
|
|
|
|
# Generate the configuration header.
|
|
math(EXPR INTEGER_PROJECT_VERSION_MAJOR "${PROJECT_VERSION_MAJOR} * 100000")
|
|
|
|
math(EXPR INTEGER_PROJECT_VERSION_MINOR "${PROJECT_VERSION_MINOR} * 100")
|
|
|
|
math(EXPR INTEGER_PROJECT_VERSION_PATCH "${PROJECT_VERSION_PATCH}")
|
|
|
|
math(EXPR INTEGER_PROJECT_VERSION "${INTEGER_PROJECT_VERSION_MAJOR} + \
|
|
${INTEGER_PROJECT_VERSION_MINOR} + \
|
|
${INTEGER_PROJECT_VERSION_PATCH}")
|
|
|
|
configure_file(
|
|
${CMAKE_MODULE_PATH}/config.h.in
|
|
${CBINDGEN_TARGET_DIR}/config.h
|
|
@ONLY
|
|
NEWLINE_STYLE LF
|
|
)
|
|
|
|
target_sources(${LIBRARY_NAME}
|
|
PRIVATE
|
|
src/${UTILS_SUBDIR}/result.c
|
|
src/${UTILS_SUBDIR}/stack_callback_data.c
|
|
src/${UTILS_SUBDIR}/stack.c
|
|
src/${UTILS_SUBDIR}/string.c
|
|
${CMAKE_BINARY_DIR}/src/${UTILS_SUBDIR}/enum_string.c
|
|
PUBLIC
|
|
FILE_SET api TYPE HEADERS
|
|
BASE_DIRS
|
|
${CBINDGEN_INCLUDEDIR}
|
|
${CMAKE_SOURCE_DIR}/${CMAKE_INSTALL_INCLUDEDIR}
|
|
FILES
|
|
${CBINDGEN_TARGET_DIR}/${LIBRARY_NAME}.h
|
|
${CBINDGEN_TARGET_DIR}/${UTILS_SUBDIR}/enum_string.h
|
|
${CMAKE_SOURCE_DIR}/${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/${UTILS_SUBDIR}/result.h
|
|
${CMAKE_SOURCE_DIR}/${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/${UTILS_SUBDIR}/stack_callback_data.h
|
|
${CMAKE_SOURCE_DIR}/${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/${UTILS_SUBDIR}/stack.h
|
|
${CMAKE_SOURCE_DIR}/${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/${UTILS_SUBDIR}/string.h
|
|
INTERFACE
|
|
FILE_SET config TYPE HEADERS
|
|
BASE_DIRS
|
|
${CBINDGEN_INCLUDEDIR}
|
|
FILES
|
|
${CBINDGEN_TARGET_DIR}/config.h
|
|
)
|
|
|
|
install(
|
|
TARGETS ${LIBRARY_NAME}
|
|
EXPORT ${PROJECT_NAME}-config
|
|
FILE_SET api
|
|
FILE_SET config
|
|
)
|
|
|
|
# \note Install the Cargo-built core bindings to enable direct linkage.
|
|
install(
|
|
FILES $<TARGET_PROPERTY:${BINDINGS_NAME},IMPORTED_LOCATION>
|
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
)
|
|
|
|
install(EXPORT ${PROJECT_NAME}-config
|
|
FILE ${PROJECT_NAME}-config.cmake
|
|
NAMESPACE "${PROJECT_NAME}::"
|
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${LIB}
|
|
)
|
|
|
|
if(BUILD_TESTING)
|
|
add_subdirectory(test EXCLUDE_FROM_ALL)
|
|
|
|
enable_testing()
|
|
endif()
|
|
|
|
add_subdirectory(docs)
|
|
|
|
add_subdirectory(examples EXCLUDE_FROM_ALL)
|