diff --git a/cmake/rust-obj.cmake b/cmake/rust-obj.cmake index 6328d37..d7e8209 100644 --- a/cmake/rust-obj.cmake +++ b/cmake/rust-obj.cmake @@ -136,10 +136,16 @@ function(add_rust_object TOP_PROJECT RUST_TOP_SOURCE_FILE) endif() ### rust compilation + set(_SHELL_SCRIPT "${CMAKE_AR} vd \"${CMAKE_CURRENT_BINARY_DIR}/lib${TARGET_NAME}.a.tmp\" \"$(${CMAKE_AR} t ${CMAKE_CURRENT_BINARY_DIR}/lib${TARGET_NAME}.a.tmp | grep \"lib${TARGET_NAME}\.${TARGET_NAME}\..*\.o\")\"") # the compile command add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.obj - COMMAND ${RUSTC_BIN} ${RUST_CFLAGS} --emit=obj,dep-info=${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.obj.d --crate-type=staticlib -o ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.obj ${RUST_TOP_SOURCE_FILE} + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.obj ${CMAKE_CURRENT_BINARY_DIR}/lib${TARGET_NAME}.a + COMMAND ${RUSTC_BIN} ${RUST_CFLAGS} --emit=link,dep-info=${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.obj.d,obj=${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.obj --crate-type=staticlib -o ${CMAKE_CURRENT_BINARY_DIR}/lib${TARGET_NAME}.a.tmp ${RUST_TOP_SOURCE_FILE} + # remove object file itself from the static library, so two-way references are possible. + # now the static library only contains dependency code from core etc + COMMAND bash -c ${_SHELL_SCRIPT} + COMMAND mv ${CMAKE_CURRENT_BINARY_DIR}/lib${TARGET_NAME}.a.tmp ${CMAKE_CURRENT_BINARY_DIR}/lib${TARGET_NAME}.a + BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/lib${TARGET_NAME}.a.tmp DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.obj.d # ensures the bindgen happens before the rustc compilation #DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/generated/rust_${TARGET_NAME}/lib${TARGET_NAME}_bindgen.rlib @@ -149,8 +155,11 @@ function(add_rust_object TOP_PROJECT RUST_TOP_SOURCE_FILE) ) # add a virtual library that can be reused and referred to (not possible with a bare add_custom_command()) add_library(${TARGET_NAME} OBJECT ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.obj) + add_library(rdep_${TARGET_NAME} OBJECT ${CMAKE_CURRENT_BINARY_DIR}/lib${TARGET_NAME}.a) # add generated object file from the library to the code to compile target_sources(${TOP_PROJECT} PUBLIC $) + # also make top project depend on rdep, so stuff from eg the core crate will also get linked in + target_link_libraries(${TOP_PROJECT} ${CMAKE_CURRENT_BINARY_DIR}/lib${TARGET_NAME}.a) ### rust-to-C bindings (generate C headers from .rs, cbindgen) # cbindgen call @@ -158,11 +167,12 @@ function(add_rust_object TOP_PROJECT RUST_TOP_SOURCE_FILE) OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/generated/rust_${TARGET_NAME}/${TARGET_NAME}.h COMMAND ${CBINDGEN_BIN} ${CBINDGEN_CFLAGS} -d --depfile ${CMAKE_CURRENT_BINARY_DIR}/generated/rust_${TARGET_NAME}/${TARGET_NAME}.h.d -o ${CMAKE_CURRENT_BINARY_DIR}/generated/rust_${TARGET_NAME}/${TARGET_NAME}.h ${RUST_TOP_SOURCE_FILE} DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/generated/rust_${TARGET_NAME}/${TARGET_NAME}.h.d - MAIN_DEPENDENCY ${RUST_TOP_SOURCE_FILE} + MAIN_DEPENDENCY ${CMAKE_CURRENT_BINARY_DIR}/lib${TARGET_NAME}.a + #MAIN_DEPENDENCY ${RUST_TOP_SOURCE_FILE} VERBATIM ) # make a virtual library for the header files - add_library(rs2c_${TARGET_NAME} INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/generated/rust_${TARGET_NAME}/${TARGET_NAME}.h ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.obj) + add_library(rs2c_${TARGET_NAME} INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/generated/rust_${TARGET_NAME}/${TARGET_NAME}.h) # ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.obj) # add dependency to ensure build order and stuff target_link_libraries(${TOP_PROJECT} rs2c_${TARGET_NAME})