From 69cd7369717dc51a31e6a05a654ba5675f53396b Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Tue, 6 Aug 2019 22:20:22 +1000 Subject: [PATCH 01/17] gh-254: emit output field in the output --- bear/main.py.in | 23 +++++++++++++------ .../cases/result/assembly_sources.fts | 6 +++-- .../cases/result/define_with_quote.fts | 3 ++- .../cases/result/define_with_unicode.fts | 6 +++-- .../cases/result/flags_filtered.fts | 12 ++++++---- test/functional/cases/result/output_kept.fts | 6 +++-- test/functional/tools/cdb_diff.py | 3 ++- 7 files changed, 40 insertions(+), 19 deletions(-) diff --git a/bear/main.py.in b/bear/main.py.in index 973f7cf7..48b5f504 100644 --- a/bear/main.py.in +++ b/bear/main.py.in @@ -530,13 +530,22 @@ class Compilation: """ 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: + return { + 'file': source, + 'arguments': + [self.compiler, self.phase] + self.flags + + ['-o', self.output] + [source], + 'directory': self.directory, + 'output': self.output + } + else: + return { + 'file': source, + 'arguments': + [self.compiler, self.phase] + self.flags + [source], + 'directory': self.directory + } @classmethod def from_db_entry(cls, entry, category): diff --git a/test/functional/cases/result/assembly_sources.fts b/test/functional/cases/result/assembly_sources.fts index 330c3cb9..9c79d588 100644 --- a/test/functional/cases/result/assembly_sources.fts +++ b/test/functional/cases/result/assembly_sources.fts @@ -45,7 +45,8 @@ cat > "${root_dir}/expected.json" << EOF "main.s" ], "directory": "${root_dir}/src", - "file": "main.s" + "file": "main.s", + "output": "main.o" }, { "arguments": [ @@ -56,7 +57,8 @@ cat > "${root_dir}/expected.json" << EOF "main.c" ], "directory": "${root_dir}/src", - "file": "main.c" + "file": "main.c", + "output": "main.s" } ] EOF diff --git a/test/functional/cases/result/define_with_quote.fts b/test/functional/cases/result/define_with_quote.fts index cb3ba76c..e2fad7ad 100644 --- a/test/functional/cases/result/define_with_quote.fts +++ b/test/functional/cases/result/define_with_quote.fts @@ -49,7 +49,8 @@ cat > "${root_dir}/expected.json" << EOF { "arguments": ["c++", "-c", "-DEXPORT=extern \"C\"", "-o", "hello", "src/main.cpp"], "directory": "${root_dir}", - "file": "src/main.cpp" + "file": "src/main.cpp", + "output": "hello" } ] EOF diff --git a/test/functional/cases/result/define_with_unicode.fts b/test/functional/cases/result/define_with_unicode.fts index 9e2deb36..020938da 100644 --- a/test/functional/cases/result/define_with_unicode.fts +++ b/test/functional/cases/result/define_with_unicode.fts @@ -50,12 +50,14 @@ cat > "${root_dir}/expected.json" << EOF { "arguments": ["cc", "-c", "-DMESSAGE=\u041a\u0430\u043a \u0434\u0435\u043b\u0430?", "-o", "hello", "src/main.c"], "directory": "${root_dir}", - "file": "src/main.c" + "file": "src/main.c", + "output": "hello" }, { "arguments": ["cc", "-c", "-DMESSAGE=\u05de\u05d4 \u05e9\u05dc\u05d5\u05de\u05da?", "-o", "hello", "src/main.c"], "directory": "${root_dir}", - "file": "src/main.c" + "file": "src/main.c", + "output": "hello" } ] EOF diff --git a/test/functional/cases/result/flags_filtered.fts b/test/functional/cases/result/flags_filtered.fts index 6bfd3802..f68cfcd8 100644 --- a/test/functional/cases/result/flags_filtered.fts +++ b/test/functional/cases/result/flags_filtered.fts @@ -75,22 +75,26 @@ cat > "${root_dir}/expected.json" << EOF { "command": "cc -c -fpic -o one.o lib.c", "directory": "${root_dir}/src", - "file": "lib.c" + "file": "lib.c", + "output": "one.o" }, { "command": "cc -c -fpic -o two.o lib.c", "directory": "${root_dir}/src", - "file": "lib.c" + "file": "lib.c", + "output": "two.o" }, { "command": "cc -c -o fooflag_one main.c", "directory": "${root_dir}/src", - "file": "main.c" + "file": "main.c", + "output": "fooflag_one" }, { "command": "cc -c -o fooflag_two main.c", "directory": "${root_dir}/src", - "file": "main.c" + "file": "main.c", + "output": "fooflag_two" } ] EOF diff --git a/test/functional/cases/result/output_kept.fts b/test/functional/cases/result/output_kept.fts index 3118bf05..81a1a7c4 100644 --- a/test/functional/cases/result/output_kept.fts +++ b/test/functional/cases/result/output_kept.fts @@ -41,7 +41,8 @@ cat > "${root_dir}/expected.json" << EOF { "command": "cc -c -o src/empty.o src/empty.c", "directory": "${root_dir}", - "file": "src/empty.c" + "file": "src/empty.c", + "output": "src/empty.o" } , { @@ -53,7 +54,8 @@ cat > "${root_dir}/expected.json" << EOF { "command": "cc -c -o empty.obj empty.c", "directory": "${root_dir}/src", - "file": "empty.c" + "file": "empty.c", + "output": "empty.obj" } , { diff --git a/test/functional/tools/cdb_diff.py b/test/functional/tools/cdb_diff.py index b764f30d..c855d14e 100755 --- a/test/functional/tools/cdb_diff.py +++ b/test/functional/tools/cdb_diff.py @@ -42,7 +42,8 @@ def smooth(entry): 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(): From a6ce8bca5316ee8991dfc676681b693b7b759794 Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Wed, 14 Aug 2019 18:45:07 +1000 Subject: [PATCH 02/17] gh-254: put the output flag behind a command line flag --- bear/main.py.in | 24 +++++---- .../cases/result/assembly_sources.fts | 6 +-- .../cases/result/define_with_quote.fts | 3 +- .../cases/result/define_with_unicode.fts | 6 +-- test/functional/cases/result/field_output.fts | 53 +++++++++++++++++++ .../cases/result/flags_filtered.fts | 12 ++--- test/functional/cases/result/output_kept.fts | 6 +-- 7 files changed, 79 insertions(+), 31 deletions(-) create mode 100644 test/functional/cases/result/field_output.fts diff --git a/bear/main.py.in b/bear/main.py.in index 48b5f504..2ba1025b 100644 --- a/bear/main.py.in +++ b/bear/main.py.in @@ -296,9 +296,9 @@ def intercept_build(): if args.append and os.path.isfile(args.cdb): previous = CompilationDatabase.load(args.cdb, category) 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 @@ -454,6 +454,10 @@ def create_intercept_parser(): metavar='', 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='', @@ -525,20 +529,22 @@ class Compilation: 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) if self.output: - return { + result = { 'file': source, 'arguments': [self.compiler, self.phase] + self.flags + ['-o', self.output] + [source], 'directory': self.directory, - 'output': self.output } + if field_output: + result.update({'output': self.output}) + return result else: return { 'file': source, @@ -676,14 +682,14 @@ class CompilationDatabase: """ 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) diff --git a/test/functional/cases/result/assembly_sources.fts b/test/functional/cases/result/assembly_sources.fts index 9c79d588..330c3cb9 100644 --- a/test/functional/cases/result/assembly_sources.fts +++ b/test/functional/cases/result/assembly_sources.fts @@ -45,8 +45,7 @@ cat > "${root_dir}/expected.json" << EOF "main.s" ], "directory": "${root_dir}/src", - "file": "main.s", - "output": "main.o" + "file": "main.s" }, { "arguments": [ @@ -57,8 +56,7 @@ cat > "${root_dir}/expected.json" << EOF "main.c" ], "directory": "${root_dir}/src", - "file": "main.c", - "output": "main.s" + "file": "main.c" } ] EOF diff --git a/test/functional/cases/result/define_with_quote.fts b/test/functional/cases/result/define_with_quote.fts index e2fad7ad..cb3ba76c 100644 --- a/test/functional/cases/result/define_with_quote.fts +++ b/test/functional/cases/result/define_with_quote.fts @@ -49,8 +49,7 @@ cat > "${root_dir}/expected.json" << EOF { "arguments": ["c++", "-c", "-DEXPORT=extern \"C\"", "-o", "hello", "src/main.cpp"], "directory": "${root_dir}", - "file": "src/main.cpp", - "output": "hello" + "file": "src/main.cpp" } ] EOF diff --git a/test/functional/cases/result/define_with_unicode.fts b/test/functional/cases/result/define_with_unicode.fts index 020938da..9e2deb36 100644 --- a/test/functional/cases/result/define_with_unicode.fts +++ b/test/functional/cases/result/define_with_unicode.fts @@ -50,14 +50,12 @@ cat > "${root_dir}/expected.json" << EOF { "arguments": ["cc", "-c", "-DMESSAGE=\u041a\u0430\u043a \u0434\u0435\u043b\u0430?", "-o", "hello", "src/main.c"], "directory": "${root_dir}", - "file": "src/main.c", - "output": "hello" + "file": "src/main.c" }, { "arguments": ["cc", "-c", "-DMESSAGE=\u05de\u05d4 \u05e9\u05dc\u05d5\u05de\u05da?", "-o", "hello", "src/main.c"], "directory": "${root_dir}", - "file": "src/main.c", - "output": "hello" + "file": "src/main.c" } ] EOF diff --git a/test/functional/cases/result/field_output.fts b/test/functional/cases/result/field_output.fts new file mode 100644 index 00000000..89e76280 --- /dev/null +++ b/test/functional/cases/result/field_output.fts @@ -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 --git a/test/functional/cases/result/flags_filtered.fts b/test/functional/cases/result/flags_filtered.fts index f68cfcd8..6bfd3802 100644 --- a/test/functional/cases/result/flags_filtered.fts +++ b/test/functional/cases/result/flags_filtered.fts @@ -75,26 +75,22 @@ cat > "${root_dir}/expected.json" << EOF { "command": "cc -c -fpic -o one.o lib.c", "directory": "${root_dir}/src", - "file": "lib.c", - "output": "one.o" + "file": "lib.c" }, { "command": "cc -c -fpic -o two.o lib.c", "directory": "${root_dir}/src", - "file": "lib.c", - "output": "two.o" + "file": "lib.c" }, { "command": "cc -c -o fooflag_one main.c", "directory": "${root_dir}/src", - "file": "main.c", - "output": "fooflag_one" + "file": "main.c" }, { "command": "cc -c -o fooflag_two main.c", "directory": "${root_dir}/src", - "file": "main.c", - "output": "fooflag_two" + "file": "main.c" } ] EOF diff --git a/test/functional/cases/result/output_kept.fts b/test/functional/cases/result/output_kept.fts index 81a1a7c4..3118bf05 100644 --- a/test/functional/cases/result/output_kept.fts +++ b/test/functional/cases/result/output_kept.fts @@ -41,8 +41,7 @@ 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" + "file": "src/empty.c" } , { @@ -54,8 +53,7 @@ cat > "${root_dir}/expected.json" << EOF { "command": "cc -c -o empty.obj empty.c", "directory": "${root_dir}/src", - "file": "empty.c", - "output": "empty.obj" + "file": "empty.c" } , { From 9fbf1c96749dcfcba3521ebe1382f362524f37bc Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Wed, 14 Aug 2019 18:51:22 +1000 Subject: [PATCH 03/17] gh-254: update the man page about the new flag --- man/bear.1 | 8 +++++++- man/bear.1.md | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/man/bear.1 b/man/bear.1 index c65840be..4214c6d9 100644 --- a/man/bear.1 +++ b/man/bear.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 2.0.6 +.\" Automatically generated by Pandoc 2.2.1 .\" .TH "BEAR" "1" "May 10, 2019" "Bear User Manuals" "" .hy @@ -47,6 +47,12 @@ done when the build command finished. .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 diff --git a/man/bear.1.md b/man/bear.1.md index 22be91ea..e933fbf9 100644 --- a/man/bear.1.md +++ b/man/bear.1.md @@ -41,6 +41,9 @@ writes the output file. : 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. From 4efad0adc4a3cbe54b159045f94a3e0e7f84d33c Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Wed, 14 Aug 2019 18:55:44 +1000 Subject: [PATCH 04/17] bump up version number and update changelog --- CMakeLists.txt | 2 +- ChangeLog.md | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 276bed8d..df44e319 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.8) project(bear C) -set(BEAR_VERSION "2.4.1") +set(BEAR_VERSION "2.4.2") include(GNUInstallDirs) install(FILES COPYING README.md ChangeLog.md diff --git a/ChangeLog.md b/ChangeLog.md index 44b91d5d..4d61ce39 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,9 @@ +## 2.4.2 + +Features: + - Support `output` field in the output. (#254, @bofeng17) + + ## 2.4.1 (2019.07.30) Features: From 770e8a029891e62830115e598a610ee65989713e Mon Sep 17 00:00:00 2001 From: Ruby Zhou Date: Tue, 4 Jun 2019 01:53:24 -0700 Subject: [PATCH 05/17] gh-241: Add fortran support --- .gitignore | 1 + .travis.yml | 4 ++ bear/main.py.in | 58 +++++++++++++++--- .../cases/testFortran/compile_fortran.fts | 61 +++++++++++++++++++ 4 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 test/functional/cases/testFortran/compile_fortran.fts diff --git a/.gitignore b/.gitignore index fac9795f..e1542a73 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ cmake-build*/ Output/ Cargo.lock target/ +.DS_Store diff --git a/.travis.yml b/.travis.yml index e2bcfe88..7d2f7fc1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: python +sudo: required matrix: include: @@ -39,6 +40,9 @@ before_install: brew update; brew install scons; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then + sudo apt-get install gfortran; + fi install: - pip --version diff --git a/bear/main.py.in b/bear/main.py.in index 2ba1025b..4974a797 100644 --- a/bear/main.py.in +++ b/bear/main.py.in @@ -92,11 +92,13 @@ IGNORED_FLAGS = { } # 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 = ( @@ -115,9 +117,18 @@ COMPILER_PATTERNS_CXX = ( 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', ['cwd', 'cmd']) @@ -127,11 +138,13 @@ CompilationCommand = collections.namedtuple( class Category: - - def __init__(self, only_use, c_compilers, cxx_compilers): + 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 @@ -153,6 +166,13 @@ class Category: pattern_match = Category._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: (Category, str) -> bool + use_match = Category._is_sting_match(cmd, self.fortran_compilers) + pattern_match = Category._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 @@ -288,7 +308,8 @@ def intercept_build(): """ Entry point for 'intercept-build' command. """ args = parse_args_for_intercept_build() - category = Category(args.use_only, args.use_cc, args.use_cxx) + category = Category(args.use_only, args.use_cc, + args.use_cxx, args.use_fortran) exit_code, current = capture(args, category) # To support incremental builds, it is desired to read elements from @@ -474,10 +495,19 @@ def create_intercept_parser(): default=[os.getenv('CXX', 'c++')], help="""Hint '%(prog)s' to classify the given program name as C++ compiler.""") + parser.add_argument( + '--use-fortran', + metavar='', + 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="""Only use compilers given to '--use-cc' and '--use-c++'.""") + help="""Only use compilers given to '--use-cc' and + '--use-c++' and '--use-fortran'.""") advanced = parser.add_argument_group('advanced options') advanced.add_argument( @@ -623,6 +653,8 @@ class Compilation: return command[0], C_LANG, parameters elif category.is_cxx_compiler(executable): return command[0], CPLUSPLUS_LANG, parameters + elif category.is_fortran_compiler(executable): + return command[0], FORTRAN_LANG, parameters return None @classmethod @@ -737,7 +769,19 @@ def classify_source(filename, c_compiler=True): '.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 --git a/test/functional/cases/testFortran/compile_fortran.fts b/test/functional/cases/testFortran/compile_fortran.fts new file mode 100644 index 00000000..23c626ea --- /dev/null +++ b/test/functional/cases/testFortran/compile_fortran.fts @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +# REQUIRES: preload +# RUN: bash %s %T/testFortran +# RUN: cd %T/testFortran; %{intercept-build} --cdb preload.json make -C src +# RUN: cd %T/testFortran; %{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 + +# cp "${test_input_dir}/main.c" "${root_dir}/src/main.c" + +# cat > ${root_dir}/src/Makefile << EOF +# main: main.o +# \$(CC) $< -o \$@ +# main.s: main.c +# \$(CC) -S \$< -o \$@ +# main.o: main.s +# \$(CC) -c \$< -o \$@ +# 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 From 345f605010ae668ded187e3fe429fbb045a4119a Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Wed, 14 Aug 2019 19:27:25 +1000 Subject: [PATCH 06/17] gh-241: make travis-ci not require sudo --- .travis.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7d2f7fc1..dd393d95 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,4 @@ language: python -sudo: required matrix: include: @@ -31,6 +30,7 @@ addons: packages: - cmake - scons + - gfortran - qt4-qmake before_install: @@ -40,9 +40,6 @@ before_install: brew update; brew install scons; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then - sudo apt-get install gfortran; - fi install: - pip --version From 2efa28d9f0584714b86dc0ea90b63e0da74a06c4 Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Wed, 14 Aug 2019 19:29:07 +1000 Subject: [PATCH 07/17] gh-241: update man page about the new flag --- man/bear.1 | 5 +++++ man/bear.1.md | 3 +++ 2 files changed, 8 insertions(+) diff --git a/man/bear.1 b/man/bear.1 index 4214c6d9..6cdd450f 100644 --- a/man/bear.1 +++ b/man/bear.1 @@ -63,6 +63,11 @@ Hint Bear to classify the given program name as C++ compiler. .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. diff --git a/man/bear.1.md b/man/bear.1.md index e933fbf9..19316d7a 100644 --- a/man/bear.1.md +++ b/man/bear.1.md @@ -50,6 +50,9 @@ writes the output file. \--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. From b9b2142420f6bf6996ab6523d1fede74bccc868d Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Wed, 14 Aug 2019 19:33:55 +1000 Subject: [PATCH 08/17] gh-241: run fortran test only if the compiler is available --- bear/main.py.in | 4 ++-- .../compile_fortran.fts | 20 ++++--------------- test/lit.cfg | 3 +++ 3 files changed, 9 insertions(+), 18 deletions(-) rename test/functional/cases/{testFortran => fortran}/compile_fortran.fts (63%) diff --git a/bear/main.py.in b/bear/main.py.in index 4974a797..b602e68e 100644 --- a/bear/main.py.in +++ b/bear/main.py.in @@ -506,8 +506,8 @@ def create_intercept_parser(): parser.add_argument( '--use-only', action='store_true', - help="""Only use compilers given to '--use-cc' and - '--use-c++' and '--use-fortran'.""") + help="""Only use compilers given to '--use-cc', '--use-c++' and + '--use-fortran'.""") advanced = parser.add_argument_group('advanced options') advanced.add_argument( diff --git a/test/functional/cases/testFortran/compile_fortran.fts b/test/functional/cases/fortran/compile_fortran.fts similarity index 63% rename from test/functional/cases/testFortran/compile_fortran.fts rename to test/functional/cases/fortran/compile_fortran.fts index 23c626ea..64f7198e 100644 --- a/test/functional/cases/testFortran/compile_fortran.fts +++ b/test/functional/cases/fortran/compile_fortran.fts @@ -1,9 +1,9 @@ #!/usr/bin/env bash -# REQUIRES: preload -# RUN: bash %s %T/testFortran -# RUN: cd %T/testFortran; %{intercept-build} --cdb preload.json make -C src -# RUN: cd %T/testFortran; %{cdb_diff} preload.json expected.json +# 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 @@ -27,23 +27,11 @@ print *,'This is my first program' end program first EOF -# cp "${test_input_dir}/main.c" "${root_dir}/src/main.c" - -# cat > ${root_dir}/src/Makefile << EOF -# main: main.o -# \$(CC) $< -o \$@ -# main.s: main.c -# \$(CC) -S \$< -o \$@ -# main.o: main.s -# \$(CC) -c \$< -o \$@ -# EOF - cat > ${root_dir}/src/Makefile << EOF all: gfortran ex.f95 -o ex EOF - cat > "${root_dir}/expected.json" << EOF [ { diff --git a/test/lit.cfg b/test/lit.cfg index 4782746f..1c105a6b 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -57,6 +57,9 @@ elif is_available('mingw32-make'): 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'} From c4a726946fbbc4c76b217271a9f69ca7c2f924c6 Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Wed, 14 Aug 2019 19:51:33 +1000 Subject: [PATCH 09/17] gh-241: update changelog --- ChangeLog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog.md b/ChangeLog.md index 4d61ce39..32c89e7b 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -2,6 +2,7 @@ Features: - Support `output` field in the output. (#254, @bofeng17) + - Support Fortran compiler (#201, #241, #253, @rubyzhou2014, @chunhualiao) ## 2.4.1 (2019.07.30) From 8221d92770d457b7f329c1b543d03159e8f831ae Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Sun, 18 Aug 2019 17:39:26 +1000 Subject: [PATCH 10/17] rename category class to tools --- bear/main.py.in | 104 ++++++++++++++++++++++++------------------------ 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/bear/main.py.in b/bear/main.py.in index b602e68e..d6094aed 100644 --- a/bear/main.py.in +++ b/bear/main.py.in @@ -137,7 +137,7 @@ CompilationCommand = collections.namedtuple( ['compiler', 'language', 'phase', 'flags', 'files', 'output']) -class Category: +class Tools: def __init__(self, only_use, c_compilers, cxx_compilers, fortran_compilers): self.ignore = only_use @@ -146,36 +146,38 @@ class Category: 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: (Category, str) -> bool - use_match = Category._is_sting_match(cmd, self.fortran_compilers) - pattern_match = Category._is_pattern_match( + # 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 @@ -308,14 +310,14 @@ def intercept_build(): """ Entry point for 'intercept-build' command. """ args = parse_args_for_intercept_build() - category = Category(args.use_only, args.use_cc, - args.use_cxx, args.use_fortran) - 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(entries, args.cdb, args.field_output) else: @@ -324,11 +326,11 @@ def intercept_build(): 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: @@ -338,23 +340,23 @@ def capture(args, category): # 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) return exit_code, iter(set(current)) -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 @@ -584,32 +586,32 @@ class Compilation: } @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']) - return cls.iter_from_execution(execution, category) + 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' @@ -624,11 +626,11 @@ class Compilation: 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 """ @@ -638,36 +640,36 @@ class Compilation: # '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 category.is_fortran_compiler(executable): + 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 @@ -726,17 +728,17 @@ class CompilationDatabase: 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 From f2a22b615c973edffee0d29aadf979e2bf8a6378 Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Sun, 18 Aug 2019 18:04:20 +1000 Subject: [PATCH 11/17] gh-191: fix cpack on fedora --- bear/CMakeLists.txt | 7 +++++++ bear/main.py.in | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/bear/CMakeLists.txt b/bear/CMakeLists.txt index 500e803e..e39cb900 100644 --- a/bear/CMakeLists.txt +++ b/bear/CMakeLists.txt @@ -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 --git a/bear/main.py.in b/bear/main.py.in index d6094aed..58812d96 100644 --- a/bear/main.py.in +++ b/bear/main.py.in @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env @BEAR_PYTHON_EXECUTABLE@ # -*- coding: utf-8 -*- # Copyright (C) 2012-2019 by László Nagy From 8f198b855aa08c378ee4e8e6d138274c9b6d9276 Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Sun, 18 Aug 2019 18:07:58 +1000 Subject: [PATCH 12/17] gh-191: update changelog --- ChangeLog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index 32c89e7b..e356355a 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -4,6 +4,9 @@ Features: - Support `output` field in the output. (#254, @bofeng17) - Support Fortran compiler (#201, #241, #253, @rubyzhou2014, @chunhualiao) +Bugfixes: + - Fix Cpack problem to create RPM. (#191, @antmak, @reverendhomer) + ## 2.4.1 (2019.07.30) From 04ec1c81904389248676e9d4bfff3e16a0cb66d9 Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Sun, 18 Aug 2019 21:37:21 +1000 Subject: [PATCH 13/17] gh-261: implement include exclude filter logic --- bear/main.py.in | 60 +++++++++++++++++++++++- test/functional/cases/result/exclude.fts | 53 +++++++++++++++++++++ 2 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 test/functional/cases/result/exclude.fts diff --git a/bear/main.py.in b/bear/main.py.in index 58812d96..e36efa17 100644 --- a/bear/main.py.in +++ b/bear/main.py.in @@ -341,8 +341,52 @@ def capture(args, tools): 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, 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) - return exit_code, iter(set(current)) + +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 + + 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, tools): @@ -510,6 +554,20 @@ def create_intercept_parser(): action='store_true', 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( diff --git a/test/functional/cases/result/exclude.fts b/test/functional/cases/result/exclude.fts new file mode 100644 index 00000000..521e75a7 --- /dev/null +++ b/test/functional/cases/result/exclude.fts @@ -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 From 3ba4ab8b67b077cff66cc7e2694714c07e190bc6 Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Tue, 20 Aug 2019 22:01:58 +1000 Subject: [PATCH 14/17] gh-261: update man page with the new flags --- man/bear.1 | 18 ++++++++++++++++++ man/bear.1.md | 12 ++++++++++++ 2 files changed, 30 insertions(+) diff --git a/man/bear.1 b/man/bear.1 index 6cdd450f..928b95ea 100644 --- a/man/bear.1 +++ b/man/bear.1 @@ -74,6 +74,24 @@ 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 diff --git a/man/bear.1.md b/man/bear.1.md index 19316d7a..e811eeaf 100644 --- a/man/bear.1.md +++ b/man/bear.1.md @@ -56,6 +56,18 @@ writes the output file. \--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 From b7619f05aef67aba7f69b8cde50e91d1c77ab84e Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Tue, 20 Aug 2019 22:04:17 +1000 Subject: [PATCH 15/17] gh-261: update changelog --- ChangeLog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog.md b/ChangeLog.md index e356355a..f12f6332 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -3,6 +3,7 @@ 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) From 695cd98a4274216ffa169ca669c50222c10a0fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20St=C3=B6ggl?= Date: Mon, 19 Aug 2019 11:17:40 +0200 Subject: [PATCH 16/17] Fix typos in README.md --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 9c25ebd0..cb0216bd 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ With this, it is easy to re-run the compilation with alternate 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. @@ -37,7 +37,7 @@ writes the output file. How to install -------------- -Bear is packaged for many distribution. Check out your package manager. +Bear is packaged for many distributions. Check out your package manager. Or build it from source. @@ -51,7 +51,7 @@ tested on FreeBSD, GNU/Linux and OS X. 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 @@ -75,12 +75,12 @@ After installation the usage is like this: bear -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`.) @@ -106,7 +106,7 @@ For OSX this is not an issue. The build commands from previous section will 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.) @@ -130,7 +130,7 @@ To check you installation, install `lit` and run the test suite. ### 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 From f7434544307ad7b47f9dd8f686f81350af39b6cf Mon Sep 17 00:00:00 2001 From: Laszlo Nagy Date: Thu, 29 Aug 2019 21:30:16 +1000 Subject: [PATCH 17/17] set release date --- ChangeLog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index f12f6332..c9f55e26 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,4 +1,4 @@ -## 2.4.2 +## 2.4.2 (2019.08.29) Features: - Support `output` field in the output. (#254, @bofeng17)