Allow passing target config to generator invocation
So the code generator 'sees' the source code in the same way as the compiler does.
This commit is contained in:
parent
19cab9c791
commit
227d3f3942
10
README.md
10
README.md
|
@ -76,6 +76,7 @@ Note that the header included at the bottom must be generated by invoking the co
|
|||
reflective_rapidjson_generator -i "$srcdir/code-defining-structs.cpp" -o "$builddir/reflection/code-defining-structs.h"
|
||||
```
|
||||
|
||||
#### Invoking code generator with CMake macro
|
||||
It is possible to use the provided CMake macro to automate this task:
|
||||
```
|
||||
find_package(reflective-rapidjson REQUIRED)
|
||||
|
@ -99,6 +100,15 @@ will always have the extension "`.h`", independently of the extension of the inp
|
|||
The full paths of the generated files are also appended to the variable `LIST_OF_GENERATED_HEADERS` which then can be added
|
||||
to the sources of your target. Of course this can be skipped if not required/wanted.
|
||||
|
||||
#### Passing Clang options
|
||||
It is possible to pass additional options to the Clang tool invocation used by the code generator.
|
||||
This can be done using the `--clang-opt` argument or the `CLANG_OPTIONS` argument when using the CMake macro.
|
||||
|
||||
It makes most sense to specify the same options as during compilation so the code generator uses the same flags,
|
||||
defines and include directories as the compiler and hence behaves like the compiler.
|
||||
When using the CMake macro it is possible to automatically pass all compile flags, compile definitions and include directories
|
||||
from certain targets to the code generator. The targets can ge specified using the `CLANG_OPTIONS_FROM_TARGETS` argument.
|
||||
|
||||
### Using Boost.Hana instead of the code generator
|
||||
The same example as above. However, this time Boost.Hana is used - so it doesn't require invoking the generator.
|
||||
|
||||
|
|
|
@ -59,6 +59,8 @@ add_reflection_generator_invocation(
|
|||
json
|
||||
OUTPUT_LISTS
|
||||
TEST_HEADER_FILES
|
||||
CLANG_OPTIONS_FROM_TARGETS
|
||||
reflective_rapidjson_generator_tests
|
||||
JSON_CLASSES
|
||||
OtherNotJsonSerializable # test specifying classes for JSON (de)serialization manually
|
||||
SomeOtherClassName # specifying a class that does not exist should not cause any problems
|
||||
|
|
|
@ -25,8 +25,7 @@ CodeFactory::ToolInvocation::ToolInvocation(CodeFactory &factory)
|
|||
fileManager.Retain();
|
||||
}
|
||||
|
||||
CodeFactory::CodeFactory(
|
||||
const char *applicationPath, const std::vector<const char *> &sourceFiles, const std::vector<const char *> &clangOptions, std::ostream &os)
|
||||
CodeFactory::CodeFactory(const char *applicationPath, const std::vector<const char *> &sourceFiles, const std::vector<string> &clangOptions, std::ostream &os)
|
||||
: m_applicationPath(applicationPath)
|
||||
, m_sourceFiles(sourceFiles)
|
||||
, m_clangOptions(clangOptions)
|
||||
|
|
|
@ -29,7 +29,7 @@ class CodeFactory {
|
|||
|
||||
public:
|
||||
CodeFactory(
|
||||
const char *applicationPath, const std::vector<const char *> &sourceFiles, const std::vector<const char *> &clangOptions, std::ostream &os);
|
||||
const char *applicationPath, const std::vector<const char *> &sourceFiles, const std::vector<std::string> &clangOptions, std::ostream &os);
|
||||
~CodeFactory();
|
||||
|
||||
const std::vector<std::unique_ptr<CodeGenerator>> &generators() const;
|
||||
|
@ -48,7 +48,7 @@ private:
|
|||
|
||||
const char *const m_applicationPath;
|
||||
const std::vector<const char *> &m_sourceFiles;
|
||||
const std::vector<const char *> &m_clangOptions;
|
||||
const std::vector<std::string> &m_clangOptions;
|
||||
std::ostream &m_os;
|
||||
std::vector<std::unique_ptr<CodeGenerator>> m_generators;
|
||||
std::unique_ptr<ToolInvocation> m_toolInvocation;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <c++utilities/application/argumentparser.h>
|
||||
#include <c++utilities/application/commandlineutils.h>
|
||||
#include <c++utilities/application/failure.h>
|
||||
#include <c++utilities/conversion/stringconversion.h>
|
||||
#include <c++utilities/io/ansiescapecodes.h>
|
||||
#include <c++utilities/io/catchiofailure.h>
|
||||
#include <c++utilities/io/misc.h>
|
||||
|
@ -16,6 +17,7 @@
|
|||
|
||||
using namespace std;
|
||||
using namespace ApplicationUtilities;
|
||||
using namespace ConversionUtilities;
|
||||
using namespace EscapeCodes;
|
||||
using namespace IoUtilities;
|
||||
using namespace ReflectiveRapidJSON;
|
||||
|
@ -63,10 +65,23 @@ int main(int argc, char *argv[])
|
|||
os = &cout;
|
||||
}
|
||||
|
||||
// compose options passed to the clang tool invocation
|
||||
vector<string> clangOptions;
|
||||
if(clangOptionsArg.isPresent()) {
|
||||
// add additional options specified via CLI argument
|
||||
for(const auto *const value : clangOptionsArg.values(0)) {
|
||||
// split options by ";" - not nice but this eases using CMake generator expressions
|
||||
const auto splittedValues(splitString<vector<string>>(value, ";", EmptyPartsTreat::Omit));
|
||||
clangOptions.reserve(clangOptions.size() + splittedValues.size());
|
||||
for(const auto &splittedValue : splittedValues) {
|
||||
clangOptions.emplace_back(move(splittedValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// configure code generator
|
||||
vector<const char *> defaultClangOptions;
|
||||
CodeFactory factory(
|
||||
parser.executable(), inputFileArg.values(0), clangOptionsArg.isPresent() ? clangOptionsArg.values(0) : defaultClangOptions, *os);
|
||||
parser.executable(), inputFileArg.values(0), clangOptions, *os);
|
||||
// add only specified generators if the --generator argument is present
|
||||
if (generatorsArg.isPresent()) {
|
||||
// find and construct generators by name
|
||||
|
|
|
@ -26,13 +26,23 @@ if(NOT REFLECTION_GENERATOR_EXECUTABLE)
|
|||
message(FATAL_ERROR "Unable to find executable of generator for reflection code.")
|
||||
endif()
|
||||
|
||||
# define helper functions
|
||||
# define helper function to add a reflection generator invocation for a specified list of source files
|
||||
include(CMakeParseArguments)
|
||||
function(add_reflection_generator_invocation)
|
||||
# parse arguments
|
||||
set(OPTIONAL_ARGS)
|
||||
set(ONE_VALUE_ARGS OUTPUT_DIRECTORY JSON_VISIBILITY)
|
||||
set(MULTI_VALUE_ARGS INPUT_FILES GENERATORS OUTPUT_LISTS CLANG_OPTIONS JSON_CLASSES)
|
||||
set(OPTIONAL_ARGS
|
||||
)
|
||||
set(ONE_VALUE_ARGS
|
||||
OUTPUT_DIRECTORY
|
||||
JSON_VISIBILITY
|
||||
)
|
||||
set(MULTI_VALUE_ARGS
|
||||
INPUT_FILES
|
||||
GENERATORS
|
||||
OUTPUT_LISTS
|
||||
CLANG_OPTIONS
|
||||
CLANG_OPTIONS_FROM_TARGETS
|
||||
JSON_CLASSES)
|
||||
cmake_parse_arguments(ARGS "${OPTIONAL_ARGS}" "${ONE_VALUE_ARGS}" "${MULTI_VALUE_ARGS}" ${ARGN})
|
||||
|
||||
# determine file name or file path if none specified
|
||||
|
@ -41,10 +51,29 @@ function(add_reflection_generator_invocation)
|
|||
file(MAKE_DIRECTORY "${ARGS_OUTPUT_DIRECTORY}")
|
||||
endif()
|
||||
|
||||
# add options to be passed to clang from the specified targets
|
||||
if(ARGS_CLANG_OPTIONS_FROM_TARGETS)
|
||||
foreach(TARGET_NAME ${ARGS_CLANG_OPTIONS_FROM_TARGETS})
|
||||
# add compile flags
|
||||
set(PROP "$<TARGET_PROPERTY:${TARGET_NAME},COMPILE_FLAGS>")
|
||||
list(APPEND ARGS_CLANG_OPTIONS "$<$<BOOL:${PROP}>:$<JOIN:${PROP},$<SEMICOLON>>>")
|
||||
# add compile definitions
|
||||
set(PROP "$<TARGET_PROPERTY:${TARGET_NAME},COMPILE_DEFINITIONS>")
|
||||
list(APPEND ARGS_CLANG_OPTIONS "$<$<BOOL:${PROP}>:-D$<JOIN:${PROP},$<SEMICOLON>-D>>")
|
||||
# add include directories
|
||||
set(PROP "$<TARGET_PROPERTY:${TARGET_NAME},INCLUDE_DIRECTORIES>")
|
||||
list(APPEND ARGS_CLANG_OPTIONS "$<$<BOOL:${PROP}>:-I$<JOIN:${PROP},$<SEMICOLON>-I>>")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# create a custom command for each input file
|
||||
foreach(INPUT_FILE ${ARGS_INPUT_FILES})
|
||||
# determine the output file
|
||||
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}")
|
||||
|
||||
# compose the CLI arguments and actually add the custom command
|
||||
set(CLI_ARGUMENTS
|
||||
--output-file "${OUTPUT_FILE}"
|
||||
--input-file "${INPUT_FILE}"
|
||||
|
@ -62,6 +91,7 @@ function(add_reflection_generator_invocation)
|
|||
DEPENDS "${INPUT_FILE}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
COMMENT "Generating reflection code for ${INPUT_FILE}"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# append the output file to lists specified via OUTPUT_LISTS
|
||||
|
|
Loading…
Reference in New Issue