From ea977c8aa88fbea40402c3244910d6570aef82a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20S=C3=A1nchez?= Date: Thu, 1 Sep 2016 12:10:23 +0200 Subject: [PATCH] Package-friendly configuration. Bootstrap script --- CMakeLists.txt | 5 + bootstrap.cmake | 27 ++++++ cmake/CMakeLists.txt | 11 +++ cmake/cpacksettings.cmake | 2 +- cmake/install.cmake | 11 +-- cmake/libclang.cmake | 19 ++-- cmake/siplasplas.cmake | 22 +++++ cmake/thirdparty.cmake | 3 + cmake/utils.cmake | 1 - src/reflection/parser/DRLParser | 60 +++++++----- src/reflection/parser/drlparser.cmake | 93 ++++++++++++++----- .../parser/templates/reflection_template.hpp | 3 +- .../parser/translationunitprocessor.py | 25 +++-- 13 files changed, 209 insertions(+), 73 deletions(-) create mode 100644 bootstrap.cmake create mode 100644 cmake/CMakeLists.txt create mode 100644 cmake/siplasplas.cmake mode change 100644 => 100755 src/reflection/parser/DRLParser diff --git a/CMakeLists.txt b/CMakeLists.txt index d13d6d4..440d64d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,8 @@ set(SIPLASPLAS_VERSION_MINOR 0) set(SIPLASPLAS_VERSION_PATCH 0) set(SIPLASPLAS_DRLPARSER_PYTHON_VERSION 2.7) +set(SIPLASPLAS_BUILDING_FROM_SOURCES TRUE CACHE INTERNAL "") +set(SIPLASPLAS_ROOT "${CMAKE_SOURCE_DIR}") include(cmake/deftargets.cmake) include(cmake/install.cmake) @@ -31,6 +33,9 @@ option(SIPLASPLAS_ENABLE_VALGRIND "Enable memory check of executable targets" OF option(SIPLASPLAS_ENABLE_ASSERTS "Force assertions, which are disabled by default on Release build" OFF) option(SIPLASPLAS_DUMP_ERRORS "Dump error logs after running an executable. Implies SIPLASPLAS_CLEAR_LOGS" ON) +include(cmake/siplasplas.cmake) + +add_subdirectory(cmake) add_subdirectory(3rdParty) add_subdirectory(src) diff --git a/bootstrap.cmake b/bootstrap.cmake new file mode 100644 index 0000000..1a07d31 --- /dev/null +++ b/bootstrap.cmake @@ -0,0 +1,27 @@ +if(NOT SIPLASPLAS_ROOT) + if(SIPLASPLAS_PACKAGE_URL) + set(SIPLASPLAS_PACKAGE "${CMAKE_BINARY_DIR}/siplasplas_package") + file(DOWNLOAD "${SIPLASPLAS_PACKAGE_URL}" "${SIPLASPLAS_PACKAGE}" SHOW_PROGRESS) + endif() + + if(NOT SIPLASPLAS_PACKAGE OR NOT EXISTS "${SIPLASPLAS_PACKAGE}") + message(FATAL_ERROR "No siplasplas package found") + endif() + + get_filename_component(SIPLASPLAS_PACKAGE_NAME "${SIPLASPLAS_PACKAGE}" NAME_WE) + + if(NOT EXISTS "${SIPLASPLAS_PACKAGE_NAME}") + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xvf "${SIPLASPLAS_PACKAGE}" + ) + endif() + + set(SIPLASPLAS_ROOT "${CMAKE_BINARY_DIR}/${SIPLASPLAS_PACKAGE_NAME}" CACHE INTERNAL "") +endif() + +if(EXISTS "${SIPLASPLAS_ROOT}") + list(APPEND CMAKE_MODULE_PATH "${SIPLASPLAS_ROOT}/cmake") + include(siplasplas) +else() + message(FATAL_ERROR "The siplasplas root directory (${SIPLASPLAS_ROOT}) does not exist") +endif() diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt new file mode 100644 index 0000000..9148b40 --- /dev/null +++ b/cmake/CMakeLists.txt @@ -0,0 +1,11 @@ +install( +FILES + utils.cmake + libclang.cmake + pip.cmake + FindLibClang.cmake + FindPythonPip.cmake + siplasplas.cmake +DESTINATION + cmake/ +) diff --git a/cmake/cpacksettings.cmake b/cmake/cpacksettings.cmake index b74a84c..617f67d 100644 --- a/cmake/cpacksettings.cmake +++ b/cmake/cpacksettings.cmake @@ -1,4 +1,3 @@ - set(PACKAGE_VARIANT "${CMAKE_CXX_COMPILER_ID}-${CMAKE_CXX_COMPILER_VERSION}-${CMAKE_BUILD_TYPE}") if(SIPLASPLAS_LIBRARIES_STATIC) @@ -23,6 +22,7 @@ string(REGEX REPLACE "\n" "" branch "${branch}") string(REGEX REPLACE " " "-" branch "${branch}") set(CPACK_PACKAGE_FILE_NAME "siplasplas-${branch}-${PACKAGE_VARIANT}") +string(REGEX REPLACE "\\." "_" CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}") set(CPACK_PACKAGE_VENDOR "Manu Sánchez") set(CPACK_PACKAGE_DESCRIPTION "Examples and utilities for the Advanced C++ course for the GUEIM association, Complutense University of Madrid") set(CPACK_PACKAGE_VERSION_MAJOR ${SIPLASPLAS_VERSION_MAJOR}) diff --git a/cmake/install.cmake b/cmake/install.cmake index 7430dea..12e9075 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -6,18 +6,9 @@ function(install_siplasplas_library TARGET) RUNTIME DESTINATION bin COMPONENT libraries ) - - headerdir_from_sourcetree(dir) - install(DIRECTORY ${dir} DESTINATION include/siplasplas - COMPONENT headers - ) endfunction() function(install_siplasplas_headeronly_library TARGET) - headerdir_from_sourcetree(dir) - install(DIRECTORY ${dir} DESTINATION include/siplasplas - COMPONENT headers - ) endfunction() function(install_siplasplas_example EXAMPLE) @@ -40,3 +31,5 @@ function(install_siplasplas_example EXAMPLE) ) endif() endfunction() + +install(DIRECTORY "${CMAKE_SOURCE_DIR}/include/siplasplas" DESTINATION include/) diff --git a/cmake/libclang.cmake b/cmake/libclang.cmake index b0377df..b3b9252 100644 --- a/cmake/libclang.cmake +++ b/cmake/libclang.cmake @@ -119,6 +119,7 @@ if(SIPLASPLAS_DOWNLOAD_LIBCLANG) if(length EQUAL 1) if(IS_DIRECTORY "${CMAKE_BINARY_DIR}/llvm/${llvm_contents}") set(llvm_root "${CMAKE_BINARY_DIR}/llvm/${llvm_contents}") + string(STRIP llvm_root "${llvm_root}") else() message(FATAL_ERROR "Extracted llvm directory \"${llvm_contents}\" is not a directory") endif() @@ -129,10 +130,14 @@ if(SIPLASPLAS_DOWNLOAD_LIBCLANG) message(FATAL_ERROR "LLVM package contents not recognized, only a root directory was expected") endif() - find_library(libclang_library NAMES clang libclang HINTS "${llvm_root}/lib") + if(WIN32) + set(libclang_library "${llvm_root}/lib/libclang.dll") + else() + set(libclang_library "${llvm_root}/lib/libclang.so") + endif() # Write output variables: - if(libclang_library) + if(libclang_library AND EXISTS "${libclang_library}") set(SIPLASPLAS_LIBCLANG_LIBRARY "${libclang_library}") else() message(FATAL_ERROR "Could not find libclang library at ${llvm_root}/lib") @@ -168,10 +173,12 @@ endif() string(REGEX REPLACE "([0-9]+\\.[0-9]+)\\.[0-9]+" "\\1" SIPLASPLAS_LIBCLANG_VERSION_MAJOR_MINOR "${SIPLASPLAS_LIBCLANG_VERSION}") -message(STATUS "libclang version: ${SIPLASPLAS_LIBCLANG_VERSION} (${SIPLASPLAS_LIBCLANG_VERSION_MAJOR_MINOR})") -message(STATUS "libclang library: ${SIPLASPLAS_LIBCLANG_LIBRARY}") -message(STATUS "libclang include dir: ${SIPLASPLAS_LIBCLANG_INCLUDE_DIR}") -message(STATUS "libclang system include dir: ${SIPLASPLAS_LIBCLANG_SYSTEM_INCLUDE_DIR}") +if(SIPLASPLAS_VERBOSE_CONFIG) + message(STATUS "libclang version: ${SIPLASPLAS_LIBCLANG_VERSION} (${SIPLASPLAS_LIBCLANG_VERSION_MAJOR_MINOR})") + message(STATUS "libclang library: ${SIPLASPLAS_LIBCLANG_LIBRARY}") + message(STATUS "libclang include dir: ${SIPLASPLAS_LIBCLANG_INCLUDE_DIR}") + message(STATUS "libclang system include dir: ${SIPLASPLAS_LIBCLANG_SYSTEM_INCLUDE_DIR}") +endif() function(gxx_executable _ret) if(SIPLASPLAS_GXX) diff --git a/cmake/siplasplas.cmake b/cmake/siplasplas.cmake new file mode 100644 index 0000000..79cf767 --- /dev/null +++ b/cmake/siplasplas.cmake @@ -0,0 +1,22 @@ +if(NOT SIPLASPLAS_ROOT) + message(FATAL_ERROR "siplasplas installation not found. Use SIPLASPLAS_ROOT variable to specify the path to your siplasplas installation") +endif() + +set(SIPLAPLAS_LIB_DIR "${SIPLASPLAS_ROOT}/lib" CACHE INTERNAL "") +set(SIPLASPLAS_CMAKE_DIR "${SIPLASPLAS_ROOT}/cmake" CACHE INTERNAL "") +set(SIPLASPLAS_BIN_DIR "${SIPLASPLAS_ROOT}/bin" CACHE INTERNAL "") +set(SIPLASPLAS_INCLUDE_DIR "${SIPLASPLAS_ROOT}/include" CACHE INTERNAL "") + +if(NOT SIPLASPLAS_DRLPARSER_PYTHON_VERSION) + set(SIPLASPLAS_DRLPARSER_PYTHON_VERSION 2.7) +endif() + +if(SIPLASPLAS_BUILDING_FROM_SOURCES) + set(SIPLASPLAS_DRLPARSER_DIR "${CMAKE_SOURCE_DIR}/src/reflection/parser") +else() + set(SIPLASPLAS_DRLPARSER_DIR "${SIPLASPLAS_BIN_DIR}/reflection-parser/parser" CACHE INTERNAL "") +endif() +list(APPEND CMAKE_MODULE_PATH "${SIPLASPLAS_CMAKE_DIR}" "${SIPLASPLAS_DRLPARSER_DIR}") + +include(utils) +include(drlparser) diff --git a/cmake/thirdparty.cmake b/cmake/thirdparty.cmake index c29d54f..bfde1da 100644 --- a/cmake/thirdparty.cmake +++ b/cmake/thirdparty.cmake @@ -222,12 +222,15 @@ function(add_siplasplas_thirdparty_component NAME) if(COMPONENT_SHARED) compute_binary_file(${COMPONENT_BINARY_NAME} SHARED "${COMPONENT_LIBRARY_SUFFIX}${COMPONENT_SHARED_LIBRARY_SUFFIX}" "${COMPONENT_BINARY_DIR}" libfile) + install(FILES "${binary_dir}/${libfile}" DESTINATION lib) # We should import the location of the import lib (.lib) too to link with the dll # (In dll platforms you link against the import lib, not the dynamic library) if(MSVC) compute_binary_file(${COMPONENT_BINARY_NAME} IMPORT "${COMPONENT_LIBRARY_SUFFIX}" "${COMPONENT_BINARY_DIR}" importedlibfile) + install(FILES "${binary_dir}/${importedlibfile}" DESTINATION lib) endif() + else() compute_binary_file(${COMPONENT_BINARY_NAME} STATIC "${COMPONENT_LIBRARY_SUFFIX}" "${COMPONENT_BINARY_DIR}" libfile) endif() diff --git a/cmake/utils.cmake b/cmake/utils.cmake index b6a737a..b196a76 100644 --- a/cmake/utils.cmake +++ b/cmake/utils.cmake @@ -1,4 +1,3 @@ - # Returns the relative path of the # current source dir against the source # tree root. diff --git a/src/reflection/parser/DRLParser b/src/reflection/parser/DRLParser old mode 100644 new mode 100755 index 39bc228..847c6a3 --- a/src/reflection/parser/DRLParser +++ b/src/reflection/parser/DRLParser @@ -37,6 +37,7 @@ class Compiler: self.outputdir = output_dir self.print_ast = print_ast self.jinjaTemplateFile = jinjaTemplateFile + self.verbose = verbose import jinja2 from jinja2 import Template, Environment, FileSystemLoader @@ -59,15 +60,17 @@ class Compiler: self.logger.step('({}outdated{}) {}'.format(Fore.RED, Fore.RESET, self.pathformat.format(tu.filePath))) outputfile = self._output_file(tu.filePath) - self.logger.info('Output file: {}'.format(outputfile)) + + if self.verbose: + self.logger.info('Output file: {}'.format(outputfile)) # Touch the output file so #include doesn't fail if not os.path.exists(outputfile): with open(outputfile, 'w') as f: f.close() - tu.process() - tu.run_jinja(outputfile) + tu.process(self.verbose) + tu.run_jinja(outputfile, self.verbose) self.syncmanager.sync(sourcefile, os.path.relpath(outputfile, self.sourcedir)) tu.dispose() # Release translation unit memory (Clang AST, processed AST, etc) else: @@ -114,9 +117,8 @@ class App: return outputfiles def splashscreen(self, message): - print '{}==>{} {}'.format(Fore.MAGENTA, Fore.RESET, message) - print ' {}{}{}'.format(Fore.MAGENTA, '='*len(message), Fore.RESET) - print '' + print message + print '{}{}{}'.format(Fore.GREEN, '='*len(message), Fore.RESET) def split_argument(self, arg): if arg: @@ -135,8 +137,8 @@ class App: return False def __init__(self): - self.splashscreen('Dynamic Reflection Library Parser') - self.logger = Logger(Fore.MAGENTA) + self.splashscreen('siplasplas reflection parser') + self.logger = Logger(Fore.GREEN) parser = argparse.ArgumentParser(description='Dynamic Reflection Library Parser') parser.add_argument('--compile-options', default = '', help = 'Clang compile options') @@ -146,7 +148,8 @@ class App: parser.add_argument('-I', '--includedirs', default = '', help = 'Extra include directories for libclang parser') parser.add_argument('-s', '--sourcedir', help = 'Project source directory') parser.add_argument('-x', '--exclude', nargs = '*', default = [], help = 'List of GLOBs to exclude source files from include directories scan') - parser.add_argument('--blacklist', nargs ='*', default = [], help = 'Subset of searchdirs to ignore') + parser.add_argument('--blacklist', default = '', help = 'Subset of searchdirs to ignore') + parser.add_argument('--no-ignore-externals', action = 'store_true', help = 'Do not ignore include directories external to the sourcetree during search') parser.add_argument('-e', '--extensions', nargs = '*', default = ['.hpp', '.h', '.hxx'], help = 'List of file extensions used for include directory input files scan') parser.add_argument('-i', '--ignore-database', action = 'store_true', help = 'Ignore database records (Ignore input file timestamps, process file always)') parser.add_argument('-l', '--libclang', help = 'Full path to libclang library (libclang.so)') @@ -160,11 +163,10 @@ class App: GlobalLogger.enabled(self.args.verbose) if self.args.libclang: - self.logger.step('libclang.so: ' + self.args.libclang) + libclang_binary = self.args.libclang clang.cindex.Config.set_library_file(self.args.libclang) else: - config = clang.cindex.Config() - self.logger.step('libclang.so: ' + os.path.abspath(config.get_filename())) + libclang_binary = os.path.realpath(clang.cindex.Config().get_filename()) self.args.compile_options = self.split_argument(self.args.compile_options) @@ -172,15 +174,25 @@ class App: self.args.files = self.split_argument(self.args.files) self.args.searchdirs = self.split_argument(self.args.searchdirs) self.args.includedirs = self.split_argument(self.args.includedirs) + self.args.blacklist = self.split_argument(self.args.blacklist) + + # Ignore directories from outside the sourcetree by default: + if not self.args.no_ignore_externals: + self.args.blacklist += [dir for dir in self.args.searchdirs if os.path.commonprefix([dir, self.args.sourcedir]) != self.args.sourcedir] + + if self.args.verbose: + self.logger.start('Settings:') - self.logger.step('Database file: {}'.format(self.args.database)) - self.logger.step('Extensions: ' + ', '.join(self.args.extensions)) - self.logger.step('Exclude: ' + ', '.join(self.args.exclude)) - self.logger.step('Compile options: ' + ' '.join(self.args.compile_options)) - self.logger.step('Template file: ' + self.args.code_template_file) - self.logger.step('Output directory: ' + self.args.output_dir) + self.logger.step('Source directory: {}'.format(self.args.sourcedir)) + self.logger.step('Libclang binary: {}'.format(libclang_binary)) + self.logger.step('Database file: {}'.format(self.args.database)) + self.logger.step('Extensions: ' + ', '.join(self.args.extensions)) + self.logger.step('Exclude: ' + ', '.join(self.args.exclude)) + self.logger.step('Blacklist: ' + ', '.join(self.args.blacklist)) + self.logger.step('Compile options: ' + ' '.join(self.args.compile_options)) + self.logger.step('Template file: ' + self.args.code_template_file) + self.logger.step('Output directory: ' + self.args.output_dir) - self.logger = Logger(Fore.YELLOW) if self.args.searchdirs: self.logger.start('Scanning search directories:') @@ -195,10 +207,11 @@ class App: self.args.files.sort() - self.logger.start('Extra include directories:') + if self.args.verbose: + self.logger.start('Extra include directories:') - for dir in self.args.includedirs: - self.logger.step(dir) + for dir in self.args.includedirs: + self.logger.step(dir) includes = ['-I{}'.format(os.path.abspath(i)) for i in (self.args.searchdirs + self.args.includedirs)] includes.append('-I' + os.path.abspath(self.args.sourcedir)) @@ -213,7 +226,8 @@ class App: self.args.sourcedir, self.args.files, self.args.database, self.args.output_dir, self.args.ignore_database, self.args.ast_dump, - self.args.code_template_file + self.args.code_template_file, + self.args.verbose ) def run(self): diff --git a/src/reflection/parser/drlparser.cmake b/src/reflection/parser/drlparser.cmake index ae2e1f7..30359fa 100644 --- a/src/reflection/parser/drlparser.cmake +++ b/src/reflection/parser/drlparser.cmake @@ -1,33 +1,59 @@ include(libclang) include(pip) +include(utils) find_package(PythonInterp 2.7 REQUIRED) -set(DRLPARSER_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/DRLParser) -set(DRLPARSER_CODEGEN_TEMPLATE ${CMAKE_CURRENT_LIST_DIR}/templates/reflection_template.hpp) -set(OUTPUT_DIR ${CMAKE_BINARY_DIR}/ouput/reflection) -set(INCLUDE_OUTPUT_DIR ${CMAKE_BINARY_DIR}/ouput/) +macro(drlparser_setup) + set(DRLPARSER_SCRIPT "${SIPLASPLAS_DRLPARSER_DIR}/DRLParser") + set(DRLPARSER_CODEGEN_TEMPLATE "${SIPLASPLAS_DRLPARSER_DIR}/templates/reflection_template.hpp") -if(SIPLASPLAS_INSTALL_DRLPARSER_DEPENDENCIES) - pip_install_requirements("${CMAKE_SOURCE_DIR}/src/reflection/parser") - pip_package_version(clang libclang_bindings_version) + if(NOT SIPLASPLAS_REFLECTION_OUTPUT_DIR) + set(SIPLASPLAS_REFLECTION_OUTPUT_DIR "${CMAKE_BINARY_DIR}/output") + endif() + if(NOT SIPLASPLAS_REFLECTION_OUTPUT_INCLUDE_PREFIX) + set(SIPLASPLAS_REFLECTION_OUTPUT_INCLUDE_PREFIX "reflection") + endif() + set(DSIPLASPLAS_REFLECTION_OUTPUT_DIR_FULLPATH "${SIPLASPLAS_REFLECTION_OUTPUT_DIR}/${SIPLASPLAS_REFLECTION_OUTPUT_INCLUDE_PREFIX}") + + if(NOT EXISTS "${DRLPARSER_SCRIPT}") + message(FATAL_ERROR "No DRLParser script found in ${SIPLASPLAS_DRLPARSER_DIR}") + endif() - if(libclang_bindings_version) - # Note that LLVM releases libclang bindings for minor releases only - # that's why the clang packages are tagged 3.x and we compare against - # SIPLASPLAS_LIBCLANG_VERSION_MAJOR_MINOR instead of SIPLASPLAS_LIBCLANG_VERSION + if(SIPLASPLAS_INSTALL_DRLPARSER_DEPENDENCIES AND NOT __SIPLASPLAS_DRLPARSER_DEPS_SATISFIED) + pip_install_requirements("${SIPLASPLAS_DRLPARSER_DIR}") + pip_package_version(clang libclang_bindings_version) - if(NOT libclang_bindings_version VERSION_EQUAL SIPLASPLAS_LIBCLANG_VERSION_MAJOR_MINOR) - message(FATAL_ERROR "libclang python bindings (clang==${libclang_bindings_version}) do not match required libclang version (${SIPLASPLAS_LIBCLANG_VERSION})") + if(libclang_bindings_version) + # Note that LLVM releases libclang bindings for minor releases only + # that's why the clang packages are tagged 3.x and we compare against + # SIPLASPLAS_LIBCLANG_VERSION_MAJOR_MINOR instead of SIPLASPLAS_LIBCLANG_VERSION + + if(NOT libclang_bindings_version VERSION_EQUAL SIPLASPLAS_LIBCLANG_VERSION_MAJOR_MINOR) + message(FATAL_ERROR "libclang python bindings (clang==${libclang_bindings_version}) do not match required libclang version (${SIPLASPLAS_LIBCLANG_VERSION})") + else() + message(STATUS "libclang python bindings found") + endif() + else() + message(STATUS "Python bindings (package \"clang\") not found. Installing...") + + pip_install_package(clang ${SIPLASPLAS_LIBCLANG_VERSION_MAJOR_MINOR}) endif() - else() - message(STATUS "Python bindings (package \"clang\") not found. Installing...") - pip_install_package(clang ${SIPLASPLAS_LIBCLANG_VERSION_MAJOR_MINOR}) + set(__SIPLASPLAS_DRLPARSER_DEPS_SATISFIED TRUE CACHE INTERNAL "") endif() -endif() +endmacro() function(configure_siplasplas_reflection TARGET) + drlparser_setup() + + cmake_parse_arguments(DRLPARSER + "" + "" + "EXCLUDE;BLACKLIST" + ${ARGN} + ) + function(log MESSAGE) if(SIPLASPLAS_VERBOSE_CONFIG) message(STATUS "[REFLECTION LOG] ${MESSAGE}") @@ -36,6 +62,8 @@ function(configure_siplasplas_reflection TARGET) if(NOT (TARGET ${TARGET})) message(FATA_ERROR "Target ${TARGET} not found!") + else() + log("Configuring siplasplas reflection for target '${TARGET}'") endif() get_target_property(SOURCES ${TARGET} SOURCES) @@ -66,7 +94,13 @@ function(configure_siplasplas_reflection TARGET) endif() target_include_directories(${TARGET} - PUBLIC ${INCLUDE_OUTPUT_DIR} + PUBLIC "${SIPLASPLAS_REFLECTION_OUTPUT_DIR}" + PUBLIC "${SIPLASPLAS_INCLUDE_DIR}" + ) + target_compile_definitions(${TARGET} PUBLIC + -DSIPLASPLAS_REFLECTION_OUTPUT_DIR="${SIPLASPLAS_REFLECTION_OUTPUT_DIR}" + -DSIPLASPLAS_REFLECTION_OUTPUT_INCLUDE_PREFIX="${SIPLASPLAS_REFLECTION_OUTPUT_INCLUDE_PREFIX}" + -DSIPLASPLAS_REFLECTION_OUTPUT_DIR_FULLPATH="${DSIPLASPLAS_REFLECTION_OUTPUT_DIR_FULLPATH}" ) log("Processing target ${TARGET}:") @@ -75,6 +109,7 @@ function(configure_siplasplas_reflection TARGET) string(REGEX REPLACE ";" "," INCLUDE_DIRS "${INCLUDE_DIRS}") set(includes ${INCLUDE_DIRS} ${EXTRA_LIBCLANG_INCLUDES}) + list(REMOVE_DUPLICATES includes) string(REGEX REPLACE ";" "," includes "${includes}") set(includedirs --includedirs "\"${includes}\"") @@ -103,6 +138,15 @@ function(configure_siplasplas_reflection TARGET) set(astdump --ast-dump) endif() + if(DRLPARSER_EXCLUDE) + string(REGEX REPLACE ";" "," exclude_globs "${DRLPARSER_EXCLUDE}") + set(exclude --exclude "\"${exclude_globs}\"") + endif() + + list(APPEND DRLPARSER_BLACKLIST "${CMAKE_BINARY_DIR}") + string(REGEX REPLACE ";" "," blacklist_dirs "${DRLPARSER_BLACKLIST}") + set(blacklist --blacklist "\"${blacklist_dirs}\"") + string(REGEX REPLACE ";" "," COMPILE_OPTIONS "${COMPILE_OPTIONS}") log("libclang compile options: ${COMPILE_OPTIONS}") @@ -111,8 +155,9 @@ function(configure_siplasplas_reflection TARGET) --searchdirs "\"${INCLUDE_DIRS}\"" ${includedirs} -s ${CMAKE_SOURCE_DIR} - -o ${OUTPUT_DIR} - --blacklist "${CMAKE_BINARY_DIR}" + -o "${DSIPLASPLAS_REFLECTION_OUTPUT_DIR_FULLPATH}" + ${exclude} + ${blacklist} ${database} ${libclang} ${ignore_database} @@ -121,11 +166,15 @@ function(configure_siplasplas_reflection TARGET) --code-template-file ${DRLPARSER_CODEGEN_TEMPLATE} ) + set(command ${DRLPARSER_SCRIPT} ${options}) + log("DRLParser command: ${command}") + add_prebuild_command( NAME ${TARGET}_drlparser TARGET ${TARGET} - COMMAND ${PYTHON_EXECUTABLE} ${DRLPARSER_SCRIPT} - ${options} + COMMAND ${command} VERBATIM + WORKING_DIRECTORY "${SIPLASPLAS_DRLPARSER_DIR}" + COMMENT "Running siplasplas reflection parser for ${TARGET}" ) endfunction() diff --git a/src/reflection/parser/templates/reflection_template.hpp b/src/reflection/parser/templates/reflection_template.hpp index 18b1cfa..ac00d26 100644 --- a/src/reflection/parser/templates/reflection_template.hpp +++ b/src/reflection/parser/templates/reflection_template.hpp @@ -1,8 +1,7 @@ #ifndef SIPLASPLAS_REFLECTION_OUTPUT_FILE_{{hash}}_HPP #define SIPLASPLAS_REFLECTION_OUTPUT_FILE_{{hash}}_HPP -#include -#include +#include #include #include diff --git a/src/reflection/parser/translationunitprocessor.py b/src/reflection/parser/translationunitprocessor.py index af68cea..61e978d 100644 --- a/src/reflection/parser/translationunitprocessor.py +++ b/src/reflection/parser/translationunitprocessor.py @@ -1,5 +1,6 @@ import clang.cindex import asciitree +import os from utility.logger import GlobalLogger from ast.translationunit import TranslationUnit @@ -24,7 +25,7 @@ def __init__(self, filepath, args, jinjaTemplate, logger, print_ast = False): self.classes = [] self.root = None - def process(self): + def process(self, verbose = False): """ Process the translation unit Generates an ast.TranslationUnit instance with all the @@ -33,14 +34,17 @@ def process(self): (See runJinja() method below) """ - self.logger.info('Parsing file...') + if verbose: + self.logger.info('Parsing file: {} {} ...'.format( os.path.basename(self.filePath), ' '.join(self.compileArgs))) self.clang_tu = clang.cindex.Index.create().parse(self.filePath, args = self.compileArgs) - for d in self.clang_tu.diagnostics: - GlobalLogger.error().step('Line {} (severity {}): {}'.format(d.location.line, d.severity, d.spelling)) + if verbose: + for d in self.clang_tu.diagnostics: + GlobalLogger.error().step('Line {} (severity {}): {}'.format(d.location.line, d.severity, d.spelling)) - self.logger.info('Processing AST...') + if verbose: + self.logger.info('Processing AST...') self.translation_unit = TranslationUnit(self.clang_tu.cursor, self.filePath) @@ -48,9 +52,11 @@ def process(self): # it gives an iterable on the translation unit AST self.root = self.translation_unit.root - # Print the processed AST and the full AST given by libclang. + # Print the processed AST and the full AST given by libclang if self.print_ast: - self.logger.info('Dumping AST to {}...'.format(self.ast_file_path)) + if verbose: + self.logger.info('Dumping AST to {}...'.format(self.ast_file_path)) + with open(self.ast_file_path, 'w') as ast_file: import asciitree @@ -73,13 +79,14 @@ def dispose(self): self.root = None - def run_jinja(self, outputfile): + def run_jinja(self, outputfile, verbose = False): """ Generate reflection code for the translation unit""" if self.jinjaTemplate: import hashlib - self.logger.info('Generating file...') + if verbose: + self.logger.info('Generating file...') with open(outputfile, 'w') as outputFile: outputFile.write(self.jinjaTemplate.render(global_namespace = self.translation_unit.root, hash = hashlib.md5(outputfile.encode()).hexdigest()))