3option(MIM_BUILD_LL_RUNTIME
"Compile the ll backend's C runtime wrappers to LLVM IR (requires clang)." ON)
4find_program(MIM_CLANG NAMES clang)
5if(MIM_BUILD_LL_RUNTIME AND NOT MIM_CLANG)
7 "MimIR: clang not found; ll backend C runtime wrappers will not be built. "
8 "Set MIM_CLANG or disable MIM_BUILD_LL_RUNTIME to silence this."
15function(mim_transitive_imports mim_file roots out)
16 set(pending
"${mim_file}")
20 list(POP_FRONT pending current)
21 file(READ
"${current}" contents)
22 string(REGEX REPLACE
"/\\*[^*]*\\*+([^/*][^*]*\\*+)*/" "" contents
"${contents}")
23 string(REGEX REPLACE
"//[^\n]*" "" contents
"${contents}")
24 string(REGEX MATCHALL
"(plugin|import)[ \t\r\n]+[A-Za-z0-9_]+" directives
"${contents}")
26 foreach(directive IN LISTS directives)
27 string(REGEX REPLACE
"^(plugin|import)[ \t\r\n]+" "" name
"${directive}")
28 foreach(root IN LISTS roots)
29 set(candidate
"${root}/${name}/${name}.mim")
30 if(EXISTS
"${candidate}")
31 if(NOT candidate IN_LIST files)
32 list(APPEND files
"${candidate}")
33 list(APPEND pending
"${candidate}")
41 set(${out}
"${files}" PARENT_SCOPE)
79function(add_mim_plugin)
82 string(LENGTH
"${PLUGIN}" PLUGIN_LENGTH)
83 if(NOT PLUGIN MATCHES
"^[A-Za-z0-9_]+$" OR PLUGIN_LENGTH GREATER 8)
85 "Mim plugin name '${PLUGIN}' must be 1 to 8 letters, digits, or underscores"
89 cmake_parse_arguments(
97 set(PLUGIN_MIM ${CMAKE_CURRENT_LIST_DIR}/${PLUGIN}.mim)
98 set(OUT_PLUGIN_MIM ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/mim/${PLUGIN}.mim)
99 set(PLUGIN_MD ${CMAKE_BINARY_DIR}/docs/plug/${PLUGIN}.md)
100 set(AUTOGEN_H ${CMAKE_BINARY_DIR}/include/mim/plug/${PLUGIN}/autogen.h)
101 set(AUTOGEN_PY ${CMAKE_BINARY_DIR}/py/mim/_plugins/${PLUGIN}.py)
105 ${CMAKE_BINARY_DIR}/docs/plug/
106 ${CMAKE_BINARY_DIR}/include/mim/plug/${PLUGIN}
107 ${CMAKE_BINARY_DIR}/py/mim/_plugins/
108 ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/mim/
111 set(PLUGIN_ROOTS
"${CMAKE_SOURCE_DIR}/src/mim/plug" "${CMAKE_CURRENT_LIST_DIR}/..")
112 mim_transitive_imports(
"${PLUGIN_MIM}" "${PLUGIN_ROOTS}" PLUGIN_IMPORTS)
119 COMMAND $<TARGET_FILE:${MIM_TARGET_NAMESPACE}mim> ${PLUGIN_MIM} -I
"${CMAKE_SOURCE_DIR}/src/mim/plug" -I
"${CMAKE_CURRENT_LIST_DIR}/.." --bootstrap
120 --output-h ${AUTOGEN_H}
121 --output-md ${PLUGIN_MD}
122 --output-py ${AUTOGEN_PY}
123 MAIN_DEPENDENCY ${PLUGIN_MIM}
124 DEPENDS ${MIM_TARGET_NAMESPACE}mim ${PLUGIN_IMPORTS}
125 COMMENT
"Bootstrapping MimIR plugin '${PLUGIN_MIM}'"
129 OUTPUT ${OUT_PLUGIN_MIM}
130 COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PLUGIN_MIM} ${OUT_PLUGIN_MIM}
131 DEPENDS ${PLUGIN_MIM}
132 COMMENT
"Copy '${PLUGIN_MIM}' to '${OUT_PLUGIN_MIM}'"
135 add_custom_target(mim_internal_${PLUGIN}
143 if(PLUGIN IN_LIST MIM_PLUGIN_LIST)
144 message(FATAL_ERROR
"Mim plugin '${PLUGIN}' is already registered")
147 list(APPEND MIM_PLUGIN_LIST
"${PLUGIN}")
148 string(APPEND MIM_PLUGIN_LAYOUT
"<tab type=\"user\" url=\"@ref ${PLUGIN}\" title=\"${PLUGIN}\"/>")
150 set(MIM_PLUGIN_LIST
"${MIM_PLUGIN_LIST}" CACHE INTERNAL
"MIM_PLUGIN_LIST")
151 set(MIM_PLUGIN_LAYOUT
"${MIM_PLUGIN_LAYOUT}" CACHE INTERNAL
"MIM_PLUGIN_LAYOUT")
153 add_library(mim_${PLUGIN} MODULE)
154 add_dependencies(mim_${PLUGIN} mim_internal_${PLUGIN})
155 target_sources(mim_${PLUGIN}
159 target_include_directories(mim_${PLUGIN}
161 $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>
163 if(EXISTS
"${CMAKE_CURRENT_LIST_DIR}/include")
164 target_include_directories(mim_${PLUGIN}
166 "${CMAKE_CURRENT_LIST_DIR}/include"
169 target_link_libraries(mim_${PLUGIN}
172 ${MIM_TARGET_NAMESPACE}libmim
174 set_target_properties(mim_${PLUGIN}
176 CXX_VISIBILITY_PRESET hidden
177 VISIBILITY_INLINES_HIDDEN 1
178 WINDOWS_EXPORT_ALL_SYMBOLS OFF
180 LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/mim
187 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/mim
188 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/mim
189 RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}/mim
190 INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mim
193 FILES ${OUT_PLUGIN_MIM}
194 DESTINATION ${CMAKE_INSTALL_LIBDIR}/mim
198 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mim/plug/${PLUGIN}
200 if(EXISTS
"${CMAKE_CURRENT_LIST_DIR}/include")
202 DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/include/"
203 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
229function(add_mim_runtime)
232 cmake_parse_arguments(
240 if(NOT MIM_BUILD_LL_RUNTIME OR NOT MIM_CLANG)
244 set(RT_DIR ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/mim/rt)
245 file(MAKE_DIRECTORY ${RT_DIR})
246 set(RT_LL ${RT_DIR}/${PLUGIN}_rt.ll)
248 set(RT_SOURCES ${PARSED_SOURCES})
249 list(TRANSFORM RT_SOURCES PREPEND ${CMAKE_CURRENT_LIST_DIR}/)
251 list(LENGTH RT_SOURCES N_SOURCES)
252 if(N_SOURCES EQUAL 1)
255 COMMAND ${MIM_CLANG} -S -emit-llvm -O2 ${RT_SOURCES} -o ${RT_LL}
256 DEPENDS ${RT_SOURCES}
257 COMMENT
"Compiling MimIR runtime '${PLUGIN}' to LLVM IR"
261 find_program(MIM_LLVM_LINK NAMES llvm-link)
262 if(NOT MIM_LLVM_LINK)
264 "add_mim_runtime(${PLUGIN}) with multiple SOURCES needs llvm-link to merge them"
268 foreach(src IN LISTS RT_SOURCES)
269 cmake_path(GET src STEM stem)
270 set(bc ${RT_DIR}/${PLUGIN}_${stem}.bc)
273 COMMAND ${MIM_CLANG} -emit-llvm -O2 -c ${src} -o ${bc}
275 COMMENT
"Compiling MimIR runtime source '${stem}' to LLVM bitcode"
278 list(APPEND RT_BCS ${bc})
282 COMMAND ${MIM_LLVM_LINK} -S ${RT_BCS} -o ${RT_LL}
284 COMMENT
"Linking MimIR runtime '${PLUGIN}' into a single LLVM IR module"
289 add_custom_target(mim_runtime_${PLUGIN} ALL DEPENDS ${RT_LL})
290 if(TARGET mim_${PLUGIN})
291 add_dependencies(mim_${PLUGIN} mim_runtime_${PLUGIN})
295 DESTINATION ${CMAKE_INSTALL_LIBDIR}/mim/rt