forked from mavlink/MAVSDK
-
Notifications
You must be signed in to change notification settings - Fork 0
/
autogenerate_plugin_container.cmake
175 lines (147 loc) · 6.43 KB
/
autogenerate_plugin_container.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# Description
# -----------
#
# This cmake script searches through the plugins directory and generates the
# files device_plugin_container.h and device_plugin_container.cpp using the
# templates device_plugin_container.h.in and device_plugin_container.cpp.in.
#
# Each plugin should have the following structure:
#
# example
# ├── CMakeLists.txt
# ├── example.cpp
# ├── example.h
# ├── example_impl.cpp
# └── example_impl.h
#
# An example plugin can be found in example_plugin/
#
# example.h and example.cpp define the publicly visible interface and
# example_impl.h and example_impl.cpp contain the implementation of the
# actual plugin.
if (DEFINED EXTERNAL_DIR)
message("External plugin folder: ${EXTERNAL_DIR}")
endif()
# This defines the plugins directory.
file(GLOB plugins plugins/*)
file(GLOB external_plugins ${EXTERNAL_DIR}/plugins/*)
# Look for plugins in plugin directory
foreach(plugin ${plugins})
if(IS_DIRECTORY ${plugin})
message("Found plugin ${plugin}")
set(class_name "")
set(source_files "")
set(unittest_source_files "")
set(header_files "")
set(impl_header_files "")
add_subdirectory(${plugin})
foreach(source_file ${source_files})
list(APPEND plugin_source_files "${plugin}/${source_file}")
endforeach()
foreach(unittest_source_file ${unittest_source_files})
list(APPEND plugin_unittest_source_files "${plugin}/${unittest_source_file}")
endforeach()
foreach(header_file ${header_files})
list(APPEND plugin_header_paths "${plugin}/${header_file}")
endforeach()
list(APPEND plugin_class_names "${class_name}")
list(APPEND plugin_header_files "${header_files}")
list(APPEND plugin_impl_header_files "${impl_header_files}")
endif()
endforeach()
# Look for plugins in external plugin directory
foreach(plugin ${external_plugins})
if(IS_DIRECTORY ${plugin})
message("Found external plugin ${plugin}")
set(class_name "")
set(source_files "")
set(unittest_source_files "")
set(header_files "")
set(impl_header_files "")
# On Windows we need to replace C: to C
string(REPLACE ":" "" plugin_safe ${plugin})
add_subdirectory(${plugin} ${CMAKE_CURRENT_BINARY_DIR}/${plugin_safe})
foreach(source_file ${source_files})
list(APPEND plugin_source_files "${plugin}/${source_file}")
endforeach()
foreach(unittest_source_file ${unittest_source_files})
list(APPEND plugin_unittest_source_files "${plugin}/${unittest_source_file}")
endforeach()
foreach(header_file ${header_files})
list(APPEND plugin_header_paths "${plugin}/${header_file}")
endforeach()
list(APPEND plugin_class_names "${class_name}")
list(APPEND plugin_header_files "${header_files}")
list(APPEND plugin_impl_header_files "${impl_header_files}")
endif()
endforeach()
message("done: ${plugin_unittest_source_files}")
# Contains the #include "example.h" for the public facing files.
set(INCLUDES_STRING "")
foreach(header_file ${plugin_header_files})
set(INCLUDES_STRING "${INCLUDES_STRING}#include \"${header_file}\"\n")
endforeach()
# Contains #include "include "example_impl.h" for the implementation header files.
set(IMPL_INCLUDES_STRING "")
foreach(impl_header_file ${plugin_impl_header_files})
set(IMPL_INCLUDES_STRING "${IMPL_INCLUDES_STRING}#include \"${impl_header_file}\"\n")
endforeach()
# Contains the forward declarations such as `class ExampleImpl;`.
set(FORWARD_DECLARATION_STRING "")
# Contains the constructor entries.
set(PLUGIN_CTOR_STRING "")
# Contains the destructor entries.
set(PLUGIN_DTOR_STRING "")
# Contains the member variables for the plugin instances.
set(PLUGIN_MEMBER_STRING "")
# Contains the getter methods which allow to access a plugin with device().example().
set(PLUGIN_GET_STRING "")
# Creates a list of the plugin implementations to call init()/deinit() on them.
set(PLUGIN_LIST_APPEND_STRING "")
# Go through all the plugins and generate the strings.
foreach(class_name ${plugin_class_names})
# We want to go from CamelCase to snake_case.
# CamelCase -> Camel_Case
string(REGEX REPLACE "(.)([A-Z][a-z]+)" "\\1_\\2" class_name_with_underscores "${class_name}")
# Camel0Case -> Camel0_Case
string(REGEX REPLACE "([a-z0-9])([A-Z])" "\\1_\\2" class_name_with_underscores "${class_name_with_underscores}")
# Camel_Case to snake_case
string(TOLOWER ${class_name_with_underscores} class_name_lowercase)
set(get_name ${class_name_lowercase})
set(member_name "_${class_name_lowercase}")
set(impl_class_name "${class_name}Impl")
set(impl_member_name "_${class_name_lowercase}_impl")
set(FORWARD_DECLARATION_STRING
"${FORWARD_DECLARATION_STRING}class ${impl_class_name};\n")
set(PLUGIN_GET_STRING
"${PLUGIN_GET_STRING} /**\n")
set(PLUGIN_GET_STRING
"${PLUGIN_GET_STRING} * Getter for ${class_name} plugin.\n")
set(PLUGIN_GET_STRING
"${PLUGIN_GET_STRING} *\n")
set(PLUGIN_GET_STRING
"${PLUGIN_GET_STRING} * @return a reference to the ${get_name} plugin instance\n")
set(PLUGIN_GET_STRING
"${PLUGIN_GET_STRING} */\n")
set(PLUGIN_GET_STRING
"${PLUGIN_GET_STRING} ${class_name} &${get_name}() { return *${member_name}; }\n\n")
set(PLUGIN_MEMBER_STRING
"${PLUGIN_MEMBER_STRING} /** @private internal use only.*/\n")
set(PLUGIN_MEMBER_STRING
"${PLUGIN_MEMBER_STRING} ${impl_class_name} *${impl_member_name};\n")
set(PLUGIN_MEMBER_STRING
"${PLUGIN_MEMBER_STRING} /** @private internal use only.*/\n")
set(PLUGIN_MEMBER_STRING
"${PLUGIN_MEMBER_STRING} ${class_name} *${member_name};\n")
set(PLUGIN_CTOR_STRING
"${PLUGIN_CTOR_STRING} ${impl_member_name} = new ${impl_class_name}();\n")
set(PLUGIN_CTOR_STRING
"${PLUGIN_CTOR_STRING} ${member_name} = new ${class_name}(${impl_member_name}),\n")
set(PLUGIN_DTOR_STRING
"${PLUGIN_DTOR_STRING} delete ${member_name};\n")
set(PLUGIN_LIST_APPEND_STRING
"${PLUGIN_LIST_APPEND_STRING} _plugin_impl_list.push_back(${impl_member_name});\n")
endforeach()
# Do the string replacements.
configure_file(include/device_plugin_container.h.in include/device_plugin_container.h)
configure_file(core/device_plugin_container.cpp.in core/device_plugin_container.cpp)