# ============================================================================= # first, get some info about the compiler # get zig binary if(NOT DEFINED ZIG_BIN OR ZIG_BIN STREQUAL "") find_program(ZIG_BIN zig REQUIRED) endif() set(ZIG_BIN ${ZIG_BIN} CACHE FILEPATH "Zig command") message(NOTICE "-- ZIG_BIN is ${ZIG_BIN}") # get zig libdir (for zig.h) execute_process( COMMAND ${ZIG_BIN} env OUTPUT_VARIABLE ZIG_LIBDIR ) string(JSON ZIG_LIBDIR GET ${ZIG_LIBDIR} lib_dir) set(ZIG_LIBDIR ${ZIG_LIBDIR} CACHE PATH "from `zig env`") # ============================================================================= # set compile options if(DEFINED ZIG_TARGET) list(APPEND ZIG_CFLAGS "-target" "${ZIG_TARGET}") endif() if(DEFINED ZIG_CPU) list(APPEND ZIG_CFLAGS "-mcpu=${ZIG_CPU}") endif() if(NOT DEFINED ZIG_OPTLEVEL) if(CMAKE_BUILD_TYPE STREQUAL Release) set(ZIG_OPTLEVEL ReleaseFast) elseif(CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo) set(ZIG_OPTLEVEL ReleaseSafe) elseif(CMAKE_BUILD_TYPE STREQUAL MinSizeRel) set(ZIG_OPTLEVEL ReleaseSmall) else() # also the Debug case set(ZIG_OPTLEVEL ${CMAKE_BUILD_TYPE}) endif() endif() list(APPEND ZIG_CFLAGS "-O" "${ZIG_OPTLEVEL}") # ============================================================================= # now define the macro we'll be using function(add_zig_object TOP_PROJECT ZIG_TOP_SOURCE_FILE) if(ARGC GREATER 2) set(TARGET_NAME ${ARGV2}) else() cmake_path(GET ZIG_TOP_SOURCE_FILE STEM TARGET_NAME) endif() # directory the header file will be in file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/generated/zig_${TARGET_NAME}/) # the compile command add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.obj # TODO: when is this generator expression evaluated??? (matters for direct rust<->zig references) COMMAND ${ZIG_BIN} build-obj ${ZIG_CFLAGS} -femit-bin=${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.obj -femit-h=${CMAKE_CURRENT_BINARY_DIR}/generated/zig_${TARGET_NAME}/${TARGET_NAME}.h "$,PREPEND,-I>" ${ZIG_TOP_SOURCE_FILE} # ${TARGET_NAME}.obj.o is a bug in zig currently BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.obj.o ${CMAKE_CURRENT_BINARY_DIR}/generated/zig_${TARGET_NAME}/${TARGET_NAME}.h MAIN_DEPENDENCY ${ZIG_TOP_SOURCE_FILE} DEPENDS ${ZIG_TOP_SOURCE_FILE} #DEPFILE ${TARGET_NAME}.obj.d # no way to generate it :/ VERBATIM COMMAND_EXPAND_LISTS ) # 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 generated object file from the library to the code to compile target_sources(${TOP_PROJECT} PUBLIC $) # add directory of zig.h and the generated header to the top project's stuff target_include_directories(${TOP_PROJECT} PRIVATE ${ZIG_LIBDIR} ${CMAKE_CURRENT_BINARY_DIR}/generated/zig_${TARGET_NAME}/) # work around https://github.com/ziglang/zig/issues/16730 target_compile_definitions(${TOP_PROJECT} PUBLIC ZIG_TARGET_MAX_INT_ALIGNMENT="\(sizeof\(intmax_t\)\)") endfunction()