nextpnr/cmake/BBAsm.cmake
Catherine 17943a51cb CMake: remove -DSERIALIZE_CHIPDBS= option.
The impetus for this commit is the fact that it causes rare but
build-breaking race conditions when used with `make -jN` with `N > 1`.
These race conditions are difficult to track down or fix because of
the very rudmentary debugging tools provided by `make` and opaque
semantics of CMake's Makefile generator. They break the build by
running two `.bba` generation processes, then one of them renaming
the `.bba.new` file once it's done, leaving the other one to fail.

After reflection (as the author of this code path) and discussion with
community members who use it, I've concluded that this isn't the right
approach.
1. In practice, on targets where `-DSERIALIZE_CHIPDBS=` matters, you
   also care about other build steps, like linking nextpnr, which
   are not serializable this way. So you use a workaround anyway, like
   `make`ing individual targets instead.
2. The way to serialize the build with Make is the `-j1` option. Trying
   to work around `-jN` to make it work like `-j1` is inherently error
   prone. While there is some utility in not serializing C++ compilation
   this utility could be more easily achieved by providing a single
   target that builds all chipdbs, running `make <chipdb-target> -j1`,
   then running `make -jN` for the rest of the build.
2025-01-21 17:13:03 +00:00

172 lines
4.6 KiB
CMake

include(TestBigEndian)
test_big_endian(IS_BIG_ENDIAN)
if (IS_BIG_ENDIAN)
set(BBASM_ENDIAN_FLAG "--be")
else()
set(BBASM_ENDIAN_FLAG "--le")
endif()
# Example usage (note the `.new`, used for atomic updates):
#
# add_bba_produce_command(
# COMMAND ${Python_EXECUTABLE}
# ${CMAKE_CURRENT_SOURCE_DIR}/chipdb.py
# -o ${CMAKE_CURRENT_BINARY_DIR}/chipdb-hx8k.bba.new
# OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/chipdb-hx8k.bba
# INPUTS ${CMAKE_CURRENT_SOURCE_DIR}/chipdb.py
# )
#
# Paths must be absolute.
#
function(add_bba_produce_command)
cmake_parse_arguments(arg "" "OUTPUT" "COMMAND;INPUTS" ${ARGN})
cmake_path(GET arg_OUTPUT PARENT_PATH arg_OUTPUT_DIR)
file(MAKE_DIRECTORY ${arg_OUTPUT_DIR})
list(GET arg_COMMAND 0 arg_EXECUTABLE)
add_custom_command(
OUTPUT
${arg_OUTPUT}
COMMAND
${arg_COMMAND}
COMMAND
${CMAKE_COMMAND} -E rename # atomic update
${arg_OUTPUT}.new
${arg_OUTPUT}
DEPENDS
${arg_EXECUTABLE}
${arg_INPUTS}
VERBATIM
)
endfunction()
# Example usage:
#
# add_bba_compile_command(
# TARGET chipdb-ice40
# OUTPUT ice40/chipdb-1k.bin
# INPUT ${CMAKE_CURRENT_BINARY_DIR}/chipdb-1k.bba
# MODE binary
# )
#
# Paths must be absolute.
#
function(add_bba_compile_command)
cmake_parse_arguments(arg "" "TARGET;OUTPUT;INPUT;MODE" "" ${ARGN})
cmake_path(GET arg_OUTPUT PARENT_PATH arg_OUTPUT_DIR)
cmake_path(GET arg_OUTPUT FILENAME arg_OUTPUT_NAME)
set(arg_PRODUCT ${CMAKE_BINARY_DIR}/share/${arg_OUTPUT})
cmake_path(GET arg_PRODUCT PARENT_PATH arg_PRODUCT_DIR)
if (arg_MODE STREQUAL "binary" OR arg_MODE STREQUAL "resource")
add_custom_command(
OUTPUT
${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}
COMMAND
bbasm ${BBASM_ENDIAN_FLAG}
${arg_INPUT}
${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}
DEPENDS
bbasm
${arg_INPUT}
VERBATIM
)
if (arg_MODE STREQUAL "resource")
file(WRITE ${arg_OUTPUT}.rc
"${arg_OUTPUT} RCDATA \"${arg_OUTPUT}\"")
target_sources(
${arg_TARGET} PUBLIC
${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}.rc
)
else()
target_sources(
${arg_TARGET} PUBLIC
${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}
)
add_custom_command(
OUTPUT
${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}
COMMAND
${CMAKE_COMMAND} -E make_directory
${arg_PRODUCT_DIR}
COMMAND
${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}
${arg_PRODUCT}
APPEND
VERBATIM
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}
DESTINATION share/nextpnr/${arg_OUTPUT_DIR}
)
endif()
elseif (arg_MODE STREQUAL "embed")
add_custom_command(
OUTPUT
${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}.cc
${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}
COMMAND
bbasm ${BBASM_ENDIAN_FLAG} --e
${arg_INPUT}
${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}.cc
${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}
DEPENDS
bbasm
${arg_INPUT}
VERBATIM
)
target_sources(
${arg_TARGET} PUBLIC
${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}.cc
)
elseif (arg_MODE STREQUAL "string")
add_custom_command(
OUTPUT
${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}.cc
COMMAND
bbasm ${BBASM_ENDIAN_FLAG} --c
${arg_INPUT}
${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}.cc
DEPENDS
bbasm
${arg_INPUT}
VERBATIM
)
if (NOT MSVC)
set_source_files_properties(
${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}.cc PROPERTIES
COMPILE_OPTIONS "-w;-g0;-O0"
)
endif()
target_sources(
${arg_TARGET} PUBLIC
${CMAKE_CURRENT_BINARY_DIR}/${arg_OUTPUT_NAME}.cc
)
endif()
endfunction()