cmake_minimum_required(VERSION 3.20) project(no_core_write LANGUAGES NONE) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) find_program(RUSTC rustc REQUIRED) set(RUST_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/main.rs") set(RUST_BINARY "${CMAKE_CURRENT_BINARY_DIR}/no_core_write${CMAKE_EXECUTABLE_SUFFIX}") # no_core is an unstable rustc feature. RUSTC_BOOTSTRAP lets this deliberately # minimal example be built with the installed compiler without Cargo or core. set(RUSTC_ENV "RUSTC_BOOTSTRAP=1") set(RUSTC_FLAGS -C panic=abort) # CMAKE_BUILD_TYPE does not automatically affect a custom rustc command. # Pass the corresponding optimization/debug-info settings explicitly. if (CMAKE_BUILD_TYPE STREQUAL "Release") list(APPEND RUSTC_FLAGS -C opt-level=3 -C debuginfo=0) elseif (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") list(APPEND RUSTC_FLAGS -C opt-level=3 -C debuginfo=2) else() list(APPEND RUSTC_FLAGS -C opt-level=0 -C debuginfo=2) endif() # A no_core binary does not get Rust's normal startup/linker setup. Link the # small platform system/runtime library needed by the stdout implementation. if (WIN32) # Use Win32 directly instead of the C runtime; this keeps the executable # small while still writing to the console's stdout handle. set(RUSTC_LINK_ARGS -l kernel32 -C "link-args=/NODEFAULTLIB /ENTRY:mainCRTStartup /SUBSYSTEM:CONSOLE /OPT:REF /OPT:ICF" ) elseif (UNIX) set(RUSTC_LINK_ARGS -C "link-args=-lc") endif() add_custom_command( OUTPUT "${RUST_BINARY}" COMMAND "${CMAKE_COMMAND}" -E env "${RUSTC_ENV}" "${RUSTC}" "${RUST_SOURCE}" --crate-name no_core_write --crate-type bin -o "${RUST_BINARY}" ${RUSTC_FLAGS} ${RUSTC_LINK_ARGS} DEPENDS "${RUST_SOURCE}" VERBATIM ) add_custom_target(no_core_write ALL DEPENDS "${RUST_BINARY}")