Allow exporting generated functions and don't inline by default
This commit is contained in:
parent
9f0f208f28
commit
ee0ca561c0
1
TODOs.md
1
TODOs.md
|
@ -13,6 +13,7 @@
|
|||
- [x] Add additional parameter for code generator to allow specifying relevant classes
|
||||
explicitely
|
||||
- [x] Fix traits currently relying on `JsonSerializable` being base class
|
||||
- [x] Allow exporting symbols
|
||||
|
||||
## Library-only
|
||||
- [ ] Support `std::unique_ptr` and `std::shared_ptr`
|
||||
|
|
|
@ -63,6 +63,8 @@ add_reflection_generator_invocation(
|
|||
JSON_CLASSES
|
||||
OtherNotJsonSerializable # test specifying classes for JSON (de)serialization manually
|
||||
SomeOtherClassName # specifying a class that does not exist should not cause any problems
|
||||
JSON_VISIBILITY
|
||||
LIB_EXPORT # not required, just to test setting visibility
|
||||
)
|
||||
|
||||
# include modules to apply configuration
|
||||
|
|
|
@ -13,12 +13,17 @@ using namespace ApplicationUtilities;
|
|||
|
||||
namespace ReflectiveRapidJSON {
|
||||
|
||||
/*!
|
||||
* \brief Initializes the CLI arguments which are specific to the JsonSerializationCodeGenerator.
|
||||
* \todo Find a more general approach to pass CLI arguments from main() to the particular code generators.
|
||||
*/
|
||||
JsonSerializationCodeGenerator::Options::Options()
|
||||
: additionalClassesArg("json-classes", '\0', "specifies additional classes to consider for JSON serialization")
|
||||
: additionalClassesArg("json-classes", '\0', "specifies additional classes to consider for JSON serialization", { "class-name" })
|
||||
, visibilityArg("json-visibility", '\0', "specifies the \"visibility attribute\" for generated functions", { "attribute" })
|
||||
{
|
||||
additionalClassesArg.setCombinable(true);
|
||||
additionalClassesArg.setValueNames({ "class-name" });
|
||||
additionalClassesArg.setRequiredValueCount(Argument::varValueCount);
|
||||
additionalClassesArg.setValueCompletionBehavior(ValueCompletionBehavior::None);
|
||||
visibilityArg.setPreDefinedCompletionValues("LIB_EXPORT");
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -86,6 +91,12 @@ void JsonSerializationCodeGenerator::generate(ostream &os) const
|
|||
os << "namespace ReflectiveRapidJSON {\n"
|
||||
"namespace JsonReflector {\n\n";
|
||||
|
||||
// determine visibility attribute
|
||||
const char *visibility = m_options.visibilityArg.firstValue();
|
||||
if (!visibility) {
|
||||
visibility = "";
|
||||
}
|
||||
|
||||
// add push and pull functions for each class, for an example of the resulting
|
||||
// output, see ../lib/tests/jsonserializable.cpp (code under comment "pretend serialization code...")
|
||||
for (const RelevantClass &relevantClass : relevantClasses) {
|
||||
|
@ -117,7 +128,7 @@ void JsonSerializationCodeGenerator::generate(ostream &os) const
|
|||
const vector<const RelevantClass *> relevantBases = findRelevantBaseClasses(relevantClass, relevantClasses);
|
||||
|
||||
// print push method
|
||||
os << "template <> inline void push<::" << relevantClass.qualifiedName << ">(const ::" << relevantClass.qualifiedName
|
||||
os << "template <> " << visibility << " void push<::" << relevantClass.qualifiedName << ">(const ::" << relevantClass.qualifiedName
|
||||
<< " &reflectable, ::RAPIDJSON_NAMESPACE::Value::Object &value, ::RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)\n{\n"
|
||||
" // push base classes\n";
|
||||
for (const RelevantClass *baseClass : relevantBases) {
|
||||
|
@ -132,7 +143,7 @@ void JsonSerializationCodeGenerator::generate(ostream &os) const
|
|||
os << "}\n";
|
||||
|
||||
// print pull method
|
||||
os << "template <> inline void pull<::" << relevantClass.qualifiedName << ">(::" << relevantClass.qualifiedName
|
||||
os << "template <> " << visibility << " void pull<::" << relevantClass.qualifiedName << ">(::" << relevantClass.qualifiedName
|
||||
<< " &reflectable, const ::RAPIDJSON_NAMESPACE::GenericValue<::RAPIDJSON_NAMESPACE::UTF8<char>>::ConstObject &value, "
|
||||
"JsonDeserializationErrors "
|
||||
"*errors)\n{\n"
|
||||
|
|
|
@ -15,8 +15,10 @@ class JsonSerializationCodeGenerator : public CodeGenerator {
|
|||
public:
|
||||
struct Options {
|
||||
Options();
|
||||
void appendTo(ApplicationUtilities::Argument *arg);
|
||||
|
||||
ApplicationUtilities::Argument additionalClassesArg;
|
||||
ApplicationUtilities::ConfigValueArgument additionalClassesArg;
|
||||
ApplicationUtilities::ConfigValueArgument visibilityArg;
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -43,6 +45,12 @@ private:
|
|||
const Options &m_options;
|
||||
};
|
||||
|
||||
inline void JsonSerializationCodeGenerator::Options::appendTo(ApplicationUtilities::Argument *arg)
|
||||
{
|
||||
arg->addSubArgument(&additionalClassesArg);
|
||||
arg->addSubArgument(&visibilityArg);
|
||||
}
|
||||
|
||||
inline JsonSerializationCodeGenerator::JsonSerializationCodeGenerator(CodeFactory &factory, const Options &options)
|
||||
: CodeGenerator(factory)
|
||||
, m_options(options)
|
||||
|
|
|
@ -38,10 +38,11 @@ int main(int argc, char *argv[])
|
|||
generatorsArg.setCombinable(true);
|
||||
ConfigValueArgument clangOptionsArg("clang-opt", 'c', "specifies arguments/options to be passed to Clang", { "option" });
|
||||
clangOptionsArg.setRequiredValueCount(Argument::varValueCount);
|
||||
JsonSerializationCodeGenerator::Options jsonOptions;
|
||||
HelpArgument helpArg(parser);
|
||||
NoColorArgument noColorArg;
|
||||
generateArg.setSubArguments({ &inputFileArg, &outputFileArg, &generatorsArg, &clangOptionsArg, &jsonOptions.additionalClassesArg });
|
||||
generateArg.setSubArguments({ &inputFileArg, &outputFileArg, &generatorsArg, &clangOptionsArg });
|
||||
JsonSerializationCodeGenerator::Options jsonOptions;
|
||||
jsonOptions.appendTo(&generateArg);
|
||||
parser.setMainArguments({ &generateArg, &noColorArg, &helpArg });
|
||||
|
||||
// parse arguments
|
||||
|
|
|
@ -2,14 +2,14 @@ namespace ReflectiveRapidJSON {
|
|||
namespace JsonReflector {
|
||||
|
||||
// define code for (de)serializing TestNamespace1::Person objects
|
||||
template <> inline void push<::TestNamespace1::Person>(const ::TestNamespace1::Person &reflectable, ::RAPIDJSON_NAMESPACE::Value::Object &value, ::RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
|
||||
template <> void push<::TestNamespace1::Person>(const ::TestNamespace1::Person &reflectable, ::RAPIDJSON_NAMESPACE::Value::Object &value, ::RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
|
||||
{
|
||||
// push base classes
|
||||
// push members
|
||||
push(reflectable.age, "age", value, allocator);
|
||||
push(reflectable.alive, "alive", value, allocator);
|
||||
}
|
||||
template <> inline void pull<::TestNamespace1::Person>(::TestNamespace1::Person &reflectable, const ::RAPIDJSON_NAMESPACE::GenericValue<::RAPIDJSON_NAMESPACE::UTF8<char>>::ConstObject &value, JsonDeserializationErrors *errors)
|
||||
template <> void pull<::TestNamespace1::Person>(::TestNamespace1::Person &reflectable, const ::RAPIDJSON_NAMESPACE::GenericValue<::RAPIDJSON_NAMESPACE::UTF8<char>>::ConstObject &value, JsonDeserializationErrors *errors)
|
||||
{
|
||||
// pull base classes
|
||||
// set error context for current record
|
||||
|
@ -28,14 +28,14 @@ template <> inline void pull<::TestNamespace1::Person>(::TestNamespace1::Person
|
|||
}
|
||||
|
||||
// define code for (de)serializing TestNamespace2::ThirdPartyStruct objects
|
||||
template <> inline void push<::TestNamespace2::ThirdPartyStruct>(const ::TestNamespace2::ThirdPartyStruct &reflectable, ::RAPIDJSON_NAMESPACE::Value::Object &value, ::RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
|
||||
template <> void push<::TestNamespace2::ThirdPartyStruct>(const ::TestNamespace2::ThirdPartyStruct &reflectable, ::RAPIDJSON_NAMESPACE::Value::Object &value, ::RAPIDJSON_NAMESPACE::Document::AllocatorType &allocator)
|
||||
{
|
||||
// push base classes
|
||||
// push members
|
||||
push(reflectable.test1, "test1", value, allocator);
|
||||
push(reflectable.test2, "test2", value, allocator);
|
||||
}
|
||||
template <> inline void pull<::TestNamespace2::ThirdPartyStruct>(::TestNamespace2::ThirdPartyStruct &reflectable, const ::RAPIDJSON_NAMESPACE::GenericValue<::RAPIDJSON_NAMESPACE::UTF8<char>>::ConstObject &value, JsonDeserializationErrors *errors)
|
||||
template <> void pull<::TestNamespace2::ThirdPartyStruct>(::TestNamespace2::ThirdPartyStruct &reflectable, const ::RAPIDJSON_NAMESPACE::GenericValue<::RAPIDJSON_NAMESPACE::UTF8<char>>::ConstObject &value, JsonDeserializationErrors *errors)
|
||||
{
|
||||
// pull base classes
|
||||
// set error context for current record
|
||||
|
|
|
@ -31,7 +31,7 @@ include(CMakeParseArguments)
|
|||
function(add_reflection_generator_invocation)
|
||||
# parse arguments
|
||||
set(OPTIONAL_ARGS)
|
||||
set(ONE_VALUE_ARGS OUTPUT_DIRECTORY)
|
||||
set(ONE_VALUE_ARGS OUTPUT_DIRECTORY JSON_VISIBILITY)
|
||||
set(MULTI_VALUE_ARGS INPUT_FILES GENERATORS OUTPUT_LISTS CLANG_OPTIONS JSON_CLASSES)
|
||||
cmake_parse_arguments(ARGS "${OPTIONAL_ARGS}" "${ONE_VALUE_ARGS}" "${MULTI_VALUE_ARGS}" ${ARGN})
|
||||
|
||||
|
@ -45,14 +45,20 @@ function(add_reflection_generator_invocation)
|
|||
get_filename_component(OUTPUT_NAME "${INPUT_FILE}" NAME_WE)
|
||||
set(OUTPUT_FILE "${ARGS_OUTPUT_DIRECTORY}/${OUTPUT_NAME}.h")
|
||||
message(STATUS "Adding generator command for ${INPUT_FILE} producing ${OUTPUT_FILE}")
|
||||
set(CLI_ARGUMENTS
|
||||
--output-file "${OUTPUT_FILE}"
|
||||
--input-file "${INPUT_FILE}"
|
||||
--generators ${ARGS_GENERATORS}
|
||||
--clang-opt ${ARGS_CLANG_OPTIONS}
|
||||
--json-classes ${ARGS_JSON_CLASSES}
|
||||
)
|
||||
if(ARGS_JSON_VISIBILITY)
|
||||
list(APPEND CLI_ARGUMENTS --json-visibility "${ARGS_JSON_VISIBILITY}")
|
||||
endif()
|
||||
add_custom_command(
|
||||
OUTPUT "${OUTPUT_FILE}"
|
||||
COMMAND "${REFLECTION_GENERATOR_EXECUTABLE}"
|
||||
--output-file "${OUTPUT_FILE}"
|
||||
--input-file "${INPUT_FILE}"
|
||||
--generators ${ARGS_GENERATORS}
|
||||
--clang-opt ${ARGS_CLANG_OPTIONS}
|
||||
--json-classes ${ARGS_JSON_CLASSES}
|
||||
ARGS ${CLI_ARGUMENTS}
|
||||
DEPENDS "${INPUT_FILE}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
COMMENT "Generating reflection code for ${INPUT_FILE}"
|
||||
|
|
Loading…
Reference in New Issue