diff --git a/cmake/findDependencies.cmake b/cmake/findDependencies.cmake index 9640e2374..389671848 100644 --- a/cmake/findDependencies.cmake +++ b/cmake/findDependencies.cmake @@ -8,3 +8,12 @@ endif() set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC OFF) + +if (NOT ${USE_MATCHCOMPILER_OPT} STREQUAL "Off") + find_package(PythonInterp) + if (NOT ${PYTHONINTERP_FOUND}) + message(WARNING "No python interpreter found. Therefore, the match compiler is switched off.") + set(USE_MATCHCOMPILER_OPT "Off") + endif() +endif() + diff --git a/cmake/options.cmake b/cmake/options.cmake index 96fd02ce2..400b01c08 100644 --- a/cmake/options.cmake +++ b/cmake/options.cmake @@ -23,6 +23,18 @@ option(ANALYZE_DATAFLOW "Clang dynamic analyzer: general dynamic dataflow an option(WARNINGS_ARE_ERRORS "Treat warnings as errors" OFF) option(WARNINGS_ANSI_ISO "Issue all the mandatory diagnostics Listed in C standard" ON) +set(USE_MATCHCOMPILER "Auto" CACHE STRING "Usage of match compliler") +set_property(CACHE USE_MATCHCOMPILER PROPERTY STRINGS Auto Off On Verify) +if (USE_MATCHCOMPILER STREQUAL "Auto") + if (CMAKE_BUILD_TYPE STREQUAL "Release") + set(USE_MATCHCOMPILER_OPT "On") + else() + set(USE_MATCHCOMPILER_OPT "Off") + endif() +else() + set(USE_MATCHCOMPILER_OPT ${USE_MATCHCOMPILER}) +endif() + option(BUILD_SHARED_LIBS "Build shared libraries" ON) option(BUILD_TESTS "Build tests" OFF) option(BUILD_GUI "Build the qt application" OFF) diff --git a/cmake/printInfo.cmake b/cmake/printInfo.cmake index 309e60cc5..7f1fb5b96 100644 --- a/cmake/printInfo.cmake +++ b/cmake/printInfo.cmake @@ -23,6 +23,9 @@ message( STATUS "ANALYZE_DATAFLOW = ${ANALYZE_DATAFLOW}" ) message( STATUS "WARNINGS_ANSI_ISO = ${WARNINGS_ANSI_ISO}" ) message( STATUS "WARNINGS_ARE_ERRORS = ${WARNINGS_ARE_ERRORS}" ) message( STATUS ) +message( STATUS "USE_MATCHCOMPILER = ${USE_MATCHCOMPILER}" ) +message( STATUS "USE_MATCHCOMPILER_OPT = ${USE_MATCHCOMPILER_OPT}" ) +message( STATUS ) message( STATUS "BUILD_SHARED_LIBS = ${BUILD_SHARED_LIBS}" ) message( STATUS "BUILD_TESTS = ${BUILD_TESTS}" ) message( STATUS "BUILD_GUI = ${BUILD_GUI}" ) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 9f187bf4a..b6275b22a 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -3,7 +3,38 @@ include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/externals/tinyxml/) file(GLOB_RECURSE hdrs "*.h") file(GLOB_RECURSE srcs "*.cpp") -add_library(${PROJECT_NAME} ${srcs} ${hdrs}) +function(build_src output filename) + get_filename_component(file ${filename} NAME) + set(outfile ${CMAKE_CURRENT_BINARY_DIR}/build/mc_${file}) + set(${output} ${${output}} ${outfile} PARENT_SCOPE) + if (${USE_MATCHCOMPILER} STREQUAL "Verify") + set(verify_option "--verify") + endif() + add_custom_command( + OUTPUT ${outfile} + COMMAND ${PYTHON_EXECUTABLE} "${PROJECT_SOURCE_DIR}/tools/matchcompiler.py" + --read-dir="${CMAKE_CURRENT_SOURCE_DIR}" + --prefix="mc_" + --line + ${verify_option} + ${file} + DEPENDS ${file} + DEPENDS ${PROJECT_SOURCE_DIR}/tools/matchcompiler.py + ) + set_source_files_properties(${outfile} PROPERTIES GENERATED TRUE) +endfunction() + +foreach(file ${srcs}) + build_src(srcs_build ${file}) +endforeach() + +if (NOT ${USE_MATCHCOMPILER_OPT} STREQUAL "Off") + set(srcs_lib ${srcs_build}) +else() + set(srcs_lib ${srcs}) +endif() + +add_library(${PROJECT_NAME} ${srcs_lib} ${hdrs}) if (HAVE_RULES) target_link_libraries(${PROJECT_NAME} pcre) diff --git a/tools/matchcompiler.py b/tools/matchcompiler.py index 648674a36..4f596beda 100755 --- a/tools/matchcompiler.py +++ b/tools/matchcompiler.py @@ -599,7 +599,7 @@ class MatchCompiler: line = line.replace('MatchCompiler::makeConstStringEnd', '")') return line - def convertFile(self, srcname, destname): + def convertFile(self, srcname, destname, line_directive): self._reset() fin = open(srcname, "rt") @@ -631,25 +631,17 @@ class MatchCompiler: for function in self._rawMatchFunctions: strFunctions += function + lineno = '' + if line_directive: + lineno = '#line 1 "' + srcname + '"\n' + fout = open(destname, 'wt') - fout.write(header + strFunctions + code) + fout.write(header + strFunctions + lineno + code) fout.close() def main(): # Main program - build_dir = 'build' - - # Check if we are invoked from the right place - if not os.path.exists('lib') and not os.path.exists('samples'): - print('Please invoke from the top level cppcheck source dir. Example: tools/matchcompiler.py') - sys.exit(-1) - - # Create build directory if needed - if not os.path.exists(build_dir): - os.makedirs(build_dir) - if not os.path.isdir(build_dir): - raise Exception(build_dir + ' is not a directory') # Argument handling parser = argparse.ArgumentParser( @@ -658,15 +650,49 @@ def main(): help='verify compiled matches against on-the-fly parser. Slow!') parser.add_argument('--show-skipped', action='store_true', default=False, help='show skipped (non-static) patterns') + parser.add_argument('--read-dir', default="lib", + help='directory from which files are read') + parser.add_argument('--write-dir', default="build", + help='directory into which files are written') + parser.add_argument('--prefix', default="", + help='prefix for build files') + parser.add_argument('--line', action='store_true', default=False, + help='add line directive to input files into build files') + parser.add_argument('file', nargs='*', + help='file to complile') args = parser.parse_args() + lib_dir = args.read_dir + build_dir = args.write_dir + line_directive = args.line + files = args.file + + # Check if we are invoked from the right place + if not os.path.exists(lib_dir): + print('Directory "' + lib_dir + '"not found.') + sys.exit(-1) + + # Create build directory if needed + if not os.path.exists(build_dir): + os.makedirs(build_dir) + if not os.path.isdir(build_dir): + raise Exception(build_dir + ' is not a directory') mc = MatchCompiler(verify_mode=args.verify, show_skipped=args.show_skipped) - # convert all lib/*.cpp files - for f in glob.glob('lib/*.cpp'): - print(f + ' => ' + build_dir + '/' + f[4:]) - mc.convertFile(f, build_dir + '/' + f[4:]) + if not files: + # select all *.cpp files in lib_dir + for f in glob.glob(lib_dir + '/*.cpp'): + files.append(f[len(lib_dir)+1:]) + + # convert files + for fi in files: + pi = lib_dir + '/' + fi + fo = args.prefix + fi + po = build_dir + '/' + fo + print(pi + ' => ' + po) + mc.convertFile(pi, po, line_directive) if __name__ == '__main__': main() +