Hello community, here is the log from the commit of package Bear for openSUSE:Factory checked in at 2019-09-27 14:54:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/Bear (Old) and /work/SRC/openSUSE:Factory/.Bear.new.2352 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "Bear" Fri Sep 27 14:54:30 2019 rev:3 rq:733664 version:2.4.2 Changes: -------- --- /work/SRC/openSUSE:Factory/Bear/Bear.changes 2018-11-26 10:28:17.109170227 +0100 +++ /work/SRC/openSUSE:Factory/.Bear.new.2352/Bear.changes 2019-09-27 14:55:23.003682771 +0200 @@ -1,0 +2,36 @@ +Fri Sep 27 11:09:06 UTC 2019 - Martin Pluskal <mplus...@suse.com> + +- Small package modernization + +------------------------------------------------------------------- +Fri Sep 27 11:04:35 UTC 2019 - Dan Čermák <dcer...@suse.com> + +- Fix sed call to fixup bear's shebang + +------------------------------------------------------------------- +Fri Sep 20 21:40:12 UTC 2019 - Dan Čermák <dcer...@suse.com> + +- Packaging changes: + - Drop unnecessary BuildRequires libconfig-devel and pkgconfig + - Drop Bear-rpmlintrc: it contains a no longer required filter + - Run the testsuite in %check + - Add bash completion files + - Use python3 as the interpreter for /usr/bin/bear + +- Update to 2.4.2 + Features: + - Support output field in the output. (#254, @bofeng17) + - Support Fortran compiler (#201, #241, #253, @rubyzhou2014, @chunhualiao) + - Support filter options (#261, #252, @liugang) + + Bugfixes: + - Fix Cpack problem to create RPM. (#191, @antmak, @reverendhomer) + +- Update to 2.4.1 + - Minor bug fixes. + +- Update to 2.4.0 + - Improve reliability by replacing flaky character conversion code in critical + execution path. + +------------------------------------------------------------------- Old: ---- 2.3.13.tar.gz Bear-rpmlintrc New: ---- 2.4.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ Bear.spec ++++++ --- /var/tmp/diff_new_pack.emGloI/_old 2019-09-27 14:55:25.443676426 +0200 +++ /var/tmp/diff_new_pack.emGloI/_new 2019-09-27 14:55:25.451676405 +0200 @@ -1,7 +1,7 @@ # # spec file for package Bear # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,18 +16,28 @@ # +# Tests are resolvable only on Tumbleweed +%if 0%{?suse_version} > 1500 +%bcond_without tests +%else +%bcond_with tests +%endif Name: Bear -Version: 2.3.13 +Version: 2.4.2 Release: 0 Summary: Tool to generate compilation database for clang tooling License: GPL-3.0-or-later Group: Development/Tools/Other URL: https://github.com/rizsotto/Bear -Source: https://github.com/rizsotto/Bear/archive/%{version}.tar.gz -Source2: %{name}-rpmlintrc +Source: %{URL}/archive/%{version}.tar.gz +BuildRequires: bash-completion BuildRequires: cmake -BuildRequires: libconfig-devel -BuildRequires: pkgconfig +%if %{with tests} +BuildRequires: clang +BuildRequires: gcc-c++ +BuildRequires: python3-lit +BuildRequires: python3-setuptools +%endif %description Bear is a tool to generate compilation database for clang tooling. @@ -37,22 +47,30 @@ file. Bear is a tool to generate such file during the build process. %prep -%setup -q +%autosetup %build %cmake \ -DCMAKE_INSTALL_LIBDIR:PATH=%{_lib} -%make_jobs +%cmake_build %install %cmake_install -sed -i "s|env python|python2|g" %{buildroot}%{_bindir}/bear +sed -i "s|env python.*$|python3|g" %{buildroot}%{_bindir}/bear rm -rf %{buildroot}%{_datadir}/doc/bear +%if %{with tests} +%check +pushd build +make check +popd +%endif + %files %license COPYING %doc ChangeLog.md README.md %{_bindir}/bear +%{_datadir}/bash-completion/completions/bear %{_mandir}/man1/bear.1%{?ext_man} %dir %{_libdir}/bear %{_libdir}/bear/libear.so ++++++ 2.3.13.tar.gz -> 2.4.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/.gitignore new/Bear-2.4.2/.gitignore --- old/Bear-2.3.13/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/Bear-2.4.2/.gitignore 2019-08-29 13:32:53.000000000 +0200 @@ -0,0 +1,6 @@ +.idea/ +cmake-build*/ +Output/ +Cargo.lock +target/ +.DS_Store diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/.travis.yml new/Bear-2.4.2/.travis.yml --- old/Bear-2.3.13/.travis.yml 2018-08-30 13:27:52.000000000 +0200 +++ new/Bear-2.4.2/.travis.yml 2019-08-29 13:32:53.000000000 +0200 @@ -4,20 +4,20 @@ include: - os: linux sudo: false - dist: trusty + dist: xenial python: "pypy" - os: linux sudo: required - dist: trusty + dist: xenial python: 2.7 - os: linux sudo: false - dist: trusty - python: 3.5 + dist: xenial + python: 3.6 - os: linux sudo: false - dist: trusty - python: 3.6 + dist: xenial + python: 3.7 - os: osx osx_image: xcode7.3 language: generic @@ -30,6 +30,7 @@ packages: - cmake - scons + - gfortran - qt4-qmake before_install: @@ -37,7 +38,7 @@ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then csrutil status || true; brew update; - brew install scons qt; + brew install scons; fi install: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/CMakeLists.txt new/Bear-2.4.2/CMakeLists.txt --- old/Bear-2.3.13/CMakeLists.txt 2018-08-30 13:27:52.000000000 +0200 +++ new/Bear-2.4.2/CMakeLists.txt 2019-08-29 13:32:53.000000000 +0200 @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.8) project(bear C) -set(BEAR_VERSION "2.3.13") +set(BEAR_VERSION "2.4.2") include(GNUInstallDirs) install(FILES COPYING README.md ChangeLog.md @@ -30,6 +30,7 @@ add_subdirectory(bear) add_subdirectory(test) add_subdirectory(man) +add_subdirectory(shell-completion) set(CPACK_PACKAGE_NAME "bear") set(CPACK_PACKAGE_CONTACT "László Nagy") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/ChangeLog.md new/Bear-2.4.2/ChangeLog.md --- old/Bear-2.3.13/ChangeLog.md 2018-08-30 13:27:52.000000000 +0200 +++ new/Bear-2.4.2/ChangeLog.md 2019-08-29 13:32:53.000000000 +0200 @@ -1,3 +1,35 @@ +## 2.4.2 (2019.08.29) + +Features: + - Support `output` field in the output. (#254, @bofeng17) + - Support Fortran compiler (#201, #241, #253, @rubyzhou2014, @chunhualiao) + - Support filter options (#261, #252, @liugang) + +Bugfixes: + - Fix Cpack problem to create RPM. (#191, @antmak, @reverendhomer) + + +## 2.4.1 (2019.07.30) + +Features: + - Add bash completion (#231, @1ace) + +Bugfixes: + - Fix limitation section in readme (#256, @Manouchehri) + - Fix preprocessor flags (#239, @bdemick) + + +## 2.4.0 (2019.05.12) + +Features: + - `libear.so` write binary file instead of JSON. + +Bugfixes: + - Fix `newlocale` problem (#182, #190, @timblaktu, @3v1n0, @caohaiming, @rbresalier) + - Fix long command line problem (#246, @jmodares) + - Fix help text for parameter `--use-only` (#245, @koutheir) + + ## 2.3.13 (2018.08.30) Bugfixes: @@ -17,7 +49,7 @@ Bugfixes: - Fix CPack RPM problems on CentOS7 (@antmak, #191, #192) - - Change libear.so location to $LIBDIR/bear to avoid direct linking. (@morxa, #189) + - Change `libear.so` location to `$LIBDIR/bear` to avoid direct linking. (@morxa, #189) ## 2.3.10 (2017.12.07) @@ -87,7 +119,7 @@ ## 2.3.0 (2017.04.20) Features: - - Rewrite functional test on lit. + - Rewrite functional test on LLVM `lit`. - Write intermediate execution report in JSON format. - Write compilation database with "arguments" instead of "command". - Write compilation database with relative paths. @@ -165,14 +197,14 @@ Bugfixes: - - Fix crash when make with -j option (@minhyuk, #87) + - Fix crash when `make -j` runs parallel (@minhyuk, #87) ## 2.0.3 (2015-04-04) Bugfixes: - - Fix passing of arguments to mkdtemp (@kljohann, #75) + - Fix passing of arguments to `mkdtemp` (@kljohann, #75) - Empty output when compiler used to link. (@QuaziRandom, #80) - Bad escape of strings in compilation database. (@jumapico, #81) @@ -242,7 +274,7 @@ - fix typo in the README.md (#48, @breser) - fix typo in the man page (#49, @sebastinas) - - fix cmake file to honor given CFLAGS (#50, @sebastinas) + - fix cmake file to honor given `CFLAGS` (#50, @sebastinas) - fix execle causes segfault on 32 bit systems (#51, #52, @breser, @sebastinas) @@ -259,7 +291,7 @@ - fix non filtered output option renamed from debug (#44, @mikemccracken) - fix broken build on OS X (#46, @breser) - fix documentation (@mlq) - - fix posix_spawn* call not implemented (#43, @agentsim, @apoluektov) + - fix `posix_spawn*` call not implemented (#43, @agentsim, @apoluektov) ## 1.2 (2013-10-01) @@ -297,7 +329,7 @@ Bugfixes: - fix process synchronization problem (#33, @blowback) - - fix malloc/realloc usage (#34, @mlq) + - fix `malloc`, `realloc` usage (#34, @mlq) ## 0.5 (2013-06-09) @@ -322,7 +354,7 @@ Bugfixes: - - fix json output on whitespaces (#19) + - fix JSON output on whitespaces (#19) - fix socket reading problem (#20, @brucestephens) - improved signal handling (#21) - build system checks for available `exec` functions (#22) @@ -354,7 +386,7 @@ - test added: unit test, end-to-end test and full `exec` family coverage (#4) - `scons` does pass empty environment to child processes (#9) - fix `execle` overriding bug (#13) - - fix json output (#14) + - fix JSON output (#14) ## 0.1 (2012-11-17) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/README.md new/Bear-2.4.2/README.md --- old/Bear-2.3.13/README.md 2018-08-30 13:27:52.000000000 +0200 +++ new/Bear-2.4.2/README.md 2019-08-29 13:32:53.000000000 +0200 @@ -1,5 +1,12 @@ -Build EAR -========= +[![Packaging status](https://repology.org/badge/tiny-repos/bear.svg)](https://repology.org/project/bear/versions) +[![GitHub release](https://img.shields.io/github/release/rizsotto/Bear)](https://github.com/rizsotto/Bear/releases) +[![GitHub Release Date](https://img.shields.io/github/release-date/rizsotto/Bear)](https://github.com/rizsotto/Bear/releases) +[![Build status](https://api.travis-ci.org/rizsotto/bear.svg?branch=master)](https://travis-ci.org/rizsotto/bear/branches) +[![Contributors](https://img.shields.io/github/contributors/rizsotto/Bear)](https://github.com/rizsotto/Bear/graphs/contributors) +[![Gitter](https://img.shields.io/gitter/room/rizsotto/Bear)](https://gitter.im/rizsotto/Bear) + +Build EAR (BEAR) +================ Bear is a tool that generates a compilation database for clang tooling. @@ -9,7 +16,7 @@ programs. One way to get a compilation database is to use `cmake` as the build -tool. Passing `-DCMAKE_EXPORT_COMPILE_COMMANDS=ON` to cmake generates +tool. Passing `-DCMAKE_EXPORT_COMPILE_COMMANDS=ON` to cmake generates the `compile_commands.json` file into the current directory. For non-cmake projects, Bear generates the JSON file during the build process. @@ -27,6 +34,13 @@ [JSONCDB]: http://clang.llvm.org/docs/JSONCompilationDatabase.html +How to install +-------------- + +Bear is packaged for many distributions. Check out your package manager. +Or build it from source. + + How to build ------------ @@ -37,7 +51,7 @@ 1. an ANSI **C compiler**, to compile the sources. 2. **cmake**, to configure the build process. -3. **make**, to run the build. The makefiles are generated by `cmake`. +3. **make**, to run the build. The makefiles are generated by `cmake`. 4. **python** is a runtime dependency. The `bear` command is written in Python. (version >= 2.7) 5. **lit** is an optional dependency to run the functional tests @@ -61,12 +75,12 @@ bear <your-build-command> -The output file called `compile_commands.json` found in current directory. +The output file called `compile_commands.json` is saved in the current directory. For more options you can check the man page or pass `--help` parameter. Side note: Since `bear` is executing the build command only those commands -will be recorded which were actually executed. Which means if you were already +will be recorded which were actually executed. Which means if you have already built your project and you re-run the build command with Bear you probably end up to have an empty output. (Practically it means you need to run `make clean` before you run `bear make`.) @@ -92,7 +106,7 @@ work, Bear will intercept compiler calls for 32-bit and 64-bit applications. For Linux, a small tune is needed at build time. Need to compile `libear.so` -libray for 32-bit and for 64-bit too. Then install these libraries to the OS +library for 32-bit and for 64-bit too. Then install these libraries to the OS preferred multilib directories. And replace the `libear.so` path default value with a single path, which matches both. (The match can be achieved by the `$LIB` token expansion from the dynamic loader. See `man ld.so` for more.) @@ -113,10 +127,10 @@ PATH=/opt/bear/bin:$PATH lit -v test PATH=/opt/bear/bin:$PATH lit -v test -DMULTILIB=true -### Empty compilation database on OS X Captain or Fedora +### Empty compilation database on OS X / macOS or Fedora Security extension/modes on different operating systems might disable library -preloads. This case Bear behaves normally, but the result compilation database +preloads. In this case Bear behaves normally, but the result compilation database will be empty. (Please make sure it's not the case when reporting bugs.) Notable examples for enabled security modes are: OS X 10.11 (check with `csrutil status | grep 'System Integrity Protection'`), and Fedora, CentOS, RHEL @@ -158,4 +172,7 @@ have a suggestion how to fix it, include that as well. Patches are also welcome. +Please follow the [contribution guide][GUIDE] when you do this. + [ISSUES]: https://github.com/rizsotto/Bear/issues + [GUIDE]: https://github.com/rizsotto/Bear/blob/master/.github/CONTRIBUTING.md diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/bear/CMakeLists.txt new/Bear-2.4.2/bear/CMakeLists.txt --- old/Bear-2.3.13/bear/CMakeLists.txt 2018-08-30 13:27:52.000000000 +0200 +++ new/Bear-2.4.2/bear/CMakeLists.txt 2019-08-29 13:32:53.000000000 +0200 @@ -1,3 +1,10 @@ +include(FindPythonInterp) +if (PYTHONINTERP_FOUND) + set(BEAR_PYTHON_EXECUTABLE "python${PYTHON_VERSION_MAJOR}") +else() + message(FATAL_ERROR "Have not found python interpreter") +endif() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/main.py.in ${CMAKE_CURRENT_BINARY_DIR}/bear) include(GNUInstallDirs) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/bear/main.py.in new/Bear-2.4.2/bear/main.py.in --- old/Bear-2.3.13/bear/main.py.in 2018-08-30 13:27:52.000000000 +0200 +++ new/Bear-2.4.2/bear/main.py.in 2019-08-29 13:32:53.000000000 +0200 @@ -1,7 +1,7 @@ -#!/usr/bin/env python +#!/usr/bin/env @BEAR_PYTHON_EXECUTABLE@ # -*- coding: utf-8 -*- -# Copyright (C) 2012-2017 by László Nagy +# Copyright (C) 2012-2019 by László Nagy # This file is part of Bear. # # Bear is a tool to generate compilation database for clang tooling. @@ -47,6 +47,7 @@ import itertools import tempfile import shutil +import struct import contextlib import logging @@ -91,11 +92,13 @@ } # type: Dict[str, int] + # Known C/C++ compiler wrapper name patterns. COMPILER_PATTERN_WRAPPER = re.compile(r'^(distcc|ccache)$') # Known MPI compiler wrapper name patterns. -COMPILER_PATTERNS_MPI_WRAPPER = re.compile(r'^mpi(cc|cxx|CC|c\+\+)$') +COMPILER_PATTERNS_MPI_WRAPPER = re.compile( + r'^mpi(cc|cxx|CC|c\+\+|fort|f77|f90)$') # Known C compiler executable name patterns. COMPILER_PATTERNS_CC = ( @@ -114,47 +117,67 @@ re.compile(r'^(g|)xl(C|c\+\+)$'), ) +# Known Fortran compiler executable name patterns +# Gfortran, Intel Fortran Compilers, PGI compilers +COMPILER_PATTERNS_FORTRAN = ( + re.compile(r'^(f95)$'), + re.compile(r'^(gfortran)$'), + re.compile(r'^(ifort)$'), + re.compile(r'^(pg)(f77|f90|f95|fortran)$') +) + TRACE_FILE_PREFIX = 'execution.' # same as in ear.c -C_LANG, CPLUSPLUS_LANG, OTHER = range(3) +C_LANG, CPLUSPLUS_LANG, FORTRAN_LANG, OTHER = range(4) -Execution = collections.namedtuple('Execution', ['pid', 'cwd', 'cmd']) +Execution = collections.namedtuple('Execution', ['cwd', 'cmd']) CompilationCommand = collections.namedtuple( 'CompilationCommand', ['compiler', 'language', 'phase', 'flags', 'files', 'output']) -class Category: - - def __init__(self, only_use, c_compilers, cxx_compilers): +class Tools: + def __init__(self, only_use, c_compilers, cxx_compilers, + fortran_compilers): self.ignore = only_use self.c_compilers = [os.path.basename(cc) for cc in c_compilers] self.cxx_compilers = [os.path.basename(cc) for cc in cxx_compilers] + self.fortran_compilers = [ + os.path.basename(cc) for cc in fortran_compilers] - def is_wrapper(self, cmd): - # type: (Category, str) -> bool + @classmethod + def is_wrapper(cls, cmd): + # type: (Type[Tools], str) -> bool return True if COMPILER_PATTERN_WRAPPER.match(cmd) else False - def is_mpi_wrapper(self, cmd): - # type: (Category, str) -> bool + @classmethod + def is_mpi_wrapper(cls, cmd): + # type: (Type[Tools], str) -> bool return True if COMPILER_PATTERNS_MPI_WRAPPER.match(cmd) else False def is_c_compiler(self, cmd): - # type: (Category, str) -> bool - use_match = Category._is_sting_match(cmd, self.c_compilers) - pattern_match = Category._is_pattern_match(cmd, COMPILER_PATTERNS_CC) + # type: (Tools, str) -> bool + use_match = Tools._is_sting_match(cmd, self.c_compilers) + pattern_match = Tools._is_pattern_match(cmd, COMPILER_PATTERNS_CC) return use_match if self.ignore else (use_match or pattern_match) def is_cxx_compiler(self, cmd): - # type: (Category, str) -> bool - use_match = Category._is_sting_match(cmd, self.cxx_compilers) - pattern_match = Category._is_pattern_match(cmd, COMPILER_PATTERNS_CXX) + # type: (Tools, str) -> bool + use_match = Tools._is_sting_match(cmd, self.cxx_compilers) + pattern_match = Tools._is_pattern_match(cmd, COMPILER_PATTERNS_CXX) + return use_match if self.ignore else (use_match or pattern_match) + + def is_fortran_compiler(self, cmd): + # type: (Tools, str) -> bool + use_match = Tools._is_sting_match(cmd, self.fortran_compilers) + pattern_match = Tools._is_pattern_match( + cmd, COMPILER_PATTERNS_FORTRAN) return use_match if self.ignore else (use_match or pattern_match) @classmethod def _is_sting_match(cls, candidate, compilers): - # type (Type[Category], str, Iterable[str) -> bool + # type (Type[Tools], str, Iterable[str) -> bool return any((candidate == compiler) for compiler in compilers) @classmethod @@ -287,26 +310,27 @@ """ Entry point for 'intercept-build' command. """ args = parse_args_for_intercept_build() - category = Category(args.use_only, args.use_cc, args.use_cxx) - exit_code, current = capture(args, category) + tools = Tools(args.use_only, args.use_cc, + args.use_cxx, args.use_fortran) + exit_code, current = capture(args, tools) # To support incremental builds, it is desired to read elements from # an existing compilation database from a previous run. if args.append and os.path.isfile(args.cdb): - previous = CompilationDatabase.load(args.cdb, category) + previous = CompilationDatabase.load(args.cdb, tools) entries = iter(set(itertools.chain(previous, current))) - CompilationDatabase.save(args.cdb, entries) + CompilationDatabase.save(entries, args.cdb, args.field_output) else: - CompilationDatabase.save(args.cdb, current) + CompilationDatabase.save(current, args.cdb, args.field_output) return exit_code -def capture(args, category): +def capture(args, tools): """ Implementation of compilation database generation. :param args: the parsed and validated command line arguments - :param category: helper object to detect compiler + :param tools: helper object to detect compiler :return: the exit status of build process. """ with temporary_directory(prefix='intercept-') as tmp_dir: @@ -316,23 +340,67 @@ # read the intercepted exec calls calls = (parse_exec_trace(file) for file in exec_trace_files(tmp_dir)) safe_calls = (x for x in calls if x is not None) - current = compilations(safe_calls, category) + current = compilations(safe_calls, tools) + # filter out not desired entries + include_filter = include(args.include, args.exclude) + filtered = set(entry for entry in current if include_filter(entry)) + return exit_code, iter(filtered) + + +def include(includes, excludes): + # type: (str, str) -> Callable[[Compilation], bool] + """ Create a predicate to filter out Compilation entries. + + :param includes: list of directories to include. + :param excludes: list of directories to exclude. + :return: a predicate which returns true if the entry should be + in the final output based on the location of the source file. """ + + def make_absolute(directory): + # type: (str) -> str + """ Makes a path like object absolute (to the project root). """ + + if os.path.isabs(directory): + return directory + else: + return os.path.normpath(os.path.join(os.getcwd(), directory)) + + include_dirs = [make_absolute(directory) for directory in includes] + exclude_dirs = [make_absolute(directory) for directory in excludes] + + def include_filter(candidate): + # type: (Compilation) -> bool + """ The predicate which returns true if the compilation should + be included in the final output. """ + + def contains(container, directory): + # type: (str, str) -> bool + """ Returns true if the container contains the directory. """ + + return os.path.commonprefix([container, directory]) == container - return exit_code, iter(set(current)) + source = candidate.source + needed = True if len(include_dirs) == 0 else \ + any(contains(directory, source) for directory in include_dirs) + rejected = False if len(exclude_dirs) == 0 else not \ + all(not contains(directory, source) for directory in exclude_dirs) + return needed and not rejected + return include_filter -def compilations(exec_calls, category): - # type: (Iterable[Execution], Category) -> Iterable[Compilation] + +def compilations(exec_calls, tools): + # type: (Iterable[Execution], Tools) -> Iterable[Compilation] """ Needs to filter out commands which are not compiler calls. And those compiler calls shall be compilation (not pre-processing or linking) calls. Plus needs to find the source file name from the arguments. :param exec_calls: iterator of executions - :param category: helper object to detect compiler + :param tools: helper object to detect compiler :return: stream of formatted compilation database entries """ for call in exec_calls: - for compilation in Compilation.iter_from_execution(call, category): + for compilation in Compilation.iter_from_execution(call, tools): yield compilation @@ -364,7 +432,7 @@ def parse_exec_trace(filename): - # type: (str) -> Execution + # type: (str) -> Optional[Execution] """ Parse execution report file. Given filename points to a file which contains the basic report @@ -373,15 +441,33 @@ :param filename: path to an execution trace file to read from, :return: an Execution object. """ + def byte_to_int(byte): + return struct.unpack_from("=I", byte)[0] + + def parse_length(handler, expected_type): + type_bytes = handler.read(3) + if type_bytes != expected_type: + raise Exception("type not expected") + length_bytes = handler.read(4) + return byte_to_int(length_bytes) + + def parse_string(handler): + length = parse_length(handler, b'str') + value_bytes = handler.read(length) + return value_bytes.decode("utf-8") + + def parse_string_list(handler): + length = parse_length(handler, b'lst') + return [parse_string(handler) for _ in range(length)] + logging.debug('parse exec trace file: %s', filename) - with open(filename, 'r') as handler: + with open(filename, 'rb', buffering=0) as handler: try: - entry = json.load(handler) - return Execution(pid=entry['pid'], - cwd=entry['cwd'], - cmd=entry['cmd']) - except ValueError: - logging.warning('parse exec trace file: %s FAILED', filename) + return Execution(cwd=parse_string(handler), + cmd=parse_string_list(handler)) + except Exception as exception: + logging.warning('parse exec trace file: %s FAILED: %s', + filename, exception) return None @@ -436,6 +522,10 @@ default="compile_commands.json", help="""The JSON compilation database.""") parser.add_argument( + '--field-output', + action='store_true', + help="""Puts output field to entries if it founds.""") + parser.add_argument( '--use-cc', metavar='<path>', dest='use_cc', @@ -452,9 +542,32 @@ help="""Hint '%(prog)s' to classify the given program name as C++ compiler.""") parser.add_argument( + '--use-fortran', + metavar='<path>', + dest='use_fortran', + action='append', + default=['f95'], + help="""Hint '%(prog)s' to classify the given program name as Fortan + compiler.""") + parser.add_argument( '--use-only', action='store_true', - help="""The JSON compilation database.""") + help="""Only use compilers given to '--use-cc', '--use-c++' and + '--use-fortran'.""") + parser.add_argument( + '--include', + action='append', + default=[], + help="""Only include these directories or files to the output. + (Absolute or relative to current working directory.) + Use --exclude parameters to filter more entries out.""") + parser.add_argument( + '--exclude', + action='append', + default=[], + help="""Exclude these directories or files from the output. + (Absolute or relative to current working directory.) + The --include will not enable entries from these directories.""") advanced = parser.add_argument_group('advanced options') advanced.add_argument( @@ -506,46 +619,57 @@ return vars(self) - def as_db_entry(self): - # type: (Compilation) -> Dict[str, Any] + def as_db_entry(self, field_output): + # type: (Compilation, bool) -> Dict[str, Any] """ This method creates a compilation database entry. """ source = os.path.relpath(self.source, self.directory) - output = ['-o', self.output] if self.output else [] - return { - 'file': source, - 'arguments': - [self.compiler, self.phase] + self.flags + output + [source], - 'directory': self.directory - } + if self.output: + result = { + 'file': source, + 'arguments': + [self.compiler, self.phase] + self.flags + + ['-o', self.output] + [source], + 'directory': self.directory, + } + if field_output: + result.update({'output': self.output}) + return result + else: + return { + 'file': source, + 'arguments': + [self.compiler, self.phase] + self.flags + [source], + 'directory': self.directory + } @classmethod - def from_db_entry(cls, entry, category): + def from_db_entry(cls, entry, tools): # type: (Type[Compilation], Dict[str, str]) -> Iterable[Compilation] """ Parser method for compilation entry. From compilation database entry it creates the compilation object. - :param entry: the compilation database entry - :param category: helper object to detect compiler + :param entry: the compilation database entry + :param tools: helper object to detect compiler :return: stream of CompilationDbEntry objects """ command = shell_split(entry['command']) if 'command' in entry else \ entry['arguments'] - execution = Execution(cmd=command, cwd=entry['directory'], pid=0) - return cls.iter_from_execution(execution, category) + execution = Execution(cmd=command, cwd=entry['directory']) + return cls.iter_from_execution(execution, tools) @classmethod - def iter_from_execution(cls, execution, category): + def iter_from_execution(cls, execution, tools): """ Generator method for compilation entries. From a single compiler call it can generate zero or more entries. :param execution: executed command and working directory - :param category: helper object to detect compiler + :param tools: helper object to detect compiler :return: stream of CompilationDbEntry objects """ - candidate = cls._split_command(execution.cmd, category) + candidate = cls._split_command(execution.cmd, tools) for source in candidate.files if candidate else []: output = candidate.output[0] if candidate.output else None phase = candidate.phase[0] if candidate.phase else '-c' @@ -560,11 +684,11 @@ yield result @classmethod - def _split_compiler(cls, command, category): + def _split_compiler(cls, command, tools): """ A predicate to decide whether the command is a compiler call. - :param command: the command to classify - :param category: helper object to detect compiler + :param command: the command to classify + :param tools: helper object to detect compiler :return: None if the command is not a compilation, or a tuple (compiler, language, rest of the command) otherwise """ @@ -574,34 +698,36 @@ # 'wrapper' 'parameters' and # 'wrapper' 'compiler' 'parameters' are valid. # Additionally, a wrapper can wrap another wrapper. - if category.is_wrapper(executable): - result = cls._split_compiler(parameters, category) + if tools.is_wrapper(executable): + result = cls._split_compiler(parameters, tools) # Compiler wrapper without compiler is a 'C' compiler. return result if result else (command[0], C_LANG, parameters) # MPI compiler wrappers add extra parameters - elif category.is_mpi_wrapper(executable): + elif tools.is_mpi_wrapper(executable): # Pass the executable with full path to avoid pick different # executable from PATH. mpi_call = get_mpi_call(command[0]) # type: List[str] - return cls._split_compiler(mpi_call + parameters, category) + return cls._split_compiler(mpi_call + parameters, tools) # and 'compiler' 'parameters' is valid. - elif category.is_c_compiler(executable): + elif tools.is_c_compiler(executable): return command[0], C_LANG, parameters - elif category.is_cxx_compiler(executable): + elif tools.is_cxx_compiler(executable): return command[0], CPLUSPLUS_LANG, parameters + elif tools.is_fortran_compiler(executable): + return command[0], FORTRAN_LANG, parameters return None @classmethod - def _split_command(cls, command, category): + def _split_command(cls, command, tools): """ Returns a value when the command is a compilation, None otherwise. - :param command: the command to classify - :param category: helper object to detect compiler + :param command: the command to classify + :param tools: helper object to detect compiler :return: stream of CompilationCommand objects """ logging.debug('input was: %s', command) # quit right now, if the program was not a C/C++ compiler - compiler_and_arguments = cls._split_compiler(command, category) + compiler_and_arguments = cls._split_compiler(command, tools) if compiler_and_arguments is None: return None @@ -628,7 +754,7 @@ elif re.match(r'^-(l|L|Wl,).+', arg): pass # some parameters look like a filename, take those explicitly - elif arg in {'-D', '-I'}: + elif arg in {'-D', '-U', '-I', '-include'}: result.flags.extend([arg, next(args)]) # get the output file separately elif arg == '-o': @@ -648,29 +774,29 @@ """ Compilation Database persistence methods. """ @staticmethod - def save(filename, iterator): - # type: (str, Iterable[Compilation]) -> None + def save(iterator, filename, field_output): + # type: (Iterable[Compilation], str, bool) -> None """ Saves compilations to given file. :param filename: the destination file name :param iterator: iterator of Compilation objects. """ - entries = [entry.as_db_entry() for entry in iterator] + entries = [entry.as_db_entry(field_output) for entry in iterator] with open(filename, 'w') as handle: json.dump(entries, handle, sort_keys=True, indent=4) @staticmethod - def load(filename, category): - # type: (str, Category) -> Iterable[Compilation] + def load(filename, tools): + # type: (str, Tools) -> Iterable[Compilation] """ Load compilations from file. :param filename: the file to read from - :param category: helper object to detect compiler + :param tools: helper object to detect compiler :returns: iterator of Compilation objects. """ with open(filename, 'r') as handle: for entry in json.load(handle): - for compilation in Compilation.from_db_entry(entry, category): + for compilation in Compilation.from_db_entry(entry, tools): yield compilation @@ -703,7 +829,19 @@ '.s': 'assembly', '.S': 'assembly', '.sx': 'assembly', - '.asm': 'assembly' + '.asm': 'assembly', + '.f95': 'fortran', + '.F95': 'fortran', + '.f90': 'fortran', + '.F90': 'fortran', + '.f': 'fortran', + '.F': 'fortran', + '.FOR': 'fortran', + '.f77': 'fortran', + '.fc': 'fortran', + '.for': 'fortran', + '.ftn': 'fortran', + '.fpp': 'fortran' } __, extension = os.path.splitext(os.path.basename(filename)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/libear/CMakeLists.txt new/Bear-2.4.2/libear/CMakeLists.txt --- old/Bear-2.3.13/libear/CMakeLists.txt 2018-08-30 13:27:52.000000000 +0200 +++ new/Bear-2.4.2/libear/CMakeLists.txt 2019-08-29 13:32:53.000000000 +0200 @@ -13,7 +13,6 @@ check_function_exists(posix_spawn HAVE_POSIX_SPAWN) check_function_exists(posix_spawnp HAVE_POSIX_SPAWNP) check_symbol_exists(_NSGetEnviron crt_externs.h HAVE_NSGETENVIRON) -check_include_file(xlocale.h HAVE_XLOCALE_HEADER) find_package(Threads REQUIRED) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/libear/config.h.in new/Bear-2.4.2/libear/config.h.in --- old/Bear-2.3.13/libear/config.h.in 2018-08-30 13:27:52.000000000 +0200 +++ new/Bear-2.4.2/libear/config.h.in 2019-08-29 13:32:53.000000000 +0200 @@ -12,6 +12,5 @@ #cmakedefine HAVE_POSIX_SPAWN #cmakedefine HAVE_POSIX_SPAWNP #cmakedefine HAVE_NSGETENVIRON -#cmakedefine HAVE_XLOCALE_HEADER #cmakedefine APPLE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/libear/ear.c new/Bear-2.4.2/libear/ear.c --- old/Bear-2.3.13/libear/ear.c 2018-08-30 13:27:52.000000000 +0200 +++ new/Bear-2.4.2/libear/ear.c 2019-08-29 13:32:53.000000000 +0200 @@ -1,4 +1,4 @@ -/* Copyright (C) 2012-2017 by László Nagy +/* Copyright (C) 2012-2019 by László Nagy This file is part of Bear. Bear is a tool to generate compilation database for clang tooling. @@ -37,6 +37,7 @@ #include <stdarg.h> #include <stdlib.h> #include <stdio.h> +#include <stdint.h> #include <string.h> #include <locale.h> #include <unistd.h> @@ -47,10 +48,6 @@ #include <pthread.h> #include <errno.h> -#if defined HAVE_XLOCALE_HEADER -#include <xlocale.h> -#endif - #if defined HAVE_POSIX_SPAWN || defined HAVE_POSIX_SPAWNP #include <spawn.h> #endif @@ -97,13 +94,11 @@ static int capture_env_t(bear_env_t *env); static void release_env_t(bear_env_t *env); static char const **string_array_partial_update(char *const envp[], bear_env_t *env); -static char const **string_array_single_update(char const **in, char const *key, char const *value); +static char const **string_array_single_update(char const *envs[], char const *key, char const *value); static void report_call(char const *const argv[]); -static void write_report(int fd, char const *const argv[]); -static int write_json_report(int fd, char const *const cmd[], char const *cwd, pid_t pid); -static int encode_json_string(char const *src, char *dst, size_t dst_size); -static char const **string_array_from_varargs(char const *arg, va_list *ap); -static char const **string_array_copy(char const **const in); +static int write_report(int fd, char const *const argv[]); +static char const **string_array_from_varargs(char const * arg, va_list *args); +static char const **string_array_copy(char const **in); static size_t string_array_length(char const *const *in); static void string_array_release(char const **); @@ -126,7 +121,6 @@ static int initialized = 0; static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; -static locale_t utf_locale; static void on_load(void) __attribute__((constructor)); static void on_unload(void) __attribute__((destructor)); @@ -175,14 +169,14 @@ static void on_load(void) { pthread_mutex_lock(&mutex); - if ((!initialized) && (mt_safe_on_load())) - initialized = 1; + if (0 == initialized) + initialized = mt_safe_on_load(); pthread_mutex_unlock(&mutex); } static void on_unload(void) { pthread_mutex_lock(&mutex); - if (initialized) + if (0 != initialized) mt_safe_on_unload(); initialized = 0; pthread_mutex_unlock(&mutex); @@ -194,21 +188,11 @@ if (0 == environ) return 0; #endif - // Create locale to encode UTF-8 characters - utf_locale = newlocale(LC_CTYPE_MASK, "", (locale_t)0); - if ((locale_t)0 == utf_locale) { - PERROR("newlocale"); - return 0; - } // Capture current relevant environment variables - if (0 == capture_env_t(&initial_env)) - return 0; - // Well done - return 1; + return capture_env_t(&initial_env); } static void mt_safe_on_unload(void) { - freelocale(utf_locale); release_env_t(&initial_env); } @@ -476,124 +460,97 @@ if (-1 == fd) ERROR_AND_EXIT("mkstemp"); // Write report file - write_report(fd, argv); + const int finished = write_report(fd, argv); // Close report file if (close(fd)) ERROR_AND_EXIT("close"); + // Remove the file if it's not done + if ((-1 == finished) && (-1 == unlink(filename))) + ERROR_AND_EXIT("unlink"); } -static void write_report(int fd, char const *const argv[]) { - const locale_t saved_locale = uselocale(utf_locale); - if ((locale_t)0 == saved_locale) - ERROR_AND_EXIT("uselocale"); - - const char *cwd = getcwd(NULL, 0); - if (0 == cwd) - ERROR_AND_EXIT("getcwd"); - if (write_json_report(fd, argv, cwd, getpid())) - ERROR_AND_EXIT("writing json problem"); - free((void *)cwd); - - const locale_t restored_locale = uselocale(saved_locale); - if ((locale_t)0 == restored_locale) - ERROR_AND_EXIT("uselocale"); -} - -static int write_json_report(int fd, char const *const cmd[], char const *const cwd, pid_t pid) { - if (0 > dprintf(fd, "{ \"pid\": %d, \"cmd\": [", pid)) +static int write_binary_string(int fd, const char *const string) { + // write type + if (-1 == write(fd, "str", 3)) { + PERROR("write type"); return -1; - - for (char const *const *it = cmd; (it) && (*it); ++it) { - char const *const sep = (it != cmd) ? "," : ""; - const size_t buffer_size = (6 * strlen(*it)) + 1; - char buffer[buffer_size]; - if (-1 == encode_json_string(*it, buffer, buffer_size)) - return -1; - if (0 > dprintf(fd, "%s \"%s\"", sep, buffer)) - return -1; } - const size_t buffer_size = 6 * strlen(cwd); - char buffer[buffer_size]; - if (-1 == encode_json_string(cwd, buffer, buffer_size)) + // write length + const uint32_t length = strlen(string); + if (-1 == write(fd, (void *) &length, sizeof(uint32_t))) { + PERROR("write length"); return -1; - if (0 > dprintf(fd, "], \"cwd\": \"%s\" }", buffer)) + } + // write value + if (-1 == write(fd, (void *) string, length)) { + PERROR("write value"); return -1; - + } return 0; } -static int encode_json_string(char const *const src, char *const dst, size_t const dst_size) { - size_t const wsrc_length = mbstowcs(NULL, src, 0); - wchar_t wsrc[wsrc_length + 1]; - if (mbstowcs((wchar_t *)&wsrc, src, wsrc_length + 1) != wsrc_length) { - PERROR("mbstowcs"); +static int write_binary_string_list(int fd, const char *const *const strings) { + // write type + if (-1 == write(fd, "lst", 3)) { + PERROR("write type"); return -1; } - wchar_t const *wsrc_it = (wchar_t const *)&wsrc; - wchar_t const *const wsrc_end = wsrc_it + wsrc_length; - - char *dst_it = dst; - char *const dst_end = dst + dst_size; - - for (; wsrc_it != wsrc_end; ++wsrc_it) { - if (dst_it >= dst_end) { + // write length + const uint32_t length = string_array_length(strings); + if (-1 == write(fd, (void *) &length, sizeof(uint32_t))) { + PERROR("write length"); + return -1; + } + // write value + for (uint32_t idx = 0; idx < length; ++idx) { + const char *string = strings[idx]; + if (-1 == write_binary_string(fd, string)) { + PERROR("write value"); return -1; } - // Insert an escape character before control characters. - switch (*wsrc_it) { - case L'\b': - dst_it += snprintf(dst_it, 3, "\\b"); - break; - case L'\f': - dst_it += snprintf(dst_it, 3, "\\f"); - break; - case L'\n': - dst_it += snprintf(dst_it, 3, "\\n"); - break; - case L'\r': - dst_it += snprintf(dst_it, 3, "\\r"); - break; - case L'\t': - dst_it += snprintf(dst_it, 3, "\\t"); - break; - case L'"': - dst_it += snprintf(dst_it, 3, "\\\""); - break; - case L'\\': - dst_it += snprintf(dst_it, 3, "\\\\"); - break; - default: - if ((*wsrc_it < L' ') || (*wsrc_it > 127)) { - dst_it += snprintf(dst_it, 7, "\\u%04x", (unsigned int)*wsrc_it); - } else { - *dst_it++ = (char)*wsrc_it; - } - break; + } + return 0; +} + +static int write_report(int fd, char const *const argv[]) { + const char *cwd = getcwd(NULL, 0); + if (0 == cwd) { + PERROR("getcwd"); + return -1; + } else { + if (-1 == write_binary_string(fd, cwd)) { + PERROR("cwd writing failed"); + return -1; } } - if (dst_it < dst_end) { - // Insert a terminating 0 value. - *dst_it = 0; - return 0; + free((void *)cwd); + if (-1 == write_binary_string_list(fd, argv)) { + PERROR("cmd writing failed"); + return -1; } - return -1; + return 0; } /* update environment assure that chilren processes will copy the desired * behaviour */ static int capture_env_t(bear_env_t *env) { - int status = 1; for (size_t it = 0; it < ENV_SIZE; ++it) { char const * const env_value = getenv(env_names[it]); - char const * const env_copy = (env_value) ? strdup(env_value) : env_value; - (*env)[it] = env_copy; - status &= (env_copy) ? 1 : 0; - // Just report the problem, but don't roll back. - if (0 == status) + if (0 == env_value) { + PERROR("getenv"); + return 0; + } + + char const * const env_copy = strdup(env_value); + if (0 == env_copy) { PERROR("strdup"); + return 0; + } + + (*env)[it] = env_copy; } - return status; + return 1; } static void release_env_t(bear_env_t *env) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/man/bear.1 new/Bear-2.4.2/man/bear.1 --- old/Bear-2.3.13/man/bear.1 2018-08-30 13:27:52.000000000 +0200 +++ new/Bear-2.4.2/man/bear.1 2019-08-29 13:32:53.000000000 +0200 @@ -1,6 +1,6 @@ -.\" Automatically generated by Pandoc 2.0.6 +.\" Automatically generated by Pandoc 2.2.1 .\" -.TH "BEAR" "1" "April 20, 2017" "Bear User Manuals" "" +.TH "BEAR" "1" "May 10, 2019" "Bear User Manuals" "" .hy .SH NAME .PP @@ -47,6 +47,12 @@ .RS .RE .TP +.B \[en]field\-output +Ask to emit the \f[C]output\f[] field for each entries in the output +file. +.RS +.RE +.TP .B \-\-use\-cc \f[I]program\f[] Hint Bear to classify the given program name as C compiler. .RS @@ -57,12 +63,35 @@ .RS .RE .TP +.B \-\-use\-fortran \f[I]program\f[] +Hint Bear to classify the given program name as Fortran compiler. +.RS +.RE +.TP .B \-\-use\-only Force to use only the \f[C]\-\-use\-cc\f[] and \f[C]\-\-use\-c++\f[] given compilers. .RS .RE .TP +.B \-\-include \f[I]directory\f[] +Only include this directories or files to the output. +The flag can be used multiple times. +The directory is either absolute or relative to current working +directory. +Use \f[C]\-\-exclude\f[] to filter entries out from these directory. +.RS +.RE +.TP +.B \-\-exclude \f[I]directory\f[] +Exclude these directories or files from the output. +The flag can be used multiple times. +The directory is either absolute or relative to current working +directory. +The \f[C]\-\-include\f[] will not enable entries from these directories. +.RS +.RE +.TP .B \-a, \-\-append Use previously generated output file and append the new entries to it. This way you can run Bear continuously during work, and it keeps the @@ -160,7 +189,7 @@ on Fedora, CentOS, RHEL. .SH COPYRIGHT .PP -Copyright (C) 2012\-2017 by László Nagy +Copyright (C) 2012\-2019 by László Nagy <https://github.com/rizsotto/Bear> .SH AUTHORS László Nagy. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/man/bear.1.md new/Bear-2.4.2/man/bear.1.md --- old/Bear-2.3.13/man/bear.1.md 2018-08-30 13:27:52.000000000 +0200 +++ new/Bear-2.4.2/man/bear.1.md 2019-08-29 13:32:53.000000000 +0200 @@ -1,6 +1,6 @@ % BEAR(1) Bear User Manuals % László Nagy -% April 20, 2017 +% May 10, 2019 # NAME @@ -41,15 +41,33 @@ : Specify output file. (Default value provided.) The output is not continuously updated, it's done when the build command finished. +--field-output +: Ask to emit the `output` field for each entries in the output file. + \--use-cc *program* : Hint Bear to classify the given program name as C compiler. \--use-c++ *program* : Hint Bear to classify the given program name as C++ compiler. +\--use-fortran *program* +: Hint Bear to classify the given program name as Fortran compiler. + \--use-only : Force to use only the `--use-cc` and `--use-c++` given compilers. +\--include *directory* +: Only include this directories or files to the output. The flag can + be used multiple times. The directory is either absolute or + relative to current working directory. Use `--exclude` to filter + entries out from these directory. + +\--exclude *directory* +: Exclude these directories or files from the output. The flag can + be used multiple times. The directory is either absolute or + relative to current working directory. The `--include` will + not enable entries from these directories. + -a, \--append : Use previously generated output file and append the new entries to it. This way you can run Bear continuously during work, and it keeps the @@ -128,5 +146,5 @@ # COPYRIGHT -Copyright (C) 2012-2017 by László Nagy +Copyright (C) 2012-2019 by László Nagy <https://github.com/rizsotto/Bear> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/shell-completion/CMakeLists.txt new/Bear-2.4.2/shell-completion/CMakeLists.txt --- old/Bear-2.3.13/shell-completion/CMakeLists.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/Bear-2.4.2/shell-completion/CMakeLists.txt 2019-08-29 13:32:53.000000000 +0200 @@ -0,0 +1 @@ +add_subdirectory(bash) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/shell-completion/bash/CMakeLists.txt new/Bear-2.4.2/shell-completion/bash/CMakeLists.txt --- old/Bear-2.3.13/shell-completion/bash/CMakeLists.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/Bear-2.4.2/shell-completion/bash/CMakeLists.txt 2019-08-29 13:32:53.000000000 +0200 @@ -0,0 +1,12 @@ +find_package(bash-completion) +if (NOT BASH_COMPLETION_FOUND) + # Fallback default dir + set(BASH_COMPLETION_COMPLETIONSDIR + "${CMAKE_INSTALL_DATADIR}/bash-completion/completions/") +endif() + +install( + FILES "bear" + DESTINATION "${BASH_COMPLETION_COMPLETIONSDIR}" + COMPONENT shell-completion + ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/shell-completion/bash/bear new/Bear-2.4.2/shell-completion/bash/bear --- old/Bear-2.3.13/shell-completion/bash/bear 1970-01-01 01:00:00.000000000 +0100 +++ new/Bear-2.4.2/shell-completion/bash/bear 2019-08-29 13:32:53.000000000 +0200 @@ -0,0 +1,55 @@ +_bear() { + for word in "${COMP_WORDS[@]:0:$COMP_CWORD}" + do + if [[ $word == -- ]] + then + _command_offset $COMP_CWORD + return + fi + done + + local cur prev + if _get_comp_words_by_ref cur prev &>/dev/null; then + case $prev in + -o|--cdb) + _filedir + COMPREPLY+=($(compgen -W 'compile_commands.json' -- "$cur")) + return + ;; + --use-cc|--use-c++) + _command_offset $COMP_CWORD + return + ;; + esac + else + cur="${COMP_WORDS[COMP_CWORD]}" + fi + + local shortopts=( + h + v + o + a + ) + + local longopts=( + help + version + verbose + cdb + use-cc + use-c++ + use-only + ) + + if [[ "$cur" == "--"* ]]; then + COMPREPLY=($(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) + elif [[ "$cur" == "-"* && ${#cur} -gt 1 ]]; then + COMPREPLY=($(compgen -P '-' -W '${shortopts[*]}' -- "${cur:1}")) + else + _command_offset $COMP_CWORD + COMPREPLY+=($(compgen -P '-' -W '${shortopts[*]}' -- "${cur:1}") + $(compgen -P '--' -W '${longopts[*]}' -- "${cur:2}")) + fi +} && +complete -F _bear bear diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/test/functional/cases/exec_calls/main.c new/Bear-2.4.2/test/functional/cases/exec_calls/main.c --- old/Bear-2.3.13/test/functional/cases/exec_calls/main.c 2018-08-30 13:27:52.000000000 +0200 +++ new/Bear-2.4.2/test/functional/cases/exec_calls/main.c 2019-08-29 13:32:53.000000000 +0200 @@ -1,4 +1,4 @@ -/* Copyright (C) 2012-2017 by László Nagy +/* Copyright (C) 2012-2019 by László Nagy This file is part of Bear. Bear is a tool to generate compilation database for clang tooling. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/test/functional/cases/fortran/compile_fortran.fts new/Bear-2.4.2/test/functional/cases/fortran/compile_fortran.fts --- old/Bear-2.3.13/test/functional/cases/fortran/compile_fortran.fts 1970-01-01 01:00:00.000000000 +0100 +++ new/Bear-2.4.2/test/functional/cases/fortran/compile_fortran.fts 2019-08-29 13:32:53.000000000 +0200 @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +# REQUIRES: preload,make,fortran +# RUN: bash %s %T/fortran +# RUN: cd %T/fortran; %{intercept-build} --cdb preload.json make -C src +# RUN: cd %T/fortran; %{cdb_diff} preload.json expected.json + +set -o errexit +set -o nounset +set -o xtrace + +# the test creates a subdirectory inside output dir. +# +# ${root_dir} +# ├── expected.json +# └── src +# ├── Makefile +# └── main.c + +root_dir=$1 +mkdir -p "${root_dir}/src" + +cat > "${root_dir}/src/ex.f95" << EOF +! Test Program +program first +print *,'This is my first program' +end program first +EOF + +cat > ${root_dir}/src/Makefile << EOF +all: + gfortran ex.f95 -o ex +EOF + +cat > "${root_dir}/expected.json" << EOF +[ + { + "arguments": [ + "gfortran", + "-c", + "-o", + "ex", + "ex.f95" + ], + "directory": "${root_dir}/src", + "file": "ex.f95" + } +] +EOF diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/test/functional/cases/result/exclude.fts new/Bear-2.4.2/test/functional/cases/result/exclude.fts --- old/Bear-2.3.13/test/functional/cases/result/exclude.fts 1970-01-01 01:00:00.000000000 +0100 +++ new/Bear-2.4.2/test/functional/cases/result/exclude.fts 2019-08-29 13:32:53.000000000 +0200 @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +# REQUIRES: preload +# RUN: bash %s %T/exclude +# RUN: cd %T/exclude; %{intercept-build} --cdb preload.json --include src/target --exclude src/target/test ./run.sh +# RUN: cd %T/exclude; %{cdb_diff} preload.json expected.json + +set -o errexit +set -o nounset +set -o xtrace + +# the test creates a subdirectory inside output dir. +# +# ${root_dir} +# ├── run.sh +# ├── expected.json +# └── src +# ├── empty.c +# └── target +# ├── empty.c +# └── test +# └── empty.c + +root_dir=$1 +mkdir -p "${root_dir}/src" +touch "${root_dir}/src/empty.c" +mkdir -p "${root_dir}/src/target" +touch "${root_dir}/src/target/empty.c" +mkdir -p "${root_dir}/src/target/test" +touch "${root_dir}/src/target/test/empty.c" + +build_file="${root_dir}/run.sh" +cat > ${build_file} << EOF +#!/usr/bin/env bash + +set -o nounset +set -o xtrace + +\$CC -c -o src/empty.o src/empty.c; +\$CC -c -o src/target/empty.o src/target/empty.c; +\$CC -c -o src/target/test/empty.o src/target/test/empty.c; +EOF +chmod +x ${build_file} + +cat > "${root_dir}/expected.json" << EOF +[ +{ + "command": "cc -c -o src/target/empty.o src/target/empty.c", + "directory": "${root_dir}", + "file": "src/target/empty.c" +} +] +EOF diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/test/functional/cases/result/field_output.fts new/Bear-2.4.2/test/functional/cases/result/field_output.fts --- old/Bear-2.3.13/test/functional/cases/result/field_output.fts 1970-01-01 01:00:00.000000000 +0100 +++ new/Bear-2.4.2/test/functional/cases/result/field_output.fts 2019-08-29 13:32:53.000000000 +0200 @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +# REQUIRES: preload +# RUN: bash %s %T/field_output +# RUN: cd %T/field_output; %{intercept-build} --cdb preload.json --field-output ./run.sh +# RUN: cd %T/field_output; %{cdb_diff} preload.json expected.json + +set -o errexit +set -o nounset +set -o xtrace + +# the test creates a subdirectory inside output dir. +# +# ${root_dir} +# ├── run.sh +# ├── expected.json +# └── src +# └── empty.c + +root_dir=$1 +mkdir -p "${root_dir}/src" + +touch "${root_dir}/src/empty.c" + +build_file="${root_dir}/run.sh" +cat > ${build_file} << EOF +#!/usr/bin/env bash + +set -o nounset +set -o xtrace + +\$CC -c -o src/empty.o src/empty.c; +\$CC -c -o src/empty.c.o src/empty.c; +EOF +chmod +x ${build_file} + +cat > "${root_dir}/expected.json" << EOF +[ +{ + "command": "cc -c -o src/empty.o src/empty.c", + "directory": "${root_dir}", + "file": "src/empty.c", + "output": "src/empty.o" +} +, +{ + "command": "cc -c -o src/empty.c.o src/empty.c", + "directory": "${root_dir}", + "file": "src/empty.c", + "output": "src/empty.c.o" +} +] +EOF diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/test/functional/tools/cdb_diff.py new/Bear-2.4.2/test/functional/tools/cdb_diff.py --- old/Bear-2.3.13/test/functional/tools/cdb_diff.py 2018-08-30 13:27:52.000000000 +0200 +++ new/Bear-2.4.2/test/functional/tools/cdb_diff.py 2019-08-29 13:32:53.000000000 +0200 @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (C) 2012-2017 by László Nagy +# Copyright (C) 2012-2019 by László Nagy # This file is part of Bear. # # Bear is a tool to generate compilation database for clang tooling. @@ -42,7 +42,8 @@ os.path.normpath(os.path.join(directory, entry['file'])) arguments = entry['command'].split() if 'command' in entry else \ entry['arguments'] - return '-'.join([source[::-1]] + arguments) + output = entry['output'] if 'output' in entry else '' + return '-'.join([source[::-1]] + arguments + [output]) def main(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Bear-2.3.13/test/lit.cfg new/Bear-2.4.2/test/lit.cfg --- old/Bear-2.3.13/test/lit.cfg 2018-08-30 13:27:52.000000000 +0200 +++ new/Bear-2.4.2/test/lit.cfg 2019-08-29 13:32:53.000000000 +0200 @@ -57,6 +57,9 @@ config.available_features.add('make') config.substitutions.append(('%{make}', 'mingw32-make')) +if is_available('gfortran'): + config.available_features.add('fortran') + # classify os script language is_windows = sys.platform in {'win32', 'cygwin'}