MimIR 0.1
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
Mim.cmake
Go to the documentation of this file.
1include(GNUInstallDirs)
2
3if(NOT DEFINED MIM_PLUGIN_LIST)
4 set(MIM_PLUGIN_LIST "" CACHE INTERNAL "MIM_PLUGIN_LIST")
5endif()
6if(NOT DEFINED MIM_PLUGIN_LAYOUT)
7 set(MIM_PLUGIN_LAYOUT "" CACHE INTERNAL "MIM_PLUGIN_LAYOUT")
8endif()
9
10if(NOT MIM_TARGET_NAMESPACE)
11 set(MIM_TARGET_NAMESPACE "")
12endif()
13
14## \page add_mim_plugin_cmake add_mim_plugin
15## \brief Registers a new MimIR plugin.
16##
17## Relative to the plugin's `CMakeLists.txt`, there should be a file
18## `<plugin-name>.mim` containing the plugin's annexes.
19##
20## \code{.cmake}
21## add_mim_plugin(<plugin-name>
22## [SOURCES <source>...]
23## [PRIVATE <private-item>...]
24## [INSTALL])
25## \endcode
26##
27## `<plugin-name>` may only contain letters, digits, and underscores, and must
28## satisfy MimIR's plugin naming constraints.
29##
30## The command creates two targets:
31## - `mim_internal_<plugin-name>` bootstraps the plugin, generates
32## `<plugin-name>/autogen.h` for the C++ interface used to identify annexes,
33## `<plugin-name>.md` for the documentation, and copies `<plugin-name>.mim`
34## into the build tree.
35## - `mim_<plugin-name>` builds the actual `MODULE` library that contains
36## normalizers, passes, and backends. One of the listed source files must
37## export `mim_get_plugin`.
38##
39## `SOURCES` lists the source files that are compiled into the loadable plugin.
40## `PRIVATE` lists additional private link dependencies.
41##
42## `INSTALL` installs the plugin module, its `.mim` file, and the generated
43## `autogen.h`. The export name `mim-targets` must be exported accordingly; see
44## CMake's `install(EXPORT ...)` documentation.
45##
46## Additional target properties can be set afterwards, for example:
47## \code{.cmake}
48## target_include_directories(mim_<plugin-name> <path>...)
49## \endcode
50function(add_mim_plugin)
51 set(PLUGIN ${ARGV0})
52
53 if(NOT PLUGIN MATCHES "^[A-Za-z0-9_]+$")
54 message(FATAL_ERROR "Mim plugin names may only contain letters, digits, and underscores")
55 endif()
56
57 string(LENGTH "${PLUGIN}" PLUGIN_LENGTH)
58 if(PLUGIN_LENGTH GREATER 8)
59 message(FATAL_ERROR "Mim plugin '${PLUGIN}' exceeds the maximum supported length of 8 characters")
60 endif()
61
62 cmake_parse_arguments(
63 PARSE_ARGV 1 # skip first arg
64 PARSED # prefix of output variables
65 "INSTALL" # options
66 "" # one-value keywords (none)
67 "SOURCES;PRIVATE" # multi-value keywords
68 )
69
70 set(PLUGIN_MIM ${CMAKE_CURRENT_LIST_DIR}/${PLUGIN}.mim)
71 set(OUT_PLUGIN_MIM ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/mim/${PLUGIN}.mim)
72 set(PLUGIN_MD ${CMAKE_BINARY_DIR}/docs/plug/${PLUGIN}.md)
73 set(AUTOGEN_H ${CMAKE_BINARY_DIR}/include/mim/plug/${PLUGIN}/autogen.h)
74
75 file(READ "${PLUGIN_MIM}" plugin_file_contents)
76
77 # Strip block comments (/* ... */) — greedy, so repeat if needed
78 string(REGEX REPLACE "/\\*[^*]*\\*+([^/*][^*]*\\*+)*/" "" plugin_file_contents "${plugin_file_contents}")
79
80 # Replace all newlines with semicolons to help with list processing
81 string(REPLACE "\n" ";" plugin_lines "${plugin_file_contents}")
82
83 file(
84 MAKE_DIRECTORY
85 ${CMAKE_BINARY_DIR}/docs/plug/
86 ${CMAKE_BINARY_DIR}/include/mim/plug/${PLUGIN}
87 )
88
89 add_custom_command(
90 OUTPUT
91 ${AUTOGEN_H}
92 ${PLUGIN_MD}
93 COMMAND $<TARGET_FILE:${MIM_TARGET_NAMESPACE}mim> ${PLUGIN_MIM} -P "${CMAKE_CURRENT_LIST_DIR}/.." --bootstrap
94 --output-h ${AUTOGEN_H}
95 --output-md ${PLUGIN_MD}
96 MAIN_DEPENDENCY ${PLUGIN_MIM}
97 DEPENDS ${MIM_TARGET_NAMESPACE}mim
98 COMMENT "Bootstrapping MimIR plugin '${PLUGIN_MIM}'"
99 VERBATIM
100 )
101 add_custom_command(
102 OUTPUT ${OUT_PLUGIN_MIM}
103 COMMAND ${CMAKE_COMMAND} -E copy_if_different ${PLUGIN_MIM} ${OUT_PLUGIN_MIM}
104 DEPENDS ${PLUGIN_MIM}
105 COMMENT "Copy '${PLUGIN_MIM}' to '${OUT_PLUGIN_MIM}'"
106 )
107
108 add_custom_target(mim_internal_${PLUGIN}
109 DEPENDS
110 ${AUTOGEN_H}
111 ${PLUGIN_MD}
112 ${OUT_PLUGIN_MIM}
113 )
114
115 if(PLUGIN IN_LIST MIM_PLUGIN_LIST)
116 message(FATAL_ERROR "Mim plugin '${PLUGIN}' is already registered")
117 endif()
118
119 list(APPEND MIM_PLUGIN_LIST "${PLUGIN}")
120 string(APPEND MIM_PLUGIN_LAYOUT "<tab type=\"user\" url=\"@ref ${PLUGIN}\" title=\"${PLUGIN}\"/>")
121
122 # populate to globals
123 set(MIM_PLUGIN_LIST "${MIM_PLUGIN_LIST}" CACHE INTERNAL "MIM_PLUGIN_LIST")
124 set(MIM_PLUGIN_LAYOUT "${MIM_PLUGIN_LAYOUT}" CACHE INTERNAL "MIM_PLUGIN_LAYOUT")
125
126 #
127 # mim_plugin
128 #
129 add_library(mim_${PLUGIN} MODULE)
130 add_dependencies(mim_${PLUGIN}
131 mim_internal_${PLUGIN}
132 ${PLUGIN_SOFT_DEPS}
133 ${PLUGIN_HARD_DEPS}
134 )
135 target_sources(mim_${PLUGIN}
136 PRIVATE
137 ${PARSED_SOURCES}
138 )
139 target_include_directories(mim_${PLUGIN}
140 PUBLIC
141 $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include> # for autogen.h
142 )
143 if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/include")
144 target_include_directories(mim_${PLUGIN}
145 PRIVATE
146 "${CMAKE_CURRENT_LIST_DIR}/include"
147 )
148 endif()
149 target_link_libraries(mim_${PLUGIN}
150 PRIVATE
151 ${PARSED_PRIVATE}
152 ${MIM_TARGET_NAMESPACE}libmim
153 )
154 set_target_properties(mim_${PLUGIN}
155 PROPERTIES
156 CXX_VISIBILITY_PRESET hidden
157 VISIBILITY_INLINES_HIDDEN 1
158 WINDOWS_EXPORT_ALL_SYMBOLS OFF
159 PREFIX "lib" # always use "lib" as prefix regardless of OS/compiler
160 LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/mim
161 )
162
163 #
164 # install
165 #
166 if(${PARSED_INSTALL})
167 install(
168 TARGETS
169 mim_${PLUGIN}
170 EXPORT mim-targets
171 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/mim
172 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/mim
173 RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}/mim
174 INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mim
175 )
176 install(
177 FILES ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/mim/${PLUGIN}.mim
178 DESTINATION ${CMAKE_INSTALL_LIBDIR}/mim
179 )
180 install(
181 FILES ${AUTOGEN_H}
182 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mim/plug/${PLUGIN}
183 )
184 if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/include")
185 install(
186 DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/include/"
187 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
188 )
189 endif()
190 endif()
191endfunction()