├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ └── bug_report.md ├── test ├── requirements.txt ├── cases │ ├── citnames │ │ ├── exit_code │ │ │ ├── exit_code_for_help.sh │ │ │ ├── exit_code_for_fail.sh │ │ │ └── exit_code_for_success.sh │ │ └── output │ │ │ ├── convert_format.sh │ │ │ ├── relative_paths_converted.sh │ │ │ ├── clang_plugin.sh │ │ │ └── wrapper_flags_extended.sh │ ├── compilation │ │ ├── exit_code │ │ │ ├── exit_code_for_help.sh │ │ │ ├── exit_code_for_empty.sh │ │ │ ├── exit_code_for_success.sh │ │ │ └── exit_code_for_fail.sh │ │ └── output │ │ │ ├── broken_build.sh │ │ │ ├── empty_argument.sh │ │ │ ├── compile_cuda.sh │ │ │ ├── compile_fortran.sh │ │ │ ├── define_with_quote.sh │ │ │ ├── define_with_escaped_quote.sh │ │ │ ├── flag │ │ │ ├── field_output.sh │ │ │ ├── use_cc.sh │ │ │ ├── use_cxx.sh │ │ │ └── append.sh │ │ │ ├── assembly_sources.mk │ │ │ ├── empty_env.sh │ │ │ ├── bug439.mk │ │ │ ├── multiple_source_build.sh │ │ │ ├── existing_files_only.sh │ │ │ ├── flags_filtered_preproc.sh │ │ │ ├── parallel_build.sh │ │ │ ├── wrapper.sh │ │ │ ├── successful_build.sh │ │ │ ├── config │ │ │ ├── filter_compilers.sh │ │ │ ├── filter_sources_relative.sh │ │ │ ├── filter_sources.sh │ │ │ ├── filter_flags_on_known_compiler.sh │ │ │ └── filter_flags.sh │ │ │ ├── duplicate_entries.sh │ │ │ └── flags_filtered_link.sh │ └── intercept │ │ ├── exit_code │ │ ├── exit_code_for_help.sh │ │ ├── exit_code_for_empty.sh │ │ ├── exit_code_for_success.sh │ │ └── exit_code_for_fail.sh │ │ ├── output │ │ ├── shell_command_with_iso8859-2.check │ │ ├── shell_command_with_iso8859-2.input │ │ ├── shell_command_with_iso8859-2.sh │ │ └── shell_commands_with_unicode.sh │ │ ├── wrapper │ │ ├── build_command_captured.sh │ │ ├── build_stdout_captured.sh │ │ ├── shell_fail_commands_intercepted.sh │ │ ├── build_stderr_captured.sh │ │ ├── use_cc_env_to_select_compiler.sh │ │ ├── libtool_commands_captured.sh │ │ ├── shell_commands_intercepted.sh │ │ ├── shell_commands_with_empty_env.sh │ │ ├── shell_commands_intercepted_without_shebang.sh │ │ ├── shell_commands_basename_compiler.sh │ │ ├── shell_commands_parallel_intercepted.sh │ │ └── shell_enable_network_proxy.sh │ │ ├── preload │ │ ├── build_command_captured.sh │ │ ├── shell_fail_commands_intercepted.sh │ │ ├── posix │ │ │ ├── no_exec.c │ │ │ ├── system │ │ │ │ └── success.c │ │ │ ├── execl │ │ │ │ ├── success.c │ │ │ │ └── failure_prints_errno.c │ │ │ ├── execlp │ │ │ │ ├── success.c │ │ │ │ ├── success_to_resolve.c │ │ │ │ └── failure_prints_errno.c │ │ │ ├── execv │ │ │ │ ├── success.c │ │ │ │ └── failure_prints_errno.c │ │ │ ├── exevp │ │ │ │ ├── success.c │ │ │ │ ├── success_to_resolve.c │ │ │ │ └── failure_prints_errno.c │ │ │ ├── execle │ │ │ │ ├── success.c │ │ │ │ └── failure_prints_errno.c │ │ │ ├── exect │ │ │ │ └── success.c │ │ │ ├── execve │ │ │ │ ├── success.c │ │ │ │ └── failure_prints_errno.c │ │ │ ├── execvpe │ │ │ │ ├── success_to_resolve.c │ │ │ │ ├── success.c │ │ │ │ └── failure_prints_errno.c │ │ │ ├── execvp2 │ │ │ │ ├── success.c │ │ │ │ └── failure_prints_errno.c │ │ │ ├── posix_spawn │ │ │ │ ├── failure_prints_errno.c │ │ │ │ └── success.c │ │ │ ├── posix_spawnp │ │ │ │ ├── failure_prints_errno.c │ │ │ │ ├── success_to_resolve.c │ │ │ │ └── success.c │ │ │ └── popen │ │ │ │ └── success.c │ │ ├── errno_reset.c │ │ ├── shell_commands_with_empty_env.sh │ │ ├── build_stdout_captured.sh │ │ ├── preload_append │ │ │ ├── fakeroot.sh │ │ │ └── io_calls.c │ │ ├── shell_commands_intercepted.sh │ │ ├── build_stderr_captured.sh │ │ ├── shell_commands_parallel_intercepted.sh │ │ ├── shell_commands_intercepted_without_shebang.sh │ │ ├── shell_redirect_works.sh │ │ ├── path_resolver │ │ │ ├── same_name_in_path.c │ │ │ └── same_name_without_exec_flag.c │ │ ├── libtool_commands_captured.sh │ │ ├── signal_inside_build.sh │ │ └── signal_outside_build.sh │ │ └── valgrind │ │ └── shell_commands_intercepted.sh ├── config.h.in └── lit.site.cfg.in ├── .gitignore ├── third_party └── CMakeLists.txt ├── source ├── intercept │ ├── libexec.version │ ├── source │ │ ├── report │ │ │ ├── wrapper │ │ │ │ ├── main.cc │ │ │ │ ├── EventFactory.h │ │ │ │ ├── EventReporter.cc │ │ │ │ ├── EventReporter.h │ │ │ │ ├── Application.h │ │ │ │ └── RpcClients.h │ │ │ └── libexec │ │ │ │ ├── std.cc │ │ │ │ ├── Environment.h │ │ │ │ ├── Buffer.cc │ │ │ │ ├── Logger.h │ │ │ │ ├── Session.h │ │ │ │ ├── Environment.cc │ │ │ │ ├── Linker.h │ │ │ │ ├── Session.cc │ │ │ │ ├── Buffer.h │ │ │ │ └── Resolver.h │ │ ├── Convert.h │ │ ├── Domain.h │ │ ├── Domain.cc │ │ ├── collect │ │ │ ├── Reporter.h │ │ │ ├── Intercept.h │ │ │ ├── SessionLibrary.h │ │ │ ├── db │ │ │ │ └── EventsDatabaseWriter.h │ │ │ ├── Reporter.cc │ │ │ ├── RpcServices.h │ │ │ ├── Session.h │ │ │ └── SessionWrapper.h │ │ └── Convert.cc │ ├── include │ │ └── intercept │ │ │ └── intercept-forward.h │ ├── test │ │ ├── libexec │ │ │ ├── LinkerMock.h │ │ │ └── ResolverMock.h │ │ └── EventFactoryTest.cc │ └── proto │ │ └── supervise.proto ├── libresult │ └── CMakeLists.txt ├── libmain │ ├── CMakeLists.txt │ ├── include │ │ └── libmain │ │ │ ├── ApplicationLogConfig.h │ │ │ ├── ApplicationFromArgs.h │ │ │ ├── SubcommandFromArgs.h │ │ │ ├── Application.h │ │ │ └── main.h │ └── source │ │ ├── SubcommandFromArgs.cc │ │ └── ApplicationFromArgs.cc ├── libflags │ └── CMakeLists.txt ├── libshell │ └── CMakeLists.txt ├── libsys │ ├── include │ │ └── libsys │ │ │ ├── lib-names.h.in │ │ │ ├── Errors.h │ │ │ ├── Environment.h │ │ │ ├── Os.h │ │ │ ├── Path.h │ │ │ └── Signal.h │ ├── test │ │ └── ErrorsTest.cc │ └── source │ │ ├── Errors.cc │ │ ├── Guard.h │ │ └── Signal.cc ├── bear │ ├── main.cc │ ├── CMakeLists.txt │ └── source │ │ └── Application.h └── citnames │ ├── source │ ├── semantic │ │ ├── ToolCuda.h │ │ ├── Common.h │ │ ├── ToolCuda.cc │ │ ├── ToolIntelFortran.h │ │ ├── ToolCrayFtnfe.h │ │ ├── ToolClang.h │ │ ├── ToolAny.h │ │ ├── ToolExtendingWrapper.h │ │ ├── ToolGcc.h │ │ ├── Build.h │ │ ├── ToolWrapper.h │ │ └── ToolAny.cc │ └── Citnames.h │ └── include │ └── citnames │ └── citnames-forward.h └── CONTRIBUTING.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [rizsotto] 2 | -------------------------------------------------------------------------------- /test/requirements.txt: -------------------------------------------------------------------------------- 1 | lit 2 | pycodestyle 3 | -------------------------------------------------------------------------------- /test/cases/citnames/exit_code/exit_code_for_help.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # RUN: %{citnames} --help -------------------------------------------------------------------------------- /test/cases/compilation/exit_code/exit_code_for_help.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # RUN: %{bear} --help -------------------------------------------------------------------------------- /test/cases/intercept/exit_code/exit_code_for_help.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # RUN: %{intercept} --help -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | cmake-build*/ 3 | Output/ 4 | Cargo.lock 5 | target/ 6 | .DS_Store 7 | cmake-build-debug/ 8 | -------------------------------------------------------------------------------- /test/cases/compilation/exit_code/exit_code_for_empty.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # XFAIL: * 4 | # RUN: %{bear} 5 | -------------------------------------------------------------------------------- /test/cases/intercept/exit_code/exit_code_for_empty.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # XFAIL: * 4 | # RUN: %{intercept} 5 | -------------------------------------------------------------------------------- /test/cases/compilation/exit_code/exit_code_for_success.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # RUN: %{bear} --verbose --output %t.json -- %{true} 4 | -------------------------------------------------------------------------------- /test/cases/citnames/exit_code/exit_code_for_fail.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # XFAIL: * 4 | # RUN: %{citnames} --verbose --input /non/exists 5 | -------------------------------------------------------------------------------- /test/cases/intercept/exit_code/exit_code_for_success.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # RUN: %{intercept} --verbose --output %t.events.json -- %{true} 4 | -------------------------------------------------------------------------------- /test/cases/compilation/exit_code/exit_code_for_fail.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # XFAIL: * 4 | # RUN: %{bear} --verbose --output %t.json -- %{false} 5 | -------------------------------------------------------------------------------- /test/cases/intercept/exit_code/exit_code_for_fail.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # XFAIL: * 4 | # RUN: %{intercept} --verbose --output %t.events.db -- %{false} 5 | -------------------------------------------------------------------------------- /test/cases/intercept/output/shell_command_with_iso8859-2.check: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rizsotto/Bear/HEAD/test/cases/intercept/output/shell_command_with_iso8859-2.check -------------------------------------------------------------------------------- /test/cases/intercept/output/shell_command_with_iso8859-2.input: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rizsotto/Bear/HEAD/test/cases/intercept/output/shell_command_with_iso8859-2.input -------------------------------------------------------------------------------- /test/cases/intercept/wrapper/build_command_captured.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: %{intercept} --force-wrapper --verbose --output %t.json -- env 5 | # RUN: assert_intercepted %t.json count -eq 0 6 | -------------------------------------------------------------------------------- /third_party/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(nlohmann_json) 2 | add_subdirectory(fmt) 3 | add_subdirectory(spdlog) 4 | add_subdirectory(grpc) 5 | 6 | if (ENABLE_UNIT_TESTS) 7 | add_subdirectory(googletest) 8 | else () 9 | add_custom_target(googletest_dependency) 10 | endif () 11 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/build_command_captured.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload 4 | # RUN: %{intercept} --verbose --output %t.json -- %{true} %s 5 | # RUN: assert_intercepted %t.json count -eq 1 6 | # RUN: assert_intercepted %t.json contains -program %{true} -arguments %{true} %s 7 | -------------------------------------------------------------------------------- /test/cases/intercept/output/shell_command_with_iso8859-2.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload, shell, dynamic-shell 4 | # TODO: %{intercept} --verbose --output %t.json -- %{shell} %S/shell_command_with_iso8859-2.input 5 | # TODO: %{shell} shell_command_with_iso8859-2.check %t.json 6 | # RUN: %{true} 7 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/shell_fail_commands_intercepted.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload, shell, dynamic-shell 4 | # RUN: %{intercept} --verbose --output %t.json -- %{shell} %s || true 5 | # RUN: assert_intercepted %t.json count -ge 2 6 | # RUN: assert_intercepted %t.json contains -program %{false} 7 | 8 | $FALSE; -------------------------------------------------------------------------------- /test/cases/intercept/valgrind/shell_commands_intercepted.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload, shell, dynamic-shell, valgrind 4 | # RUN: %{valgrind} --tool=memcheck --trace-children=yes %{intercept} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_intercepted %t.json count -ge 4 6 | 7 | $TRUE; 8 | $TRUE; 9 | $TRUE; 10 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/no_exec.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload 2 | // RUN: %{compile} -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -ge 1 5 | // RUN: assert_intercepted %t.json contains -program %t 6 | 7 | #include "config.h" 8 | 9 | int main() 10 | { 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /source/intercept/libexec.version: -------------------------------------------------------------------------------- 1 | { 2 | global: 3 | on_load; 4 | on_unload; 5 | execv; 6 | execve; 7 | execvp; 8 | execvP; 9 | exect; 10 | execvpe; 11 | execl; 12 | execlp; 13 | execle; 14 | posix_spawn; 15 | posix_spawnp; 16 | local: 17 | *; 18 | }; -------------------------------------------------------------------------------- /test/cases/intercept/preload/errno_reset.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload 2 | // RUN: %{compile} -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main() 11 | { 12 | printf("error %i: %s\n", errno, strerror(errno)); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /test/cases/intercept/wrapper/build_stdout_captured.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: %{shell} %s > %t.orig.stdout 5 | # RUN: %{intercept} --force-wrapper --output %t.json -- %{shell} %s > %t.fwd.stdout 6 | # RUN: diff %t.orig.stdout %t.fwd.stdout 7 | 8 | $ECHO "Lorem ipsum dolor sit amet, consectetur adipiscing elit," 9 | $ECHO "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." 10 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/shell_commands_with_empty_env.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload 4 | # RUN: %{intercept} --verbose --output %t.json -- env - %{shell} %s %{true} 5 | # RUN: assert_intercepted %t.json count -ge 5 6 | # RUN: assert_intercepted %t.json contains -program %{true} 7 | # RUN: assert_intercepted %t.json contains -program %{shell} -arguments %{shell} %s %{true} 8 | 9 | $1; 10 | $1; 11 | $1; 12 | -------------------------------------------------------------------------------- /test/cases/intercept/wrapper/shell_fail_commands_intercepted.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: cd %T; %{intercept} --force-wrapper --verbose --output %t.json -- %{shell} %s || true 5 | # RUN: assert_intercepted %t.json count -ge 1 6 | # RUN: assert_intercepted %t.json contains -program %{cxx_compiler} -arguments %{cxx_compiler} -c not_exists.cc -o not_exists.o 7 | 8 | $CXX -c not_exists.cc -o not_exists.o; 9 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/build_stdout_captured.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload, shell, dynamic-shell 4 | # RUN: %{shell} %s > %t.orig.stdout 5 | # RUN: %{intercept} --output %t.json -- %{shell} %s > %t.fwd.stdout 6 | # RUN: diff %t.orig.stdout %t.fwd.stdout 7 | 8 | $ECHO "Lorem ipsum dolor sit amet, consectetur adipiscing elit," 9 | $ECHO "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." 10 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/preload_append/fakeroot.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload, fakeroot 4 | # RUN: %{fakeroot} whoami | xargs test 'root' = 5 | # RUN: %{intercept} --output %t.json -- %{fakeroot} whoami | xargs test 'root' = 6 | # RUN: assert_intercepted %t.json count -ge 2 7 | # RUN: assert_intercepted %t.json contains -arguments %{fakeroot} whoami 8 | # RUN: assert_intercepted %t.json contains -arguments whoami 9 | -------------------------------------------------------------------------------- /test/cases/intercept/wrapper/build_stderr_captured.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: %{shell} %s 2> %t.orig.stderr 5 | # RUN: %{intercept} --force-wrapper --output %t.json -- %{shell} %s 2> %t.fwd.stderr 6 | # RUN: diff %t.orig.stderr %t.fwd.stderr 7 | 8 | >&2 $ECHO "Lorem ipsum dolor sit amet, consectetur adipiscing elit," 9 | >&2 $ECHO "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." 10 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/shell_commands_intercepted.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload, shell, dynamic-shell 4 | # RUN: %{intercept} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_intercepted %t.json count -ge 4 6 | # RUN: assert_intercepted %t.json contains -program %{true} 7 | # RUN: assert_intercepted %t.json contains -program %{shell} -arguments %{shell} %s 8 | 9 | $TRUE; 10 | $TRUE; 11 | $TRUE; 12 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/build_stderr_captured.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload, shell, dynamic-shell 4 | # RUN: %{shell} %s 2> %t.orig.stderr 5 | # RUN: %{intercept} --output %t.json -- %{shell} %s 2> %t.fwd.stderr 6 | # RUN: diff %t.orig.stderr %t.fwd.stderr 7 | 8 | >&2 $ECHO "Lorem ipsum dolor sit amet, consectetur adipiscing elit," 9 | >&2 $ECHO "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." 10 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/shell_commands_parallel_intercepted.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload 4 | # RUN: %{intercept} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_intercepted %t.json count -ge 4 6 | # RUN: assert_intercepted %t.json contains -program %{true} 7 | # RUN: assert_intercepted %t.json contains -program %{shell} -arguments %{shell} %s 8 | 9 | $TRUE & 10 | $TRUE & 11 | $TRUE & 12 | 13 | wait 14 | -------------------------------------------------------------------------------- /test/cases/compilation/output/broken_build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_compilation %t.json count -ge 1 6 | # RUN: assert_compilation %t.json contains -file %T/broken_build.c -directory %T -arguments %{c_compiler} -c -o broken_build.o broken_build.c 7 | 8 | echo "int test() { ;" > broken_build.c 9 | 10 | $CC -c -o broken_build.o broken_build.c || true 11 | -------------------------------------------------------------------------------- /test/cases/compilation/output/empty_argument.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_compilation %t.json count -eq 0 6 | 7 | touch empty_argument_1.c empty_argument_2.c 8 | 9 | # empty argument for a command 10 | $ECHO "" ""; 11 | 12 | # empty argument for a compiler 13 | $CC -c -o empty_argument_1.o empty_argument_1.c "" || true; 14 | $CC -c -o empty_argument_2.o "" empty_argument_2.c || true; 15 | -------------------------------------------------------------------------------- /source/libresult/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(result_a INTERFACE) 2 | target_include_directories(result_a INTERFACE include/) 3 | 4 | if (ENABLE_UNIT_TESTS) 5 | add_executable(result_unit_test 6 | test/ResultTest.cc 7 | ) 8 | 9 | target_link_libraries(result_unit_test result_a) 10 | target_link_libraries(result_unit_test PkgConfig::GTest ${CMAKE_THREAD_LIBS_INIT}) 11 | 12 | add_test(NAME bear::result_unit_test COMMAND $) 13 | endif () -------------------------------------------------------------------------------- /source/libmain/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(main_a OBJECT) 2 | target_include_directories(main_a PUBLIC include/) 3 | target_sources(main_a 4 | PRIVATE 5 | source/ApplicationLogConfig.cc 6 | source/ApplicationFromArgs.cc 7 | source/SubcommandFromArgs.cc 8 | INTERFACE 9 | $ 10 | ) 11 | target_link_libraries(main_a PUBLIC 12 | result_a 13 | flags_a 14 | fmt::fmt 15 | spdlog::spdlog) 16 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/shell_commands_intercepted_without_shebang.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload, shell, dynamic-shell 4 | # RUN: %{shell} %s > %t.sh 5 | # RUN: chmod +x %t.sh 6 | # RUN: %{intercept} --verbose --output %t.json -- %t.sh 7 | # RUN: assert_intercepted %t.json count -ge 4 8 | # RUN: assert_intercepted %t.json contains -program %{true} 9 | # RUN: assert_intercepted %t.json contains -program %t.sh -arguments %t.sh 10 | 11 | cat << EOF 12 | $TRUE 13 | $TRUE 14 | $TRUE 15 | EOF 16 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/system/success.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_system 2 | // RUN: %{compile} -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -ge 2 5 | // RUN: assert_intercepted %t.json contains -program %t 6 | // RUN: assert_intercepted %t.json contains -arguments ls -l 7 | 8 | #include 9 | 10 | int main () { 11 | char *const command = "ls -l"; 12 | 13 | system(command); 14 | 15 | return EXIT_SUCCESS; 16 | } 17 | -------------------------------------------------------------------------------- /test/cases/intercept/wrapper/use_cc_env_to_select_compiler.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: echo "#!/usr/bin/env sh\n%{c_compiler} $@" > %t.wrapper 5 | # RUN: chmod +x %t.wrapper 6 | # RUN: cd %T; env CC=%t.wrapper %{intercept} --force-wrapper --verbose --output %t.json -- %{shell} %s || true 7 | # RUN: assert_intercepted %t.json count -ge 1 8 | # RUN: assert_intercepted %t.json contains -program %t.wrapper -arguments %t.wrapper -c use_env.c -o use_env.o 9 | 10 | touch use_env.c 11 | 12 | $CC -c use_env.c -o use_env.o; 13 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/shell_redirect_works.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload, shell, dynamic-shell 4 | # RUN: %{intercept} --output %t.json -- %{shell} -c "%{echo} hi | %{shell} %s" 5 | # RUN: assert_intercepted %t.json count -eq 4 6 | # RUN: assert_intercepted %t.json contains -program %{shell} 7 | # RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "hi" 8 | # RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "hi there" 9 | 10 | while read line 11 | do 12 | $ECHO "$line there" 13 | done 14 | -------------------------------------------------------------------------------- /test/cases/compilation/output/compile_cuda.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell, cuda 4 | # RUN: cd %T; env CC=%{cuda} %{bear} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_compilation %t.json count -eq 2 6 | # RUN: assert_compilation %t.json contains -file %T/successful_build_1.cu -directory %T 7 | # RUN: assert_compilation %t.json contains -file %T/successful_build_2.cu -directory %T 8 | 9 | touch successful_build_1.cu successful_build_2.cu 10 | 11 | $CC -c -o successful_build_1.o successful_build_1.cu; 12 | $CC -c -o successful_build_2.o successful_build_2.cu; 13 | -------------------------------------------------------------------------------- /test/cases/compilation/output/compile_fortran.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell, fortran 4 | # RUN: cd %T; env FC=%{fortran} %{bear} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_compilation %t.json count -eq 1 6 | # RUN: assert_compilation %t.json contains -file %T/compile_fortran.f95 -directory %T -arguments %{fortran} -c -o compile_fortran.o compile_fortran.f95 7 | 8 | cat > compile_fortran.f95 << EOF 9 | ! Test Program 10 | program first 11 | print *,'This is my first program' 12 | end program first 13 | EOF 14 | 15 | $FC -c -o compile_fortran.o compile_fortran.f95 16 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/execl/success.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execl 2 | // RUN: %{compile} '-D_PROGRAM="%{echo}"' -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -eq 2 5 | // RUN: assert_intercepted %t.json contains -program %t -arguments %t 6 | // RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "hi there" 7 | 8 | #include "config.h" 9 | 10 | #if defined HAVE_UNISTD_H 11 | #include 12 | #endif 13 | 14 | int main() 15 | { 16 | char *const program = _PROGRAM; 17 | return execl(program, program, "hi there", 0); 18 | } 19 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/execlp/success.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execlp 2 | // RUN: %{compile} '-D_PROGRAM="%{echo}"' -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -eq 2 5 | // RUN: assert_intercepted %t.json contains -program %t -arguments %t 6 | // RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "hi there" 7 | 8 | #include "config.h" 9 | 10 | #if defined HAVE_UNISTD_H 11 | #include 12 | #endif 13 | 14 | int main() 15 | { 16 | char *const program = _PROGRAM; 17 | return execlp(program, program, "hi there", 0); 18 | } 19 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/execlp/success_to_resolve.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execlp 2 | // RUN: %{compile} '-D_PROGRAM="echo"' -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -eq 2 5 | // RUN: assert_intercepted %t.json contains -program %t -arguments %t 6 | // RUN: assert_intercepted %t.json contains -program %{echo} -arguments echo "hi there" 7 | 8 | #include "config.h" 9 | 10 | #if defined HAVE_UNISTD_H 11 | #include 12 | #endif 13 | 14 | int main() 15 | { 16 | char *const program = _PROGRAM; 17 | return execlp(program, program, "hi there", 0); 18 | } 19 | -------------------------------------------------------------------------------- /test/cases/compilation/output/define_with_quote.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_compilation %t.json count -ge 1 6 | # RUN: assert_compilation %t.json contains -file %T/define_with_quote.c -directory %T -arguments %{cxx_compiler} -c -DEXPORT="extern \"C\"" -o define_with_quote define_with_quote.c 7 | 8 | cat > define_with_quote.c < 10 | 11 | EXPORT void foo(void) { 12 | printf("Hello world!\n"); 13 | } 14 | 15 | int main() { 16 | foo(); 17 | } 18 | EOF 19 | 20 | $CXX -DEXPORT="extern \"C\"" -o define_with_quote define_with_quote.c; 21 | -------------------------------------------------------------------------------- /test/cases/compilation/output/define_with_escaped_quote.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_compilation %t.json count -ge 1 6 | # RUN: assert_compilation %t.json contains -file %T/define_with_escaped_quote.c -directory %T -arguments %{c_compiler} -c '-DMESSAGE="Hello World\n"' -o define_with_escaped_quote define_with_escaped_quote.c 7 | 8 | cat > define_with_escaped_quote.c < 10 | 11 | int main() { 12 | printf(MESSAGE); 13 | return 0; 14 | } 15 | EOF 16 | 17 | $CC '-DMESSAGE="Hello World\n"' -o define_with_escaped_quote define_with_escaped_quote.c; 18 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/execv/success.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execv 2 | // RUN: %{compile} '-D_PROGRAM="%{echo}"' -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -eq 2 5 | // RUN: assert_intercepted %t.json contains -program %t -arguments %t 6 | // RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "hi there" 7 | 8 | #include "config.h" 9 | 10 | #if defined HAVE_UNISTD_H 11 | #include 12 | #endif 13 | 14 | int main() 15 | { 16 | char *const program = _PROGRAM; 17 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 18 | return execv(program, argv); 19 | } 20 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/exevp/success.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execvp 2 | // RUN: %{compile} '-D_PROGRAM="%{echo}"' -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -eq 2 5 | // RUN: assert_intercepted %t.json contains -program %t -arguments %t 6 | // RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "hi there" 7 | 8 | #include "config.h" 9 | 10 | #if defined HAVE_UNISTD_H 11 | #include 12 | #endif 13 | 14 | int main() 15 | { 16 | char *const program = _PROGRAM; 17 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 18 | return execvp(program, argv); 19 | } 20 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/exevp/success_to_resolve.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execvp 2 | // RUN: %{compile} '-D_PROGRAM="echo"' -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -eq 2 5 | // RUN: assert_intercepted %t.json contains -program %t -arguments %t 6 | // RUN: assert_intercepted %t.json contains -program %{echo} -arguments echo "hi there" 7 | 8 | #include "config.h" 9 | 10 | #if defined HAVE_UNISTD_H 11 | #include 12 | #endif 13 | 14 | int main() 15 | { 16 | char *const program = _PROGRAM; 17 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 18 | return execvp(program, argv); 19 | } 20 | -------------------------------------------------------------------------------- /source/libflags/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(flags_a OBJECT) 2 | target_include_directories(flags_a PUBLIC include/) 3 | target_sources(flags_a 4 | PRIVATE 5 | source/Flags.cc 6 | INTERFACE 7 | $ 8 | ) 9 | target_link_libraries(flags_a PUBLIC result_a fmt::fmt) 10 | 11 | if (ENABLE_UNIT_TESTS) 12 | add_executable(flags_unit_test 13 | test/FlagsTest.cc 14 | ) 15 | 16 | target_link_libraries(flags_unit_test flags_a) 17 | target_link_libraries(flags_unit_test PkgConfig::GTest ${CMAKE_THREAD_LIBS_INIT}) 18 | 19 | add_test(NAME bear::flags_unit_test COMMAND $) 20 | endif () -------------------------------------------------------------------------------- /source/libshell/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(shell_a OBJECT) 2 | target_include_directories(shell_a PUBLIC include/) 3 | target_sources(shell_a 4 | PRIVATE 5 | source/Command.cc 6 | INTERFACE 7 | $ 8 | ) 9 | target_link_libraries(shell_a PUBLIC result_a) 10 | 11 | if (ENABLE_UNIT_TESTS) 12 | add_executable(shell_unit_test 13 | test/CommandTest.cc 14 | ) 15 | 16 | target_link_libraries(shell_unit_test shell_a) 17 | target_link_libraries(shell_unit_test PkgConfig::GTest ${CMAKE_THREAD_LIBS_INIT}) 18 | 19 | add_test(NAME bear::shell_unit_test COMMAND $) 20 | endif () 21 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/execle/success.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execle 2 | // RUN: %{compile} '-D_PROGRAM="%{echo}"' -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -eq 2 5 | // RUN: assert_intercepted %t.json contains -program %t -arguments %t 6 | // RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "hi there" 7 | 8 | #include "config.h" 9 | 10 | #if defined HAVE_UNISTD_H 11 | #include 12 | #endif 13 | 14 | int main() 15 | { 16 | char *const program = _PROGRAM; 17 | char *const envp[] = { "THIS=THAT", 0 }; 18 | return execle(program, program, "hi there", 0, envp); 19 | } 20 | -------------------------------------------------------------------------------- /test/cases/compilation/output/flag/field_output.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_compilation %t.json count -eq 2 6 | # RUN: assert_compilation %t.json contains -file %T/field_output_1.c -output %T/field_output_1.o -directory %T -arguments %{c_compiler} -c -o field_output_1.o field_output_1.c 7 | # RUN: assert_compilation %t.json contains -file %T/field_output_2.c -output %T/field_output_2.o -directory %T -arguments %{c_compiler} -c -o field_output_2.o field_output_2.c 8 | 9 | touch field_output_1.c field_output_2.c 10 | 11 | $CC -c -o field_output_1.o field_output_1.c; 12 | $CC -c -o field_output_2.o field_output_2.c; 13 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/exect/success.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_exect 2 | // RUN: %{compile} '-D_PROGRAM="%{echo}"' -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -eq 2 5 | // RUN: assert_intercepted %t.json contains -program %t -arguments %t 6 | // RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "hi there" 7 | 8 | #include "config.h" 9 | 10 | #if defined HAVE_UNISTD_H 11 | #include 12 | #endif 13 | 14 | int main() 15 | { 16 | char *const program = _PROGRAM; 17 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 18 | char *const envp[] = { "THIS=THAT", 0 }; 19 | return exect(program, argv, envp); 20 | } 21 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/execve/success.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execve 2 | // RUN: %{compile} '-D_PROGRAM="%{echo}"' -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -eq 2 5 | // RUN: assert_intercepted %t.json contains -program %t -arguments %t 6 | // RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "hi there" 7 | 8 | #include "config.h" 9 | 10 | #if defined HAVE_UNISTD_H 11 | #include 12 | #endif 13 | 14 | int main() 15 | { 16 | char *const program = _PROGRAM; 17 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 18 | char *const envp[] = { "THIS=THAT", 0 }; 19 | return execve(program, argv, envp); 20 | } 21 | -------------------------------------------------------------------------------- /test/cases/compilation/output/assembly_sources.mk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env make 2 | 3 | # REQUIRES: make 4 | # RUN: %{make} -C %T -f %s clean 5 | # RUN: %{bear} --verbose --output %t.json -- %{make} -C %T -f %s 6 | # RUN: assert_compilation %t.json count -eq 2 7 | # RUN: assert_compilation %t.json contains -file %T/main.c -directory %T -arguments %{c_compiler} -S -o main.s main.c 8 | # RUN: assert_compilation %t.json contains -file %T/main.s -directory %T -arguments %{c_compiler} -c -o main.o main.s 9 | 10 | main: main.o 11 | $(CC) $< -o $@ 12 | 13 | main.s: main.c 14 | $(CC) -S $< -o $@ 15 | 16 | main.o: main.s 17 | $(CC) -c $< -o $@ 18 | 19 | main.c: 20 | echo "int main() { return 0; }" > $@ 21 | 22 | clean: 23 | rm -f main main.o main.s main.c 24 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/path_resolver/same_name_in_path.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, shell, dynamic-shell 2 | // RUN: mkdir -p %T/same_name_in_path/a %T/same_name_in_path/b 3 | // RUN: %{compile} '-D_MESSAGE="one"' -o %T/same_name_in_path/a/a.out %s 4 | // RUN: %{compile} '-D_MESSAGE="two"' -o %T/same_name_in_path/b/a.out %s 5 | // RUN: env PATH=%T/same_name_in_path/a:%T/same_name_in_path/b %{shell} -c a.out > %t.without.txt 6 | // RUN: env PATH=%T/same_name_in_path/a:%T/same_name_in_path/b %{intercept} --output %t.json -- %{shell} -c a.out > %t.with.txt 7 | // RUN: diff %t.without.txt %t.with.txt 8 | 9 | #include 10 | 11 | int main() 12 | { 13 | const char *const message = _MESSAGE; 14 | printf(message); 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/execvpe/success_to_resolve.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execvpe 2 | // RUN: %{compile} '-D_PROGRAM="echo"' -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -eq 2 5 | // RUN: assert_intercepted %t.json contains -program %t -arguments %t 6 | // RUN: assert_intercepted %t.json contains -arguments echo "hi there" 7 | 8 | #include "config.h" 9 | 10 | #define _GNU_SOURCE 11 | 12 | #if defined HAVE_UNISTD_H 13 | #include 14 | #endif 15 | 16 | int main() 17 | { 18 | char *const program = _PROGRAM; 19 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 20 | char *const envp[] = { "THIS=THAT", 0 }; 21 | return execvpe(program, argv, envp); 22 | } 23 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/preload_append/io_calls.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, shell, dynamic-shell 2 | // RUN: %{compile} '-D_FILE="%t.state"' -fpic -shared -o %t.so %s 3 | // RUN: env LD_PRELOAD=%t.so %{intercept} --verbose --output %t.json -- %{shell} -c %{true} 4 | // RUN: assert_intercepted %t.json count -ge 2 5 | // RUN: assert_intercepted %t.json contains -arguments %{shell} -c %{true} 6 | // RUN: assert_intercepted %t.json contains -program %{true} -arguments %{true} 7 | // RUN: test -f %t.state 8 | 9 | #include 10 | 11 | void on_load() __attribute__((constructor)); 12 | void on_load() 13 | { 14 | const char* file = _FILE; 15 | 16 | FILE* handle = fopen(file, "a"); 17 | fprintf(handle, "here we go\n"); 18 | fclose(handle); 19 | } 20 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/execvpe/success.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execvpe 2 | // RUN: %{compile} '-D_PROGRAM="%{echo}"' -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -eq 2 5 | // RUN: assert_intercepted %t.json contains -program %t -arguments %t 6 | // RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "hi there" 7 | 8 | #include "config.h" 9 | 10 | #if defined HAVE_UNISTD_H 11 | #define _GNU_SOURCE 12 | #include 13 | #endif 14 | 15 | int main() 16 | { 17 | char *const program = _PROGRAM; 18 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 19 | char *const envp[] = { "THIS=THAT", 0 }; 20 | return execvpe(program, argv, envp); 21 | } 22 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/execvp2/success.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execvP 2 | // RUN: %{compile} '-D_PROGRAM="echo"' -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -eq 2 5 | // RUN: assert_intercepted %t.json contains -program %t -arguments %t 6 | // RUN: assert_intercepted %t.json contains -program %{echo} -arguments echo "hi there" 7 | 8 | #include "config.h" 9 | 10 | #if defined HAVE_UNISTD_H 11 | #include 12 | #endif 13 | 14 | int main() 15 | { 16 | char *const program = _PROGRAM; 17 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 18 | char *const envp[] = { "THIS=THAT", 0 }; 19 | return execvP(program, argv, "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin", envp); 20 | } 21 | -------------------------------------------------------------------------------- /test/cases/compilation/output/empty_env.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload, shell 4 | # RUN: %{shell} %s %t 5 | # RUN: cd %T; /usr/bin/env - %{bear} --verbose --output %t.json -- %{shell} %t/build.sh 6 | # RUN: assert_compilation %t.json count -eq 2 7 | # RUN: assert_compilation %t.json contains -file %t/source_1.c -directory %T -arguments %{c_compiler} -c -o %t/source_1.o %t/source_1.c 8 | # RUN: assert_compilation %t.json contains -file %t/source_2.c -directory %T -arguments %{c_compiler} -c -o %t/source_2.o %t/source_2.c 9 | 10 | TEST=$1 11 | 12 | mkdir -p $TEST; 13 | touch $TEST/source_1.c; 14 | touch $TEST/source_2.c; 15 | 16 | cat > "$TEST/build.sh" << EOF 17 | #!/usr/bin/env sh 18 | 19 | $CC -c -o $TEST/source_1.o $TEST/source_1.c; 20 | $CC -c -o $TEST/source_2.o $TEST/source_2.c; 21 | EOF 22 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/path_resolver/same_name_without_exec_flag.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, shell, dynamic-shell 2 | // RUN: mkdir -p %T/same_name_without_exec_flag/a %T/same_name_without_exec_flag/b 3 | // RUN: touch %T/same_name_without_exec_flag/a/a.out 4 | // RUN: %{compile} '-D_MESSAGE="two"' -o %T/same_name_without_exec_flag/b/a.out %s 5 | // RUN: env PATH=%T/same_name_without_exec_flag/a:%T/same_name_without_exec_flag/b %{shell} -c a.out > %t.without.txt 6 | // RUN: env PATH=%T/same_name_without_exec_flag/a:%T/same_name_without_exec_flag/b %{intercept} --output %t.json -- %{shell} -c a.out > %t.with.txt 7 | // RUN: diff %t.without.txt %t.with.txt 8 | 9 | #include 10 | 11 | int main() 12 | { 13 | const char *const message = _MESSAGE; 14 | printf(message); 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /test/cases/compilation/output/bug439.mk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env make 2 | 3 | # REQUIRES: make, shell 4 | # RUN: mkdir -p %T/make 5 | # RUN: %{make} -C %T -f %s clean 6 | # RUN: %{shell} -c "PATH=%T:$PATH %{bear} --verbose --output %t.json -- %{make} -C %T -f %s" 7 | # RUN: assert_compilation %t.json count -eq 2 8 | # RUN: assert_compilation %t.json contains -file %T/bug439.c -directory %T -arguments %{c_compiler} -S -o bug439.s bug439.c 9 | # RUN: assert_compilation %t.json contains -file %T/bug439.s -directory %T -arguments %{c_compiler} -c -o bug439.o bug439.s 10 | 11 | bug439: bug439.o 12 | $(CC) $< -o $@ 13 | 14 | bug439.s: bug439.c 15 | $(CC) -S $< -o $@ 16 | 17 | bug439.o: bug439.s 18 | $(CC) -c $< -o $@ 19 | 20 | bug439.c: 21 | echo "int main() { return 0; }" > $@ 22 | 23 | clean: 24 | rm -f bug439 bug439.o bug439.s bug439.c 25 | -------------------------------------------------------------------------------- /test/cases/intercept/wrapper/libtool_commands_captured.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell, libtool 4 | # RUN: %{intercept} --force-wrapper --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_intercepted %t.json count -ge 4 6 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -g -O -c main.c -o main.o 7 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -g -O -c hello.c -o hello.o 8 | 9 | echo "int main() { return 0; }" > main.c 10 | echo "int hello() { return 1; }" > hello.c 11 | 12 | $LIBTOOL --mode=compile --tag=CC $CC -g -O -c main.c -o main.o; 13 | $LIBTOOL --mode=compile --tag=CC $CC -g -O -c hello.c -o hello.o; 14 | $LIBTOOL --mode=link --tag=CC $CC -g -O -o libhello.la hello.lo 15 | $LIBTOOL --mode=link --tag=CC $CC -g -O -o libtool_test main.lo libhello.la 16 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/libtool_commands_captured.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload, shell, dynamic-shell, libtool 4 | # RUN: %{intercept} --force-preload --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_intercepted %t.json count -ge 4 6 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -g -O -c main.c -o main.o 7 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -g -O -c hello.c -o hello.o 8 | 9 | echo "int main() { return 0; }" > main.c 10 | echo "int hello() { return 1; }" > hello.c 11 | 12 | $LIBTOOL --mode=compile --tag=CC $CC -g -O -c main.c -o main.o; 13 | $LIBTOOL --mode=compile --tag=CC $CC -g -O -c hello.c -o hello.o; 14 | $LIBTOOL --mode=link --tag=CC $CC -g -O -o libhello.la hello.lo 15 | $LIBTOOL --mode=link --tag=CC $CC -g -O -o libtool_test main.lo libhello.la 16 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/execl/failure_prints_errno.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execl 2 | // RUN: %{compile} '-D_PROGRAM="/path/to/not/existing"' -o %t %s 3 | // RUN: %t > %t.without.errno 4 | // RUN: %{intercept} --output %t.json -- %t > %t.with.errno 5 | // RUN: diff %t.with.errno %t.without.errno 6 | // RUN: assert_intercepted %t.json count -eq 1 7 | // RUN: assert_intercepted %t.json contains -program %t 8 | 9 | #include "config.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #if defined HAVE_UNISTD_H 17 | #include 18 | #endif 19 | 20 | int main() 21 | { 22 | char *const program = _PROGRAM; 23 | if (-1 == execl(program, program, "hi there", 0)) { 24 | const int error = errno; 25 | printf("errno: %d (%s)\n", error, strerror(error)); 26 | return EXIT_SUCCESS; 27 | } 28 | 29 | return EXIT_FAILURE; 30 | } 31 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/execlp/failure_prints_errno.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execlp 2 | // RUN: %{compile} '-D_PROGRAM="/path/to/not/existing"' -o %t %s 3 | // RUN: %t > %t.without.errno 4 | // RUN: %{intercept} --output %t.json -- %t > %t.with.errno 5 | // RUN: diff %t.with.errno %t.without.errno 6 | // RUN: assert_intercepted %t.json count -eq 1 7 | // RUN: assert_intercepted %t.json contains -program %t 8 | 9 | #include "config.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #if defined HAVE_UNISTD_H 17 | #include 18 | #endif 19 | 20 | int main() 21 | { 22 | char *const program = _PROGRAM; 23 | if (-1 == execlp(program, program, "hi there", 0)) { 24 | const int error = errno; 25 | printf("errno: %d (%s)\n", error, strerror(error)); 26 | return EXIT_SUCCESS; 27 | } 28 | 29 | return EXIT_FAILURE; 30 | } 31 | -------------------------------------------------------------------------------- /source/libsys/include/libsys/lib-names.h.in: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #define LIBC_SO "@LIBC_SO@" 23 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/execle/failure_prints_errno.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execle 2 | // RUN: %{compile} '-D_PROGRAM="/path/to/not/existing"' -o %t %s 3 | // RUN: %t > %t.without.errno 4 | // RUN: %{intercept} --output %t.json -- %t > %t.with.errno 5 | // RUN: diff %t.with.errno %t.without.errno 6 | // RUN: assert_intercepted %t.json count -eq 1 7 | // RUN: assert_intercepted %t.json contains -program %t 8 | 9 | #include "config.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #if defined HAVE_UNISTD_H 17 | #include 18 | #endif 19 | 20 | extern char **environ; 21 | 22 | int main() 23 | { 24 | char *const program = _PROGRAM; 25 | if (-1 == execle(program, program, "hi there", 0, environ)) { 26 | const int error = errno; 27 | printf("errno: %d (%s)\n", error, strerror(error)); 28 | return EXIT_SUCCESS; 29 | } 30 | 31 | return EXIT_FAILURE; 32 | } 33 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/execv/failure_prints_errno.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execv 2 | // RUN: %{compile} '-D_PROGRAM="/path/to/not/existing"' -o %t %s 3 | // RUN: %t > %t.without.errno 4 | // RUN: %{intercept} --output %t.json -- %t > %t.with.errno 5 | // RUN: diff %t.with.errno %t.without.errno 6 | // RUN: assert_intercepted %t.json count -eq 1 7 | // RUN: assert_intercepted %t.json contains -program %t 8 | 9 | #include "config.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #if defined HAVE_UNISTD_H 17 | #include 18 | #endif 19 | 20 | int main() 21 | { 22 | char *const program = _PROGRAM; 23 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 24 | 25 | if (-1 == execv(program, argv)) { 26 | const int error = errno; 27 | printf("errno: %d (%s)\n", error, strerror(error)); 28 | return EXIT_SUCCESS; 29 | } 30 | 31 | return EXIT_FAILURE; 32 | } 33 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/exevp/failure_prints_errno.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execvp 2 | // RUN: %{compile} '-D_PROGRAM="/path/to/not/existing"' -o %t %s 3 | // RUN: %t > %t.without.errno 4 | // RUN: %{intercept} --output %t.json -- %t > %t.with.errno 5 | // RUN: diff %t.with.errno %t.without.errno 6 | // RUN: assert_intercepted %t.json count -eq 1 7 | // RUN: assert_intercepted %t.json contains -program %t 8 | 9 | #include "config.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #if defined HAVE_UNISTD_H 17 | #include 18 | #endif 19 | 20 | int main() 21 | { 22 | char *const program = _PROGRAM; 23 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 24 | 25 | if (-1 == execvp(program, argv)) { 26 | const int error = errno; 27 | printf("errno: %d (%s)\n", error, strerror(error)); 28 | return EXIT_SUCCESS; 29 | } 30 | 31 | return EXIT_FAILURE; 32 | } 33 | -------------------------------------------------------------------------------- /test/cases/intercept/wrapper/shell_commands_intercepted.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: cd %T; %{intercept} --force-wrapper --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_intercepted %t.json count -ge 3 6 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_commands_intercepted.c -o shell_commands_intercepted.1.o 7 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_commands_intercepted.c -o shell_commands_intercepted.2.o 8 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_commands_intercepted.c -o shell_commands_intercepted.3.o 9 | 10 | touch shell_commands_intercepted.c 11 | 12 | $CC -c shell_commands_intercepted.c -o shell_commands_intercepted.1.o; 13 | $CC -c shell_commands_intercepted.c -o shell_commands_intercepted.2.o; 14 | $CC -c shell_commands_intercepted.c -o shell_commands_intercepted.3.o; 15 | -------------------------------------------------------------------------------- /source/libsys/include/libsys/Errors.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include 23 | 24 | namespace sys { 25 | 26 | std::string error_string(int error) noexcept; 27 | } 28 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/execve/failure_prints_errno.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execve 2 | // RUN: %{compile} '-D_PROGRAM="/path/to/not/existing"' -o %t %s 3 | // RUN: %t > %t.without.errno 4 | // RUN: %{intercept} --output %t.json -- %t > %t.with.errno 5 | // RUN: diff %t.with.errno %t.without.errno 6 | // RUN: assert_intercepted %t.json count -eq 1 7 | // RUN: assert_intercepted %t.json contains -program %t 8 | 9 | #include "config.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #if defined HAVE_UNISTD_H 17 | #include 18 | #endif 19 | 20 | extern char **environ; 21 | 22 | int main() 23 | { 24 | char *const program = _PROGRAM; 25 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 26 | 27 | if (-1 == execve(program, argv, environ)) { 28 | const int error = errno; 29 | printf("errno: %d (%s)\n", error, strerror(error)); 30 | return EXIT_SUCCESS; 31 | } 32 | 33 | return EXIT_FAILURE; 34 | } 35 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/execvpe/failure_prints_errno.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execvpe 2 | // RUN: %{compile} '-D_PROGRAM="/path/to/not/existing"' -o %t %s 3 | // RUN: %t > %t.without.errno 4 | // RUN: %{intercept} --output %t.json -- %t > %t.with.errno 5 | // RUN: diff %t.with.errno %t.without.errno 6 | // RUN: assert_intercepted %t.json count -eq 1 7 | // RUN: assert_intercepted %t.json contains -program %t 8 | 9 | #include "config.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #if defined HAVE_UNISTD_H 17 | #include 18 | #endif 19 | 20 | extern char **environ; 21 | 22 | int main() 23 | { 24 | char *const program = _PROGRAM; 25 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 26 | 27 | if (-1 == execve(program, argv, environ)) { 28 | const int error = errno; 29 | printf("errno: %d (%s)\n", error, strerror(error)); 30 | return EXIT_SUCCESS; 31 | } 32 | 33 | return EXIT_FAILURE; 34 | } 35 | -------------------------------------------------------------------------------- /test/cases/compilation/output/multiple_source_build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_compilation %t.json count -eq 3 6 | # RUN: assert_compilation %t.json contains -file %T/multiple_source_build_1.c -directory %T -arguments %{c_compiler} -c -o multiple_source_build multiple_source_build_1.c 7 | # RUN: assert_compilation %t.json contains -file %T/multiple_source_build_2.c -directory %T -arguments %{c_compiler} -c -o multiple_source_build multiple_source_build_2.c 8 | # RUN: assert_compilation %t.json contains -file %T/multiple_source_build_3.c -directory %T -arguments %{c_compiler} -c -o multiple_source_build multiple_source_build_3.c 9 | 10 | echo "int foo() { return 1; }" > multiple_source_build_1.c 11 | echo "int bar() { return 1; }" > multiple_source_build_2.c 12 | echo "int main() { return 0; }" > multiple_source_build_3.c 13 | 14 | $CC -o multiple_source_build multiple_source_build_1.c multiple_source_build_2.c multiple_source_build_3.c 15 | -------------------------------------------------------------------------------- /test/cases/compilation/output/existing_files_only.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | 5 | # RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s -build 6 | # RUN: assert_compilation %t.json count -ge 2 7 | # RUN: assert_compilation %t.json contains -file %T/exists/src/source_1.c -directory %T -arguments %{c_compiler} -c -o exists/src/source_1.o exists/src/source_1.c 8 | # RUN: assert_compilation %t.json contains -file %T/exists/src/source_2.c -directory %T -arguments %{c_compiler} -c -o exists/src/source_2.o exists/src/source_2.c 9 | 10 | mkdir -p exists exists/config 11 | touch exists/config/source_1.c exists/config/source_2.c 12 | $CC -c -o exists/config/source_1.o exists/config/source_1.c 13 | $CC -c -o exists/config/source_2.o exists/config/source_2.c 14 | rm exists/config/source_1.c exists/config/source_2.c 15 | 16 | mkdir -p exists exists/src 17 | touch exists/src/source_1.c exists/src/source_2.c 18 | $CC -c -o exists/src/source_1.o exists/src/source_1.c 19 | $CC -c -o exists/src/source_2.o exists/src/source_2.c 20 | -------------------------------------------------------------------------------- /source/bear/main.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "source/Application.h" 21 | #include "libmain/main.h" 22 | 23 | int main(int argc, char *argv[], char *envp[]) { 24 | return ps::main(argc, argv, envp); 25 | } 26 | -------------------------------------------------------------------------------- /test/cases/intercept/wrapper/shell_commands_with_empty_env.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # XFAIL: * 4 | # REQUIRES: shell 5 | # RUN: cd %T; %{intercept} --force-wrapper --verbose --output %t.json -- env - %{shell} %s 6 | # RUN: assert_intercepted %t.json count -ge 3 7 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_commands_with_empty_env.c -o shell_commands_with_empty_env.1.o 8 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_commands_with_empty_env.c -o shell_commands_with_empty_env.2.o 9 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_commands_with_empty_env.c -o shell_commands_with_empty_env.3.o 10 | 11 | touch shell_commands_with_empty_env.c 12 | 13 | CC=${CC:-cc} 14 | 15 | $CC -c shell_commands_with_empty_env.c -o shell_commands_with_empty_env.1.o 16 | $CC -c shell_commands_with_empty_env.c -o shell_commands_with_empty_env.2.o 17 | $CC -c shell_commands_with_empty_env.c -o shell_commands_with_empty_env.3.o 18 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/execvp2/failure_prints_errno.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_execvP 2 | // RUN: %{compile} '-D_PROGRAM="/path/to/not/existing"' -o %t %s 3 | // RUN: %t > %t.without.errno 4 | // RUN: %{intercept} --output %t.json -- %t > %t.with.errno 5 | // RUN: diff %t.with.errno %t.without.errno 6 | // RUN: assert_intercepted %t.json count -eq 1 7 | // RUN: assert_intercepted %t.json contains -program %t 8 | 9 | #include "config.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #if defined HAVE_UNISTD_H 17 | #include 18 | #endif 19 | 20 | extern char **environ; 21 | 22 | int main() 23 | { 24 | char *const program = _PROGRAM; 25 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 26 | 27 | if (-1 == execvP(program, argv, "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin", environ)) { 28 | const int error = errno; 29 | printf("errno: %d (%s)\n", error, strerror(error)); 30 | return EXIT_SUCCESS; 31 | } 32 | 33 | return EXIT_FAILURE; 34 | } 35 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/posix_spawn/failure_prints_errno.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_posix_spawn 2 | // RUN: %{compile} '-D_PROGRAM="/path/to/not/existing"' -o %t %s 3 | // RUN: %t > %t.without.errno 4 | // RUN: %{intercept} --output %t.json -- %t > %t.with.errno 5 | // RUN: diff %t.with.errno %t.without.errno 6 | // RUN: assert_intercepted %t.json count -eq 1 7 | // RUN: assert_intercepted %t.json contains -program %t 8 | 9 | #include "config.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #if defined HAVE_SPAWN_H 17 | #include 18 | #endif 19 | 20 | extern char **environ; 21 | 22 | int main() 23 | { 24 | char *const program = _PROGRAM; 25 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 26 | 27 | pid_t child; 28 | if (0 != posix_spawn(&child, program, 0, 0, argv, environ)) { 29 | const int error = errno; 30 | printf("errno: %d (%s)\n", error, strerror(error)); 31 | return EXIT_SUCCESS; 32 | } 33 | 34 | return EXIT_FAILURE; 35 | } 36 | -------------------------------------------------------------------------------- /test/cases/compilation/output/flags_filtered_preproc.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_compilation %t.json count -eq 2 6 | # RUN: assert_compilation %t.json contains -file %T/flags_filtered_preproc_1.c -directory %T -arguments %{c_compiler} -c -o flags_filtered_preproc_1.o flags_filtered_preproc_1.c 7 | # RUN: assert_compilation %t.json contains -file %T/flags_filtered_preproc_2.c -directory %T -arguments %{c_compiler} -c -o flags_filtered_preproc_2.o flags_filtered_preproc_2.c 8 | 9 | touch flags_filtered_preproc_1.c flags_filtered_preproc_2.c 10 | 11 | # these shall not be in the output 12 | $CC -c -M -o flags_filtered_preproc_1.d flags_filtered_preproc_1.c; 13 | $CC -c -MM -o flags_filtered_preproc_2.d flags_filtered_preproc_2.c; 14 | 15 | # these shall be in the output 16 | $CC -c -MD -MF flags_filtered_preproc_1.d -o flags_filtered_preproc_1.o flags_filtered_preproc_1.c; 17 | $CC -c -MMD -MF flags_filtered_preproc_2.d -o flags_filtered_preproc_2.o flags_filtered_preproc_2.c; 18 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/posix_spawnp/failure_prints_errno.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_posix_spawnp 2 | // RUN: %{compile} '-D_PROGRAM="/path/to/not/existing"' -o %t %s 3 | // RUN: %t > %t.without.errno 4 | // RUN: %{intercept} --output %t.json -- %t > %t.with.errno 5 | // RUN: diff %t.with.errno %t.without.errno 6 | // RUN: assert_intercepted %t.json count -eq 1 7 | // RUN: assert_intercepted %t.json contains -program %t 8 | 9 | #include "config.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #if defined HAVE_SPAWN_H 17 | #include 18 | #endif 19 | 20 | extern char **environ; 21 | 22 | int main() 23 | { 24 | char *const program = _PROGRAM; 25 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 26 | 27 | pid_t child; 28 | if (0 != posix_spawnp(&child, program, 0, 0, argv, environ)) { 29 | const int error = errno; 30 | printf("errno: %d (%s)\n", error, strerror(error)); 31 | return EXIT_SUCCESS; 32 | } 33 | 34 | return EXIT_FAILURE; 35 | } 36 | -------------------------------------------------------------------------------- /test/cases/intercept/output/shell_commands_with_unicode.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload, shell, dynamic-shell 4 | # RUN: %{intercept} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_intercepted %t.json count -ge 7 6 | # RUN: assert_intercepted %t.json contains -program %{true} 7 | # RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "hi there \"people\"" 8 | # RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "hi again" 9 | # RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "מה שלומך?" 10 | # RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "Как дела?" 11 | # RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "This line might cause an exception in json load" 12 | # RUN: assert_intercepted %t.json contains -arguments %{shell} %s 13 | 14 | $ECHO "hi there \"people\"" 15 | $ECHO "hi again" 16 | $ECHO "מה שלומך?" 17 | $ECHO "Как дела?" 18 | $ECHO "This line might cause an exception in json load" 19 | 20 | $TRUE 21 | -------------------------------------------------------------------------------- /test/cases/intercept/wrapper/shell_commands_intercepted_without_shebang.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: %{shell} %s > %t.sh 5 | # RUN: chmod +x %t.sh 6 | # RUN: cd %T; %{intercept} --force-wrapper --verbose --output %t.json -- %t.sh 7 | # RUN: assert_intercepted %t.json count -ge 3 8 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_commands_intercepted.c -o shell_commands_intercepted.1.o 9 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_commands_intercepted.c -o shell_commands_intercepted.2.o 10 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_commands_intercepted.c -o shell_commands_intercepted.3.o 11 | 12 | cat < %t.sh 5 | # RUN: chmod +x %t.sh 6 | # RUN: cd %T; %{intercept} --force-wrapper --verbose --output %t.json -- %t.sh 7 | # RUN: assert_intercepted %t.json count -ge 3 8 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_commands_intercepted.c -o shell_commands_intercepted.1.o 9 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_commands_intercepted.c -o shell_commands_intercepted.2.o 10 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_commands_intercepted.c -o shell_commands_intercepted.3.o 11 | 12 | cat <. 18 | */ 19 | 20 | #include "libmain/main.h" 21 | #include "report/wrapper/Application.h" 22 | 23 | int main(int argc, char* argv[], char* envp[]) 24 | { 25 | return ps::main(argc, argv, envp); 26 | } 27 | -------------------------------------------------------------------------------- /source/intercept/source/Convert.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "Domain.h" 23 | #include "supervise.pb.h" 24 | 25 | namespace domain { 26 | 27 | Execution from(const rpc::Execution &) noexcept; 28 | rpc::Execution into(const Execution &) noexcept; 29 | } 30 | -------------------------------------------------------------------------------- /test/cases/intercept/wrapper/shell_commands_parallel_intercepted.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: cd %T; %{intercept} --force-wrapper --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_intercepted %t.json count -ge 3 6 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_commands_parallel_intercepted.c -o shell_commands_parallel_intercepted.1.o 7 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_commands_parallel_intercepted.c -o shell_commands_parallel_intercepted.2.o 8 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_commands_parallel_intercepted.c -o shell_commands_parallel_intercepted.3.o 9 | 10 | touch shell_commands_parallel_intercepted.c 11 | 12 | $CC -c shell_commands_parallel_intercepted.c -o shell_commands_parallel_intercepted.1.o & 13 | $CC -c shell_commands_parallel_intercepted.c -o shell_commands_parallel_intercepted.2.o & 14 | $CC -c shell_commands_parallel_intercepted.c -o shell_commands_parallel_intercepted.3.o & 15 | 16 | wait 17 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/popen/success.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_popen 2 | // RUN: %{compile} -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -ge 2 5 | // RUN: assert_intercepted %t.json contains -program %t 6 | // RUN: assert_intercepted %t.json contains -arguments more 7 | 8 | #include 9 | #include 10 | 11 | void 12 | write_data (FILE * stream) 13 | { 14 | int i; 15 | for (i = 0; i < 100; i++) 16 | fprintf (stream, "%d\n", i); 17 | if (ferror (stream)) 18 | { 19 | fprintf (stderr, "Output to stream failed.\n"); 20 | exit (EXIT_FAILURE); 21 | } 22 | } 23 | 24 | int 25 | main (void) 26 | { 27 | FILE *output; 28 | 29 | output = popen ("more", "w"); 30 | if (!output) 31 | { 32 | fprintf (stderr, 33 | "incorrect parameters or too many files.\n"); 34 | return EXIT_FAILURE; 35 | } 36 | write_data (output); 37 | if (pclose (output) != 0) 38 | { 39 | fprintf (stderr, 40 | "Could not run more or other error.\n"); 41 | } 42 | return EXIT_SUCCESS; 43 | } 44 | -------------------------------------------------------------------------------- /source/citnames/source/semantic/ToolCuda.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "ToolGcc.h" 23 | 24 | namespace cs::semantic { 25 | 26 | struct ToolCuda : public ToolGcc { 27 | [[nodiscard]] 28 | bool is_compiler_call(const fs::path& program) const override; 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/signal_inside_build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload, shell, dynamic-shell 4 | # RUN: %{intercept} --verbose --output %t.json -- %{shell} %s --sleep %{sleep} --true %{true} 5 | # RUN: assert_intercepted %t.json count -ge 3 6 | # RUN: assert_intercepted %t.json contains -program %{true} -arguments %{true} 7 | # RUN: assert_intercepted %t.json contains -program %{sleep} -arguments %{sleep} 1 8 | # RUN: assert_intercepted %t.json contains -program %{sleep} -arguments %{sleep} 5 9 | 10 | for i in "$@" 11 | do 12 | case $i in 13 | --sleep) 14 | SLEEP=$2 15 | shift 16 | shift 17 | ;; 18 | --true) 19 | TRUE=$2 20 | shift 21 | shift 22 | ;; 23 | *) 24 | # unknown option 25 | ;; 26 | esac 27 | done 28 | 29 | echo "SLEEP = $SLEEP" 30 | echo "TRUE = $TRUE" 31 | 32 | if [ -z "$SLEEP" ]; then 33 | echo "SLEEP is not defined"; 34 | exit 1; 35 | fi 36 | 37 | if [ -z "$TRUE" ]; then 38 | echo "TRUE is not defined"; 39 | exit 1; 40 | fi 41 | 42 | # do the test 43 | $SLEEP 5 & 44 | $SLEEP 1 45 | kill -15 %1; 46 | wait; 47 | 48 | $TRUE 49 | -------------------------------------------------------------------------------- /source/libsys/include/libsys/Environment.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include 23 | #include 24 | 25 | namespace sys::env { 26 | 27 | using Vars = std::map; 28 | 29 | // Convert an environment array into a map. 30 | Vars from(const char** value); 31 | } 32 | -------------------------------------------------------------------------------- /test/cases/compilation/output/parallel_build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_compilation %t.json count -eq 4 6 | # RUN: assert_compilation %t.json contains -file %T/parallel_build_1.c -directory %T -arguments %{c_compiler} -c -o parallel_build_1.o parallel_build_1.c 7 | # RUN: assert_compilation %t.json contains -file %T/parallel_build_2.c -directory %T -arguments %{c_compiler} -c -o parallel_build_2.o parallel_build_2.c 8 | # RUN: assert_compilation %t.json contains -file %T/parallel_build_3.c -directory %T -arguments %{c_compiler} -c -o parallel_build_3.o parallel_build_3.c 9 | # RUN: assert_compilation %t.json contains -file %T/parallel_build_4.c -directory %T -arguments %{c_compiler} -c -o parallel_build_4.o parallel_build_4.c 10 | 11 | touch parallel_build_1.c parallel_build_2.c parallel_build_3.c parallel_build_4.c 12 | 13 | $CC -c -o parallel_build_1.o parallel_build_1.c & 14 | $CC -c -o parallel_build_2.o parallel_build_2.c & 15 | $CC -c -o parallel_build_3.o parallel_build_3.c & 16 | $CC -c -o parallel_build_4.o parallel_build_4.c & 17 | 18 | wait 19 | 20 | true; 21 | -------------------------------------------------------------------------------- /test/cases/compilation/output/wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_compilation %t.json count -eq 2 6 | # RUN: assert_compilation %t.json contains -file %T/wrapper_1.c -directory %T -arguments %{c_compiler} -c -o wrapper_1.o wrapper_1.c 7 | # RUN: assert_compilation %t.json contains -file %T/wrapper_2.c -directory %T -arguments %{c_compiler} -c -o wrapper_2.o wrapper_2.c 8 | 9 | # RUN: cd %T; %{bear} --verbose --output %t.json --force-wrapper -- %{shell} %s 10 | # RUN: assert_compilation %t.json count -eq 2 11 | # RUN: assert_compilation %t.json contains -file %T/wrapper_1.c -directory %T -arguments %{c_compiler} -c -o wrapper_1.o wrapper_1.c 12 | # RUN: assert_compilation %t.json contains -file %T/wrapper_2.c -directory %T -arguments %{c_compiler} -c -o wrapper_2.o wrapper_2.c 13 | 14 | touch wrapper_1.c wrapper_2.c 15 | 16 | cat > wrapper << EOF 17 | #!/usr/bin/env sh 18 | 19 | exec \$* 20 | EOF 21 | 22 | chmod +x wrapper 23 | 24 | ORIGINAL=$CC 25 | CC=./wrapper 26 | 27 | $CC $ORIGINAL -c -o wrapper_1.o wrapper_1.c; 28 | $CC $ORIGINAL -c -o wrapper_2.o wrapper_2.c; 29 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/signal_outside_build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: preload, shell, dynamic-shell 4 | # RUN: %{shell} -c "%{intercept} --verbose --output %t.json -- %{shell} %s --sleep %{sleep} --true %{true} & %{sleep} 1; kill -15 %1; wait;" 5 | # RUN: assert_intercepted %t.json count -eq 3 6 | # RUN: assert_intercepted %t.json contains -program %{true} 7 | # RUN: assert_intercepted %t.json contains -program %{sleep} -arguments %{sleep} 5 8 | 9 | for i in "$@" 10 | do 11 | case $i in 12 | --sleep) 13 | SLEEP=$2 14 | shift 15 | shift 16 | ;; 17 | --true) 18 | TRUE=$2 19 | shift 20 | shift 21 | ;; 22 | *) 23 | # unknown option 24 | ;; 25 | esac 26 | done 27 | 28 | echo "SLEEP = $SLEEP" 29 | echo "TRUE = $TRUE" 30 | 31 | if [ -z "$SLEEP" ]; then 32 | echo "SLEEP is not defined"; 33 | exit 1; 34 | fi 35 | 36 | if [ -z "$TRUE" ]; then 37 | echo "TRUE is not defined"; 38 | exit 1; 39 | fi 40 | 41 | forward() { 42 | kill -15 $child; 43 | } 44 | 45 | trap forward SIGTERM 46 | 47 | # do the test 48 | $TRUE 49 | $SLEEP 5& 50 | 51 | child=$! 52 | wait $child 53 | -------------------------------------------------------------------------------- /source/libsys/test/ErrorsTest.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "gtest/gtest.h" 21 | 22 | #include "libsys/Errors.h" 23 | 24 | #include 25 | 26 | namespace { 27 | 28 | TEST(errors, ENOENT) 29 | { 30 | auto result = sys::error_string(ENOENT); 31 | 32 | EXPECT_STREQ("No such file or directory", result.data()); 33 | } 34 | } -------------------------------------------------------------------------------- /test/cases/compilation/output/successful_build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_compilation %t.json count -eq 4 6 | # RUN: assert_compilation %t.json contains -file %T/successful_build_1.c -directory %T -arguments %{c_compiler} -c -o successful_build_1.o successful_build_1.c 7 | # RUN: assert_compilation %t.json contains -file %T/successful_build_2.c -directory %T -arguments %{c_compiler} -c -o successful_build_2.o successful_build_2.c 8 | # RUN: assert_compilation %t.json contains -file %T/successful_build_3.c -directory %T -arguments %{cxx_compiler} -c -o successful_build_3.o successful_build_3.c 9 | # RUN: assert_compilation %t.json contains -file %T/successful_build_4.c -directory %T -arguments %{cxx_compiler} -c -o successful_build_4.o successful_build_4.c 10 | 11 | touch successful_build_1.c successful_build_2.c successful_build_3.c successful_build_4.c 12 | 13 | $CC -c -o successful_build_1.o successful_build_1.c; 14 | $CC -c -o successful_build_2.o successful_build_2.c; 15 | $CXX -c -o successful_build_3.o successful_build_3.c; 16 | $CXX -c -o successful_build_4.o successful_build_4.c; 17 | -------------------------------------------------------------------------------- /test/cases/intercept/wrapper/shell_enable_network_proxy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell, cc 4 | 5 | # If an unreachable or an invalid http proxy is set, an error is returned if '--enable-network-proxy' is set 6 | # 7 | # RUN: env http_proxy=http://localhost:9999 %{intercept} --enable-network-proxy --output %t.json -- %{shell} %s 2> %t.stderr 8 | # RUN: grep "failed to connect to all addresses" %t.stderr 9 | # RUN: assert_intercepted %t.json count -eq 0 10 | 11 | # If no http proxy is set, it should run correctly even with '--enable-network-proxy' 12 | # 13 | # RUN: %{intercept} --enable-network-proxy --output %t.json -- %{shell} %s 14 | # RUN: assert_intercepted %t.json count -eq 1 15 | # RUN: assert_intercepted %t.json contains -program %{c_compiler} -arguments %{c_compiler} -c shell_enable_network_proxy.c -o shell_enable_network_proxy.o 16 | 17 | # By default, even with an invalid http proxy set, it should run correctly 18 | # 19 | # RUN: env http_proxy=http://localhost:9999 %{intercept} --output %t.json -- %{shell} 20 | # RUN: assert_intercepted %t.json count -eq 1 21 | 22 | touch shell_enable_network_proxy.c 23 | 24 | $CC -c shell_enable_network_proxy.c -o shell_enable_network_proxy.o 25 | 26 | -------------------------------------------------------------------------------- /source/libsys/include/libsys/Os.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "libresult/Result.h" 23 | #include "libsys/Environment.h" 24 | 25 | #include 26 | 27 | namespace sys::os { 28 | 29 | // Return PATH from environment and fall back to confstr default one. 30 | [[nodiscard]] rust::Result get_path(const sys::env::Vars& env); 31 | } 32 | -------------------------------------------------------------------------------- /source/citnames/source/semantic/Common.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "Semantic.h" 23 | #include "Parsers.h" 24 | 25 | #include "libresult/Result.h" 26 | 27 | namespace cs::semantic { 28 | rust::Result compilation_impl(const FlagsByName& flags, const Execution& execution, 29 | std::function create_argument_list_func, 30 | std::function is_preprocessor_func); 31 | } 32 | -------------------------------------------------------------------------------- /source/citnames/source/semantic/ToolCuda.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "ToolCuda.h" 21 | #include "ToolGcc.h" 22 | 23 | #include 24 | 25 | namespace cs::semantic { 26 | 27 | bool ToolCuda::is_compiler_call(const fs::path& program) const { 28 | static const auto pattern = std::regex(R"(^(nvcc)$)"); 29 | 30 | std::cmatch m; 31 | return std::regex_match(program.filename().c_str(), m, pattern); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/cases/compilation/output/config/filter_compilers.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: %{shell} %s %t 5 | # RUN: cd %T; %{bear} --verbose --output %t.json --config %t/config.json -- %{shell} %t/build.sh 6 | # RUN: assert_compilation %t.json count -eq 2 7 | # RUN: assert_compilation %t.json contains -file %t/source_1.c -directory %T -arguments %{c_compiler} -c %t/source_1.c 8 | # RUN: assert_compilation %t.json contains -file %t/source_2.c -directory %T -arguments %{c_compiler} -c %t/source_2.c 9 | 10 | TEST=$1 11 | 12 | mkdir -p $TEST; 13 | touch $TEST/source_1.c; 14 | touch $TEST/source_2.c; 15 | mkdir -p $TEST/exclude; 16 | touch $TEST/exclude/source_1.cc; 17 | touch $TEST/exclude/source_2.cc; 18 | 19 | cat > "$TEST/build.sh" << EOF 20 | #!/usr/bin/env sh 21 | 22 | \$CC -c $TEST/source_1.c; 23 | \$CC -c $TEST/source_2.c; 24 | \$CXX -c $TEST/exclude/source_1.cc; 25 | \$CXX -c $TEST/exclude/source_2.cc; 26 | EOF 27 | 28 | 29 | cat > "$TEST/config.json" << EOF 30 | { 31 | "compilation": { 32 | "compilers_to_exclude": [ 33 | "$CXX" 34 | ] 35 | }, 36 | "output": { 37 | "content": { 38 | "include_only_existing_source": true 39 | }, 40 | "format": { 41 | "command_as_array": true, 42 | "drop_output_field": true 43 | } 44 | } 45 | } 46 | EOF 47 | -------------------------------------------------------------------------------- /source/intercept/include/intercept/intercept-forward.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2023 by Samu698 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "config.h" 23 | #include "libmain/SubcommandFromArgs.h" 24 | 25 | namespace ic { 26 | 27 | struct Intercept : ps::SubcommandFromArgs { 28 | Intercept(const ps::ApplicationLogConfig&) noexcept; 29 | rust::Result command(const flags::Arguments &args, const char **envp) const override; 30 | 31 | NON_DEFAULT_CONSTRUCTABLE(Intercept) 32 | }; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /source/citnames/include/citnames/citnames-forward.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2023 by Samu698 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "libmain/SubcommandFromArgs.h" 23 | #include "libresult/Result.h" 24 | 25 | namespace cs { 26 | 27 | struct Citnames : ps::SubcommandFromArgs { 28 | Citnames(const ps::ApplicationLogConfig&) noexcept; 29 | 30 | rust::Result command(const flags::Arguments &args, const char **envp) const override; 31 | 32 | NON_DEFAULT_CONSTRUCTABLE(Citnames) 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /source/citnames/source/semantic/ToolIntelFortran.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "Tool.h" 23 | #include "Parsers.h" 24 | 25 | namespace cs::semantic { 26 | 27 | struct ToolIntelFortran : public Tool { 28 | 29 | [[nodiscard]] 30 | rust::Result recognize(const Execution &execution) const override; 31 | 32 | protected: 33 | [[nodiscard]] bool is_compiler_call(const fs::path& program) const; 34 | 35 | static const FlagsByName FLAG_DEFINITION; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /test/cases/compilation/output/config/filter_sources_relative.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: %{shell} %s %t 5 | # RUN: cd %T; %{bear} --verbose --output %t.json --config %t/config.json -- %{shell} %t/build.sh 6 | # RUN: assert_compilation %t.json count -eq 2 7 | # RUN: assert_compilation %t.json contains -file %t/source_1.c -directory %T -arguments %{c_compiler} -c %t/source_1.c 8 | # RUN: assert_compilation %t.json contains -file %t/source_2.c -directory %T -arguments %{c_compiler} -c %t/source_2.c 9 | 10 | TEST=$1 11 | TEST_RELATIVE=$(basename $1) 12 | 13 | mkdir -p $TEST; 14 | touch $TEST/source_1.c; 15 | touch $TEST/source_2.c; 16 | mkdir -p $TEST/exclude; 17 | touch $TEST/exclude/source_1.c; 18 | touch $TEST/exclude/source_2.c; 19 | 20 | cat > "$TEST/build.sh" << EOF 21 | #!/usr/bin/env sh 22 | 23 | \$CC -c $TEST/source_1.c; 24 | \$CC -c $TEST/source_2.c; 25 | \$CC -c $TEST/exclude/source_1.c; 26 | \$CC -c $TEST/exclude/source_2.c; 27 | EOF 28 | 29 | 30 | cat > "$TEST/config.json" << EOF 31 | { 32 | "output": { 33 | "content": { 34 | "include_only_existing_source": true, 35 | "paths_to_exclude": [ 36 | "$TEST_RELATIVE/exclude" 37 | ] 38 | }, 39 | "format": { 40 | "command_as_array": true, 41 | "drop_output_field": true 42 | } 43 | } 44 | } 45 | EOF 46 | -------------------------------------------------------------------------------- /test/cases/compilation/output/config/filter_sources.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: %{shell} %s %t 5 | # RUN: cd %T; %{bear} --verbose --output %t.json --config %t/config.json -- %{shell} %t/build.sh 6 | # RUN: assert_compilation %t.json count -eq 2 7 | # RUN: assert_compilation %t.json contains -file %t/source_1.c -directory %T -arguments %{c_compiler} -c %t/source_1.c 8 | # RUN: assert_compilation %t.json contains -file %t/source_2.c -directory %T -arguments %{c_compiler} -c %t/source_2.c 9 | 10 | TEST=$1 11 | 12 | mkdir -p $TEST; 13 | touch $TEST/source_1.c; 14 | touch $TEST/source_2.c; 15 | mkdir -p $TEST/exclude; 16 | touch $TEST/exclude/source_1.c; 17 | touch $TEST/exclude/source_2.c; 18 | 19 | cat > "$TEST/build.sh" << EOF 20 | #!/usr/bin/env sh 21 | 22 | \$CC -c $TEST/source_1.c; 23 | \$CC -c $TEST/source_2.c; 24 | \$CC -c $TEST/exclude/source_1.c; 25 | \$CC -c $TEST/exclude/source_2.c; 26 | EOF 27 | 28 | 29 | cat > "$TEST/config.json" << EOF 30 | { 31 | "output": { 32 | "content": { 33 | "include_only_existing_source": true, 34 | "paths_to_include": [ 35 | "$TEST" 36 | ], 37 | "paths_to_exclude": [ 38 | "$TEST/exclude" 39 | ] 40 | }, 41 | "format": { 42 | "command_as_array": true, 43 | "drop_output_field": true 44 | } 45 | } 46 | } 47 | EOF 48 | -------------------------------------------------------------------------------- /source/citnames/source/semantic/ToolCrayFtnfe.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "Parsers.h" 23 | #include "Tool.h" 24 | 25 | namespace cs::semantic { 26 | 27 | struct ToolCrayFtnfe : public Tool { 28 | 29 | [[nodiscard]] 30 | rust::Result recognize(const Execution& execution) const override; 31 | 32 | protected: 33 | [[nodiscard]] bool is_compiler_call(const fs::path& program) const; 34 | 35 | static const FlagsByName FLAG_DEFINITION; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /source/intercept/source/report/libexec/std.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | 22 | /** 23 | * To avoid undefined symbol from `libc++.so` or `libstdc++.so` define a 24 | * no-op delete operator. It's safe to not call `free` because we are not 25 | * `malloc` or `new` in this library. 26 | * 27 | * But it's needed since we were declaring a few classes virtual, which 28 | * requires this symbol to be present. 29 | */ 30 | void operator delete(void*, std::size_t) 31 | { } 32 | 33 | void operator delete(void*) 34 | { } 35 | -------------------------------------------------------------------------------- /source/bear/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Create a static library, which is used for unit tests and the final shared library. 2 | add_library(bear_a OBJECT) 3 | target_include_directories(bear_a PUBLIC source/ ../citnames/include/ ../intercept/include/) 4 | target_sources(bear_a 5 | PRIVATE 6 | source/Application.cc 7 | INTERFACE 8 | $ 9 | ) 10 | target_link_libraries(bear_a PUBLIC 11 | main_a 12 | sys_a 13 | flags_a 14 | fmt::fmt 15 | citnames_a 16 | intercept_a 17 | spdlog::spdlog) 18 | 19 | # Create an executable from the sub projects. 20 | add_executable(bear 21 | main.cc 22 | ) 23 | target_link_libraries(bear 24 | bear_a) 25 | 26 | include(GNUInstallDirs) 27 | install(TARGETS bear 28 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 29 | 30 | # Markdown file is the source to the man file. Please modify that and generate 31 | # the man file from it with pandoc. 32 | # 33 | # $ pandoc -s -t man bear.1.md -o bear.1 34 | # 35 | # This is not automated, because pandoc has big dependencies on different OS 36 | # distributions and packaging would require to install those. Which might be 37 | # too much effort to generate a single text file. 38 | 39 | install(FILES man/bear.1 40 | DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) 41 | -------------------------------------------------------------------------------- /source/citnames/source/semantic/ToolClang.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "ToolGcc.h" 23 | 24 | namespace cs::semantic { 25 | 26 | struct ToolClang : public ToolGcc { 27 | 28 | ToolClang() noexcept; 29 | 30 | [[nodiscard]] 31 | rust::Result recognize(const Execution &execution) const override; 32 | 33 | protected: 34 | [[nodiscard]] 35 | bool is_compiler_call(const fs::path &program) const override; 36 | 37 | const FlagsByName flag_definition; 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /source/intercept/source/report/libexec/Environment.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | namespace el::env { 23 | 24 | /** 25 | * Returns the value for the given environment name, from the given 26 | * environment array. 27 | * 28 | * It's a re-implementation of the standard library function.. 29 | * 30 | * @param envp the environment array. 31 | * @param key the name of the environment. 32 | * @return the value of the environment. 33 | */ 34 | const char* get_env_value(const char** envp, const char* key) noexcept; 35 | } 36 | -------------------------------------------------------------------------------- /source/libsys/include/libsys/Path.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "config.h" 23 | #include "libresult/Result.h" 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | namespace fs = std::filesystem; 30 | 31 | namespace sys::path { 32 | 33 | // PATH variable manipulation functions 34 | // 35 | // https://en.wikipedia.org/wiki/PATH_(variable) 36 | std::list split(const std::string &input); 37 | std::string join(const std::list &input); 38 | 39 | rust::Result get_cwd(); 40 | } 41 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/posix_spawnp/success_to_resolve.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_posix_spawnp 2 | // RUN: %{compile} '-D_PROGRAM="echo"' -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -eq 2 5 | // RUN: assert_intercepted %t.json contains -program %t -arguments %t 6 | // RUN: assert_intercepted %t.json contains -arguments echo "hi there" 7 | 8 | #include "config.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #if defined HAVE_SPAWN_H 15 | #include 16 | #endif 17 | 18 | #if defined HAVE_SYS_TYPES_H 19 | #include 20 | #endif 21 | #if defined HAVE_SYS_WAIT_H 22 | #include 23 | #endif 24 | 25 | int main() 26 | { 27 | char *const program = _PROGRAM; 28 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 29 | char *const envp[] = { "THIS=THAT", 0 }; 30 | 31 | pid_t child; 32 | if (0 != posix_spawnp(&child, program, 0, 0, argv, envp)) { 33 | perror("posix_spawn"); 34 | exit(EXIT_FAILURE); 35 | } 36 | 37 | int status; 38 | if (-1 == waitpid(child, &status, 0)) { 39 | perror("wait"); 40 | return EXIT_FAILURE; 41 | } 42 | if (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE) { 43 | fprintf(stderr, "child process has non zero exit code\n"); 44 | return EXIT_FAILURE; 45 | } 46 | return EXIT_SUCCESS; 47 | } 48 | -------------------------------------------------------------------------------- /source/citnames/source/semantic/ToolAny.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "Tool.h" 23 | 24 | namespace cs::semantic { 25 | 26 | class ToolAny : public Tool { 27 | public: 28 | using ToolPtr = std::shared_ptr; 29 | using ToolPtrs = std::list; 30 | 31 | ToolAny(ToolPtrs &&tools, std::list &&to_exclude) noexcept; 32 | 33 | [[nodiscard]] 34 | rust::Result recognize(const Execution &execution) const override; 35 | 36 | private: 37 | ToolPtrs tools_; 38 | std::list to_exclude_; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /source/libsys/include/libsys/Signal.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "config.h" 23 | #include 24 | 25 | namespace sys { 26 | 27 | class Process; 28 | 29 | class SignalForwarder { 30 | public: 31 | explicit SignalForwarder(const Process &child) noexcept; 32 | ~SignalForwarder() noexcept; 33 | 34 | public: 35 | NON_DEFAULT_CONSTRUCTABLE(SignalForwarder) 36 | NON_COPYABLE_NOR_MOVABLE(SignalForwarder) 37 | 38 | private: 39 | pid_t pid_; 40 | using handler_t = void (*)(int); 41 | handler_t handlers_[NSIG]; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/posix_spawn/success.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_posix_spawn 2 | // RUN: %{compile} '-D_PROGRAM="%{echo}"' -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -eq 2 5 | // RUN: assert_intercepted %t.json contains -program %t -arguments %t 6 | // RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "hi there" 7 | 8 | #include "config.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #if defined HAVE_SPAWN_H 15 | #include 16 | #endif 17 | 18 | #if defined HAVE_SYS_TYPES_H 19 | #include 20 | #endif 21 | #if defined HAVE_SYS_WAIT_H 22 | #include 23 | #endif 24 | 25 | int main() 26 | { 27 | char *const program = _PROGRAM; 28 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 29 | char *const envp[] = { "THIS=THAT", 0 }; 30 | 31 | pid_t child; 32 | if (0 != posix_spawn(&child, program, 0, 0, argv, envp)) { 33 | perror("posix_spawn"); 34 | exit(EXIT_FAILURE); 35 | } 36 | 37 | int status; 38 | if (-1 == waitpid(child, &status, 0)) { 39 | perror("wait"); 40 | return EXIT_FAILURE; 41 | } 42 | if (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE) { 43 | fprintf(stderr, "child process has non zero exit code\n"); 44 | return EXIT_FAILURE; 45 | } 46 | return EXIT_SUCCESS; 47 | } 48 | -------------------------------------------------------------------------------- /test/cases/intercept/preload/posix/posix_spawnp/success.c: -------------------------------------------------------------------------------- 1 | // REQUIRES: preload, c_api_posix_spawnp 2 | // RUN: %{compile} '-D_PROGRAM="%{echo}"' -o %t %s 3 | // RUN: %{intercept} --verbose --output %t.json -- %t 4 | // RUN: assert_intercepted %t.json count -eq 2 5 | // RUN: assert_intercepted %t.json contains -program %t -arguments %t 6 | // RUN: assert_intercepted %t.json contains -program %{echo} -arguments %{echo} "hi there" 7 | 8 | #include "config.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #if defined HAVE_SPAWN_H 15 | #include 16 | #endif 17 | 18 | #if defined HAVE_SYS_TYPES_H 19 | #include 20 | #endif 21 | #if defined HAVE_SYS_WAIT_H 22 | #include 23 | #endif 24 | 25 | int main() 26 | { 27 | char *const program = _PROGRAM; 28 | char *const argv[] = { _PROGRAM, "hi there", 0 }; 29 | char *const envp[] = { "THIS=THAT", 0 }; 30 | 31 | pid_t child; 32 | if (0 != posix_spawnp(&child, program, 0, 0, argv, envp)) { 33 | perror("posix_spawn"); 34 | exit(EXIT_FAILURE); 35 | } 36 | 37 | int status; 38 | if (-1 == waitpid(child, &status, 0)) { 39 | perror("wait"); 40 | return EXIT_FAILURE; 41 | } 42 | if (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE) { 43 | fprintf(stderr, "child process has non zero exit code\n"); 44 | return EXIT_FAILURE; 45 | } 46 | return EXIT_SUCCESS; 47 | } 48 | -------------------------------------------------------------------------------- /source/intercept/source/report/libexec/Buffer.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "report/libexec/Array.h" 21 | #include "report/libexec/Buffer.h" 22 | 23 | #include 24 | 25 | namespace el { 26 | 27 | char const* Buffer::store(char const* const input) noexcept 28 | { 29 | if (input == nullptr) 30 | return nullptr; 31 | 32 | const auto input_end = el::array::end(input) + 1; // include the zero element 33 | auto top = el::array::copy(input, input_end, top_, end_); 34 | if (top != nullptr) 35 | std::swap(top_, top); 36 | return top; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Environment:** 20 | - OS name: [e.g. linux] run `uname -s` 21 | - OS version: [e.g. CentOS 7.6] 22 | - OS architecture: [e.g. `x86_64`] run `uname -m` 23 | - Bear version: [e.g. `3.15.0`] 24 | - Bear install method: [e.g. from package] 25 | 26 | **Additional context** 27 | - Can you give us a reference to the project that you are running against this tool? [e.g. No if it's a close source project, but in case of an open source project a link to the sources could be nice.] 28 | - What build tools this project is using? [e.g. GNU make wtih `configure` script] 29 | - What architecture you are trying to compile for? [e.g. cross compiling] 30 | - Could you attach build logs? If you can re-run the command which failed (e.g. `bear -- make`) with extra verbose log switches (e.g. `bear --verbose -- make`) and send the output of it, that would help a lot. 31 | 32 | **Before you send...** 33 | - Have you read the `README.md` file or `man bear`? 34 | - Have you looked what other open issues Bear has? 35 | - Are you sure that the build works without Bear? 36 | -------------------------------------------------------------------------------- /source/citnames/source/semantic/ToolExtendingWrapper.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "ToolGcc.h" 23 | 24 | namespace cs::semantic { 25 | 26 | struct ToolExtendingWrapper : public ToolGcc { 27 | 28 | explicit ToolExtendingWrapper(CompilerWrapper &&compilers_to_recognize) noexcept; 29 | 30 | [[nodiscard]] 31 | bool is_compiler_call(const fs::path& program) const override; 32 | 33 | [[nodiscard]] 34 | rust::Result recognize(const Execution &execution) const override; 35 | 36 | private: 37 | CompilerWrapper compilers_to_recognize_; 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | Thank you for taking the time to contribute! 4 | 5 | ## Reporting bug 6 | 7 | - Please read the documentation, maybe it's a limitation, a known issue of that release. This might also help to clear false expectation from the tool itself, or help you to classify you request not as a bug, but maybe an enhancement. 8 | 9 | - Ensure that the bug was not already reported by searching on GitHub under Issues. 10 | 11 | - If you have not found an open issue addressing the problem, open a new one. Be sure to include a title and clear description, with as much relevant information as possible. You might also attach the output of the tool, this case try to run it with verbose flags. 12 | 13 | - For more detailed information on submitting a bug report and creating an issue, visit our reporting guidelines. 14 | 15 | ## Suggesting enhancements 16 | 17 | - Enhancement suggestions are tracked as GitHub issues. 18 | 19 | - Use a clear and descriptive title for the issue to identify the suggestion. 20 | 21 | - Describe the current behavior and explain which behavior you expected to see instead and why. 22 | 23 | ## Pull Requests 24 | 25 | - Open a new GitHub pull request with the patch. 26 | 27 | - Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable. 28 | 29 | - Think about testability. Please write test(s) for the problem you have fixed. Make sure that existing test are not get broken. 30 | -------------------------------------------------------------------------------- /test/cases/compilation/output/duplicate_entries.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_compilation %t.json count -eq 4 6 | # RUN: assert_compilation %t.json contains -file %T/duplicate_entries_1.c -directory %T -arguments %{c_compiler} -c -o duplicate_entries_1.o duplicate_entries_1.c 7 | # RUN: assert_compilation %t.json contains -file %T/duplicate_entries_2.c -directory %T -arguments %{c_compiler} -c -o duplicate_entries_2.o duplicate_entries_2.c 8 | # RUN: assert_compilation %t.json contains -file %T/duplicate_entries_1.c -directory %T -arguments %{c_compiler} -c -D_FLAG=value -o duplicate_entries_3.o duplicate_entries_1.c 9 | # RUN: assert_compilation %t.json contains -file %T/duplicate_entries_2.c -directory %T -arguments %{c_compiler} -c -D_FLAG=value -o duplicate_entries_4.o duplicate_entries_2.c 10 | 11 | touch duplicate_entries_1.c duplicate_entries_2.c 12 | 13 | $CC -c duplicate_entries_1.c -o duplicate_entries_1.o; 14 | $CC -c duplicate_entries_2.c -o duplicate_entries_2.o; 15 | $CC -c duplicate_entries_1.c -o duplicate_entries_3.o -D_FLAG=value; 16 | $CC -c duplicate_entries_2.c -o duplicate_entries_4.o -D_FLAG=value; 17 | $CC -c duplicate_entries_1.c -o duplicate_entries_1.o; 18 | $CC -c duplicate_entries_2.c -o duplicate_entries_2.o; 19 | $CC -c duplicate_entries_1.c -o duplicate_entries_3.o -D_FLAG=value; 20 | $CC -c duplicate_entries_2.c -o duplicate_entries_4.o -D_FLAG=value; 21 | -------------------------------------------------------------------------------- /source/intercept/source/report/wrapper/EventFactory.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "Domain.h" 23 | 24 | #include "intercept.pb.h" 25 | 26 | namespace wr { 27 | using namespace domain; 28 | 29 | class EventFactory { 30 | public: 31 | EventFactory() noexcept; 32 | ~EventFactory() noexcept = default; 33 | 34 | [[nodiscard]] rpc::Event start(ProcessId pid, ProcessId ppid, const Execution &execution) const; 35 | [[nodiscard]] rpc::Event signal(int number) const; 36 | [[nodiscard]] rpc::Event terminate(int code) const; 37 | 38 | private: 39 | ReporterId rid_; 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /test/config.h.in: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | // header checks 23 | #cmakedefine HAVE_SPAWN_H 24 | #cmakedefine HAVE_UNISTD_H 25 | #cmakedefine HAVE_SYS_WAIT_H 26 | #cmakedefine HAVE_SYS_TYPES_H 27 | 28 | // symbol checks 29 | #cmakedefine HAVE_EXECVE 30 | #cmakedefine HAVE_EXECV 31 | #cmakedefine HAVE_EXECVPE 32 | #cmakedefine HAVE_EXECVP 33 | #cmakedefine HAVE_EXECVP2 34 | #cmakedefine HAVE_EXECT 35 | #cmakedefine HAVE_EXECL 36 | #cmakedefine HAVE_EXECLP 37 | #cmakedefine HAVE_EXECLE 38 | #cmakedefine HAVE_EXECVEAT 39 | #cmakedefine HAVE_FEXECVE 40 | #cmakedefine HAVE_POSIX_SPAWN 41 | #cmakedefine HAVE_POSIX_SPAWNP 42 | #cmakedefine HAVE_POPEN 43 | #cmakedefine HAVE_SYSTEM 44 | -------------------------------------------------------------------------------- /source/libmain/include/libmain/ApplicationLogConfig.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "config.h" 23 | 24 | namespace ps { 25 | 26 | struct ApplicationLogConfig { 27 | ApplicationLogConfig(const char *name, const char *id); 28 | virtual ~ApplicationLogConfig() = default; 29 | 30 | virtual void initForSilent() const; 31 | virtual void initForVerbose() const; 32 | 33 | void record(const char** argv, const char** envp) const; 34 | void context() const; 35 | 36 | NON_DEFAULT_CONSTRUCTABLE(ApplicationLogConfig) 37 | 38 | protected: 39 | const char *name_; 40 | const char *id_; 41 | }; 42 | } 43 | -------------------------------------------------------------------------------- /source/libsys/source/Errors.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "libsys/Errors.h" 21 | 22 | #include "config.h" 23 | 24 | #ifdef HAVE_STRERROR_R 25 | #include 26 | #else 27 | #include 28 | #endif 29 | 30 | namespace sys { 31 | 32 | std::string error_string(const int error) noexcept 33 | { 34 | #ifdef HAVE_STRERROR_R 35 | #if defined(__GLIBC__) && defined(_GNU_SOURCE) 36 | char buffer[256]; 37 | char *const result = ::strerror_r(error, buffer, 255); 38 | return {result}; 39 | #else 40 | char buffer[256]; 41 | ::strerror_r(error, buffer, 255); 42 | return {buffer}; 43 | #endif 44 | #else 45 | return fmt::format("{0}", error); 46 | #endif 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /test/cases/citnames/output/convert_format.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # RUN: cd %T; %{shell} %s %t 4 | # RUN: assert_compilation %t.compilations.json count -eq 1 5 | # RUN: assert_compilation %t.compilations.json contains -file /home/user/broken_build.c -directory /home/user -arguments /usr/bin/gcc -c -o broken_build.o broken_build.c 6 | # RUN: %{citnames} --verbose --input %t.commands.json --output %t.compilations.json --config %t.config.json --append 7 | # RUN: assert_compilation %t.compilations.json count -eq 1 8 | # RUN: assert_compilation %t.compilations.json contains -file /home/user/broken_build.c -directory /home/user -arguments /usr/bin/gcc -c -o broken_build.o broken_build.c 9 | 10 | cat > "$1.config.json" << EOF 11 | { 12 | "compilation": { 13 | "compilers_to_recognize": [ 14 | { 15 | "executable": "/usr/bin/gcc" 16 | }, 17 | { 18 | "executable": "/usr/bin/c++" 19 | } 20 | ] 21 | }, 22 | "output": { 23 | "content": { 24 | "include_only_existing_source": false 25 | }, 26 | "format": { 27 | "command_as_array": false, 28 | "drop_output_field": false 29 | } 30 | } 31 | } 32 | EOF 33 | 34 | cat > "$1.compilations.json" << EOF 35 | [ 36 | { 37 | "arguments": [ 38 | "/usr/bin/gcc", 39 | "-c", 40 | "-o", 41 | "broken_build.o", 42 | "broken_build.c" 43 | ], 44 | "directory": "/home/user", 45 | "file": "/home/user/broken_build.c", 46 | "output": "/home/user/broken_build.o" 47 | } 48 | ] 49 | EOF 50 | 51 | cat > "$1.commands.json" << EOF 52 | EOF 53 | -------------------------------------------------------------------------------- /source/intercept/source/Domain.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | namespace fs = std::filesystem; 30 | 31 | namespace domain { 32 | 33 | using ReporterId = uint64_t; 34 | using ProcessId = uint32_t; 35 | 36 | struct Execution { 37 | fs::path executable; 38 | std::list arguments; 39 | fs::path working_dir; 40 | std::map environment; 41 | }; 42 | 43 | bool operator==(const Execution& lhs, const Execution& rhs); 44 | std::ostream& operator<<(std::ostream&, const Execution&); 45 | 46 | using SessionLocator = std::string; 47 | } 48 | -------------------------------------------------------------------------------- /source/citnames/source/semantic/ToolGcc.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "Tool.h" 23 | #include "Parsers.h" 24 | 25 | namespace cs::semantic { 26 | 27 | struct ToolGcc : public Tool { 28 | 29 | [[nodiscard]] 30 | rust::Result recognize(const Execution &execution) const override; 31 | 32 | protected: 33 | [[nodiscard]] 34 | virtual bool is_compiler_call(const fs::path& program) const; 35 | 36 | [[nodiscard]] 37 | virtual rust::Result compilation(const Execution &execution) const; 38 | 39 | [[nodiscard]] 40 | static rust::Result compilation(const FlagsByName &flags, const Execution &execution); 41 | 42 | static const FlagsByName FLAG_DEFINITION; 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /source/intercept/test/libexec/LinkerMock.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "report/libexec/Linker.h" 23 | 24 | #include "gmock/gmock.h" 25 | 26 | class LinkerMock : public el::Linker { 27 | public: 28 | MOCK_METHOD( 29 | (rust::Result), 30 | execve, 31 | (const char* path, char* const argv[], char* const envp[]), 32 | (const, noexcept, override) 33 | ); 34 | 35 | MOCK_METHOD( 36 | (rust::Result), 37 | posix_spawn, 38 | ( pid_t* pid, 39 | const char* path, 40 | const posix_spawn_file_actions_t* file_actions, 41 | const posix_spawnattr_t* attrp, 42 | char* const argv[], 43 | char* const envp[]), 44 | (const, noexcept, override) 45 | ); 46 | }; 47 | -------------------------------------------------------------------------------- /source/intercept/source/report/libexec/Logger.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | namespace el::log { 23 | 24 | enum Level { 25 | SILENT = 0, 26 | VERBOSE = 1 27 | }; 28 | 29 | // Not MT safe 30 | void set(Level); 31 | 32 | class Logger { 33 | public: 34 | constexpr explicit Logger(const char *name) noexcept; 35 | 36 | ~Logger() noexcept = default; 37 | 38 | void debug(char const *message) const noexcept; 39 | void debug(char const *message, char const *variable) const noexcept; 40 | 41 | void warning(char const *message) const noexcept; 42 | 43 | private: 44 | const char *name_; 45 | }; 46 | 47 | inline constexpr 48 | Logger::Logger(const char *name) noexcept 49 | : name_(name) 50 | { } 51 | } 52 | -------------------------------------------------------------------------------- /source/intercept/test/libexec/ResolverMock.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "report/libexec/Resolver.h" 23 | 24 | #include "gmock/gmock.h" 25 | 26 | class ResolverMock : public el::Resolver { 27 | public: 28 | MOCK_METHOD( 29 | (rust::Result), 30 | from_current_directory, 31 | (std::string_view const &), 32 | (override) 33 | ); 34 | 35 | MOCK_METHOD( 36 | (rust::Result), 37 | from_path, 38 | (std::string_view const &, const char **), 39 | (override) 40 | ); 41 | 42 | MOCK_METHOD( 43 | (rust::Result), 44 | from_search_path, 45 | (std::string_view const &, const char *), 46 | (override) 47 | ); 48 | }; 49 | -------------------------------------------------------------------------------- /source/citnames/source/semantic/Build.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "config.h" 23 | #include "Configuration.h" 24 | #include "semantic/Tool.h" 25 | #include "intercept.grpc.pb.h" 26 | 27 | #include 28 | 29 | namespace cs::semantic { 30 | 31 | // Represents an expert system which can recognize compilation entries from 32 | // command executions. It covers multiple tools and consider omit results 33 | // based on configuration. 34 | class Build { 35 | public: 36 | explicit Build(Compilation cfg) noexcept; 37 | 38 | [[nodiscard]] 39 | rust::Result recognize(const rpc::Event &event) const; 40 | 41 | NON_DEFAULT_CONSTRUCTABLE(Build) 42 | NON_COPYABLE_NOR_MOVABLE(Build) 43 | 44 | private: 45 | std::shared_ptr tools_; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /source/intercept/source/Domain.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "Domain.h" 21 | #include "Convert.h" 22 | 23 | #include 24 | 25 | #include 26 | 27 | namespace domain { 28 | 29 | bool operator==(const Execution &lhs, const Execution &rhs) { 30 | return (lhs.executable == rhs.executable) 31 | && (lhs.arguments == rhs.arguments) 32 | && (lhs.working_dir == rhs.working_dir) 33 | && (lhs.environment == rhs.environment); 34 | } 35 | 36 | std::ostream &operator<<(std::ostream &os, const Execution &rhs) { 37 | const auto rpc = into(rhs); 38 | std::string json; 39 | const auto rc = google::protobuf::util::MessageToJsonString(rpc, &json); 40 | if (rc.ok()) { 41 | os << json; 42 | } 43 | return os; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /source/intercept/source/report/wrapper/EventReporter.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "report/wrapper/EventReporter.h" 21 | 22 | namespace wr { 23 | 24 | EventReporter::EventReporter(const SessionLocator &session_locator) noexcept 25 | : event_factory() 26 | , client(session_locator) 27 | { } 28 | 29 | void EventReporter::report_start(ProcessId pid, const Execution &execution) { 30 | const auto &event = event_factory.start(pid, getppid(), execution); 31 | client.report(event); 32 | } 33 | 34 | void EventReporter::report_wait(const sys::ExitStatus exit_status) { 35 | const auto event = (exit_status.is_signaled()) 36 | ? event_factory.signal(exit_status.signal().value()) 37 | : event_factory.terminate(exit_status.code().value()); 38 | client.report(event); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/cases/compilation/output/config/filter_flags_on_known_compiler.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: %{shell} %s %t 5 | # RUN: cd %T; %{bear} --verbose --output %t.json --config %t/config.json -- %{shell} %t/build.sh 6 | # RUN: assert_compilation %t.json count -eq 2 7 | # RUN: assert_compilation %t.json contains -file %t/source_1.c -directory %T -arguments %{c_compiler} -c -I. %t/source_1.c 8 | # RUN: assert_compilation %t.json contains -file %t/source_2.c -directory %T -arguments %{c_compiler} -c -Werror -I. %t/source_2.c 9 | 10 | # RUN: cd %T; %{bear} --verbose --output %t.json --config %t/config.json --force-wrapper -- %{shell} %t/build.sh 11 | # RUN: assert_compilation %t.json count -eq 2 12 | # RUN: assert_compilation %t.json contains -file %t/source_1.c -directory %T -arguments %{c_compiler} -c -I. %t/source_1.c 13 | # RUN: assert_compilation %t.json contains -file %t/source_2.c -directory %T -arguments %{c_compiler} -c -Werror -I. %t/source_2.c 14 | 15 | TEST=$1 16 | 17 | mkdir $TEST 18 | touch $TEST/source_1.c; 19 | touch $TEST/source_2.c; 20 | 21 | cat > "$TEST/build.sh" << EOF 22 | #!/usr/bin/env sh 23 | 24 | \$CC -c "$TEST/source_1.c" -Wall; 25 | \$CC -c "$TEST/source_2.c" -Werror; 26 | EOF 27 | 28 | 29 | cat > "$TEST/config.json" << EOF 30 | { 31 | "output": { 32 | "content": { 33 | "include_only_existing_source": true 34 | }, 35 | "format": { 36 | "command_as_array": true, 37 | "drop_output_field": true 38 | } 39 | }, 40 | "compilation": { 41 | "compilers_to_recognize": [ 42 | { 43 | "executable": "$CC", 44 | "flags_to_add": ["-I."], 45 | "flags_to_remove": ["-Wall"] 46 | } 47 | ] 48 | } 49 | } 50 | EOF 51 | -------------------------------------------------------------------------------- /source/intercept/source/report/libexec/Session.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | namespace el { 23 | 24 | class Buffer; 25 | 26 | /** 27 | * Represents an intercept session parameter set. 28 | * 29 | * It does not own the memory (of the pointed areas). 30 | */ 31 | struct Session { 32 | char const* reporter = nullptr; 33 | char const* destination = nullptr; 34 | bool verbose = false; 35 | }; 36 | 37 | namespace session { 38 | 39 | // Util method to initialize instance. 40 | void from(Session& session, const char** environment) noexcept; 41 | 42 | // Util method to store the values. 43 | void persist(Session& session, char* begin, char* end) noexcept; 44 | 45 | // Util method to check if session is initialized. 46 | bool is_valid(Session const& session) noexcept; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /source/libsys/source/Guard.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "config.h" 23 | #include 24 | #include 25 | 26 | namespace sys::env { 27 | 28 | // Memory resource guard class. 29 | // 30 | // The OS expect `const char**`, but the caller usually manipulated 31 | // the values in different form. This class let the caller use a more 32 | // convenient form (`std::map`) to use, 33 | // but makes the final `const char**` not leak. 34 | class Guard { 35 | public: 36 | explicit Guard(const std::map &environment); 37 | ~Guard() noexcept; 38 | 39 | [[nodiscard]] const char** data() const; 40 | 41 | public: 42 | NON_DEFAULT_CONSTRUCTABLE(Guard) 43 | NON_COPYABLE_NOR_MOVABLE(Guard) 44 | 45 | private: 46 | const char** data_; 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /source/libmain/include/libmain/ApplicationFromArgs.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "config.h" 23 | #include "libmain/Application.h" 24 | #include "libmain/ApplicationLogConfig.h" 25 | #include "libresult/Result.h" 26 | #include "libflags/Flags.h" 27 | 28 | namespace ps { 29 | 30 | struct ApplicationFromArgs : Application { 31 | explicit ApplicationFromArgs(const ApplicationLogConfig&) noexcept; 32 | 33 | rust::Result command(int argc, const char** argv, const char** envp) const override; 34 | 35 | virtual rust::Result parse(int argc, const char** argv) const = 0; 36 | virtual rust::Result command(const flags::Arguments &args, const char** envp) const = 0; 37 | 38 | NON_DEFAULT_CONSTRUCTABLE(ApplicationFromArgs) 39 | 40 | protected: 41 | ApplicationLogConfig log_config_; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /source/libmain/include/libmain/SubcommandFromArgs.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2023 by Samu698 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "config.h" 23 | #include "libmain/Application.h" 24 | #include "libmain/ApplicationLogConfig.h" 25 | #include "libresult/Result.h" 26 | #include "libflags/Flags.h" 27 | #include 28 | 29 | namespace ps { 30 | 31 | struct SubcommandFromArgs : Subcommand { 32 | explicit SubcommandFromArgs(const char* name, const ApplicationLogConfig&) noexcept; 33 | 34 | bool matches(const flags::Arguments &args); 35 | rust::Result subcommand(const flags::Arguments &args, const char** envp) const override; 36 | 37 | virtual rust::Result command(const flags::Arguments &args, const char** envp) const = 0; 38 | 39 | NON_DEFAULT_CONSTRUCTABLE(SubcommandFromArgs) 40 | 41 | protected: 42 | std::string name_; 43 | ApplicationLogConfig log_config_; 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /source/intercept/source/report/libexec/Environment.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "report/libexec/Environment.h" 21 | #include "report/libexec/Array.h" 22 | 23 | namespace el::env { 24 | 25 | const char* get_env_value(const char **envp, const char *const key) noexcept 26 | { 27 | const size_t key_size = el::array::length(key); 28 | 29 | for (const char** it = envp; *it != nullptr; ++it) { 30 | const char* const current = *it; 31 | // Is the key a prefix of the pointed string? 32 | if (!el::array::equal_n(key, current, key_size)) 33 | continue; 34 | // Is the next character is the equal sign? 35 | if (current[key_size] != '=') 36 | continue; 37 | // It must be the one! Calculate the address of the value. 38 | return current + key_size + 1; 39 | } 40 | return nullptr; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /source/libmain/include/libmain/Application.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "libresult/Result.h" 23 | #include "libflags/Flags.h" 24 | 25 | #include 26 | 27 | namespace ps { 28 | 29 | struct Command { 30 | virtual ~Command() noexcept = default; 31 | 32 | [[nodiscard]] 33 | virtual rust::Result execute() const = 0; 34 | }; 35 | 36 | using CommandPtr = std::unique_ptr; 37 | 38 | struct Application { 39 | virtual ~Application() noexcept = default; 40 | 41 | [[nodiscard]] 42 | virtual rust::Result command(int argc, const char** argv, const char** envp) const = 0; 43 | }; 44 | 45 | struct Subcommand { 46 | virtual ~Subcommand() noexcept = default; 47 | 48 | [[nodiscard]] 49 | virtual rust::Result subcommand(const flags::Arguments &args, const char** envp) const = 0; 50 | }; 51 | } 52 | -------------------------------------------------------------------------------- /source/citnames/source/Citnames.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "Output.h" 23 | #include "semantic/Tool.h" 24 | #include "libmain/SubcommandFromArgs.h" 25 | #include "libresult/Result.h" 26 | #include "libsys/Environment.h" 27 | 28 | #include 29 | #include 30 | 31 | #include "citnames/citnames-forward.h" 32 | 33 | namespace fs = std::filesystem; 34 | 35 | namespace cs { 36 | 37 | struct Arguments { 38 | fs::path input; 39 | fs::path output; 40 | bool append; 41 | }; 42 | 43 | struct Command : ps::Command { 44 | Command(Arguments arguments, cs::Configuration configuration) noexcept; 45 | 46 | [[nodiscard]] rust::Result execute() const override; 47 | 48 | NON_DEFAULT_CONSTRUCTABLE(Command) 49 | NON_COPYABLE_NOR_MOVABLE(Command) 50 | 51 | private: 52 | Arguments arguments_; 53 | cs::Configuration configuration_; 54 | }; 55 | } 56 | -------------------------------------------------------------------------------- /source/citnames/source/semantic/ToolWrapper.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "ToolGcc.h" 23 | 24 | #include 25 | #include 26 | 27 | namespace el { 28 | class Resolver; 29 | } 30 | 31 | namespace cs::semantic { 32 | 33 | struct ToolWrapper : public ToolGcc { 34 | [[nodiscard]] 35 | rust::Result recognize(const Execution &execution) const override; 36 | 37 | // visible for testing 38 | public: 39 | static bool is_ccache_call(const fs::path &program); 40 | static bool is_ccache_query(const std::list &arguments); 41 | 42 | static bool is_distcc_call(const fs::path &program); 43 | static bool is_distcc_query(const std::list &arguments); 44 | 45 | static domain::Execution remove_wrapper(const domain::Execution &); 46 | static domain::Execution remove_wrapper(el::Resolver &, const domain::Execution &); 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /test/cases/compilation/output/flags_filtered_link.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s 5 | # RUN: assert_compilation %t.json count -eq 4 6 | # RUN: assert_compilation %t.json contains -file %T/flags_filtered_link_1.c -directory %T -arguments %{c_compiler} -c -fpic -o flags_filtered_link_1.o flags_filtered_link_1.c 7 | # RUN: assert_compilation %t.json contains -file %T/flags_filtered_link_2.c -directory %T -arguments %{c_compiler} -c -fpic -o flags_filtered_link_2.o flags_filtered_link_2.c 8 | # RUN: assert_compilation %t.json contains -file %T/flags_filtered_link_3.c -directory %T -arguments %{c_compiler} -c -o flags_filtered_link_3 flags_filtered_link_3.c 9 | # RUN: assert_compilation %t.json contains -file %T/flags_filtered_link_4.c -directory %T -arguments %{c_compiler} -c -o flags_filtered_link_4 flags_filtered_link_4.c 10 | 11 | # set up platform specific linker options 12 | PREFIX="foobar"; 13 | if [ $(uname | grep -i "darwin") ]; then 14 | LD_FLAGS="-o lib${PREFIX}.dylib -dynamiclib -install_name @rpath/${PREFIX}" 15 | else 16 | LD_FLAGS="-o lib${PREFIX}.so -shared -Wl,-soname,${PREFIX}" 17 | fi 18 | 19 | # create the source files 20 | echo "int foo() { return 2; }" > flags_filtered_link_1.c; 21 | echo "int bar() { return 2; }" > flags_filtered_link_2.c; 22 | echo "int main() { return 0; }" > flags_filtered_link_3.c; 23 | echo "int main() { return 0; }" > flags_filtered_link_4.c; 24 | 25 | $CC -c -o flags_filtered_link_1.o -fpic flags_filtered_link_1.c; 26 | $CC -c -o flags_filtered_link_2.o -fpic flags_filtered_link_2.c; 27 | $CC ${LD_FLAGS} flags_filtered_link_1.o flags_filtered_link_2.o; 28 | 29 | $CC -o flags_filtered_link_3 -l${PREFIX} -L. flags_filtered_link_3.c; 30 | $CC -o flags_filtered_link_4 -l ${PREFIX} -L . flags_filtered_link_4.c; 31 | -------------------------------------------------------------------------------- /test/cases/citnames/output/relative_paths_converted.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # RUN: cd %T; %{shell} %s %t 4 | # RUN: %{citnames} --verbose --input %t.commands.json --output %t.compilations.json --config %t.config.json 5 | # RUN: assert_compilation %t.compilations.json count -eq 1 6 | # RUN: assert_compilation %t.compilations.json contains -file /home/user/broken_build.c -directory /home/user/build -arguments /usr/bin/wrapper -c -o broken_build.o ../broken_build.c 7 | 8 | cat > "$1.config.json" << EOF 9 | { 10 | "compilation": { 11 | "compilers_to_recognize": [ 12 | { 13 | "executable": "/usr/bin/wrapper" 14 | } 15 | ] 16 | }, 17 | "output": { 18 | "content": { 19 | "include_only_existing_source": false 20 | }, 21 | "format": { 22 | "command_as_array": true, 23 | "drop_output_field": false 24 | } 25 | } 26 | } 27 | EOF 28 | 29 | cat << EOF | tr '\r\n' ' ' > "$1.commands.json" 30 | { 31 | "rid": "13711651845693228889", 32 | "started": { 33 | "execution": { 34 | "executable": "/usr/bin/wrapper", 35 | "arguments": [ 36 | "/usr/bin/wrapper", 37 | "-c", 38 | "-o", 39 | "broken_build.o", 40 | "../broken_build.c" 41 | ], 42 | "working_dir": "/home/user/build", 43 | "environment": { 44 | "PATH": "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin" 45 | } 46 | }, 47 | "pid": 380296, 48 | "ppid":380286 49 | }, 50 | "timestamp": "2021-07-17T02:59:36.338446Z" 51 | } 52 | EOF 53 | 54 | echo "" >> "$1.commands.json" 55 | 56 | cat << EOF | tr '\r\n' ' ' >> "$1.commands.json" 57 | { 58 | "rid": "13711651845693228889", 59 | "terminated": { 60 | "status": "0" 61 | }, 62 | "timestamp": "2021-07-17T02:59:36.344702Z" 63 | } 64 | EOF 65 | 66 | echo "" >> "$1.commands.json" 67 | -------------------------------------------------------------------------------- /test/cases/citnames/exit_code/exit_code_for_success.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # UNSUPPORTED: true 4 | # RUN: cd %T; %{shell} %s %t.commands.json 5 | # RUN: %{citnames} --verbose --input %t.commands.json --output %t.compilations.json 6 | # RUN: assert_compilation %t.compilations.json count -eq 0 7 | 8 | cat > $1 << EOF 9 | { 10 | "context": { 11 | "host_info": { 12 | "_CS_GNU_LIBC_VERSION": "glibc 2.31", 13 | "_CS_GNU_LIBPTHREAD_VERSION": "NPTL 2.31", 14 | "_CS_PATH": "/usr/bin", 15 | "machine": "x86_64", 16 | "release": "5.8.4-200.fc32.x86_64", 17 | "sysname": "Linux", 18 | "version": "#1 SMP Wed Aug 26 22:28:08 UTC 2020" 19 | }, 20 | "intercept": "library preload" 21 | }, 22 | "executions": [ 23 | { 24 | "command": { 25 | "arguments": [ 26 | "/usr/bin/bash", 27 | "/home/user/build.sh" 28 | ], 29 | "environment": { 30 | "PATH": "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin" 31 | }, 32 | "program": "/usr/bin/bash", 33 | "working_dir": "/home/user" 34 | }, 35 | "run": { 36 | "events": [ 37 | { 38 | "at": "2020-09-13T21:13:04.724530Z", 39 | "type": "started" 40 | }, 41 | { 42 | "at": "2020-09-13T21:13:04.798790Z", 43 | "status": 0, 44 | "type": "terminated" 45 | } 46 | ], 47 | "pid": 629422, 48 | "ppid": 629392 49 | } 50 | } 51 | ] 52 | } 53 | EOF 54 | -------------------------------------------------------------------------------- /test/lit.site.cfg.in: -------------------------------------------------------------------------------- 1 | config.test_src_root = '@CMAKE_SOURCE_DIR@' 2 | config.test_bin_root = '@CMAKE_BINARY_DIR@' 3 | 4 | config.substitutions.append(('%{compile}', 'cc -I @CMAKE_CURRENT_BINARY_DIR@')) 5 | 6 | lit_config.load_config(config, '@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg') 7 | 8 | if 'PREFIX_' != 'PREFIX_@HAVE_EXECVE@': 9 | config.available_features.add('c_api_execve') 10 | 11 | if 'PREFIX_' != 'PREFIX_@HAVE_EXECV@': 12 | config.available_features.add('c_api_execv') 13 | 14 | if 'PREFIX_' != 'PREFIX_@HAVE_EXECVPE@': 15 | config.available_features.add('c_api_execvpe') 16 | 17 | if 'PREFIX_' != 'PREFIX_@HAVE_EXECVP@': 18 | config.available_features.add('c_api_execvp') 19 | 20 | if 'PREFIX_' != 'PREFIX_@HAVE_EXECVP2@': 21 | config.available_features.add('c_api_execvP') 22 | 23 | if 'PREFIX_' != 'PREFIX_@HAVE_EXECT@': 24 | config.available_features.add('c_api_exect') 25 | 26 | if 'PREFIX_' != 'PREFIX_@HAVE_EXECL@': 27 | config.available_features.add('c_api_execl') 28 | 29 | if 'PREFIX_' != 'PREFIX_@HAVE_EXECLP@': 30 | config.available_features.add('c_api_execlp') 31 | 32 | if 'PREFIX_' != 'PREFIX_@HAVE_EXECLE@': 33 | config.available_features.add('c_api_execle') 34 | 35 | if 'PREFIX_' != 'PREFIX_@HAVE_EXECVEAT@': 36 | config.available_features.add('c_api_execveat') 37 | 38 | if 'PREFIX_' != 'PREFIX_@HAVE_FEXECVE@': 39 | config.available_features.add('c_api_fexecve') 40 | 41 | if 'PREFIX_' != 'PREFIX_@HAVE_POSIX_SPAWN@': 42 | config.available_features.add('c_api_posix_spawn') 43 | 44 | if 'PREFIX_' != 'PREFIX_@HAVE_POSIX_SPAWNP@': 45 | config.available_features.add('c_api_posix_spawnp') 46 | 47 | if 'PREFIX_' != 'PREFIX_@HAVE_POPEN@': 48 | config.available_features.add('c_api_popen') 49 | 50 | if 'PREFIX_' != 'PREFIX_@HAVE_SYSTEM@': 51 | config.available_features.add('c_api_system') 52 | -------------------------------------------------------------------------------- /source/intercept/source/collect/Reporter.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "collect/db/EventsDatabaseWriter.h" 23 | #include "libflags/Flags.h" 24 | #include "libresult/Result.h" 25 | #include "intercept.pb.h" 26 | 27 | #include 28 | #include 29 | 30 | namespace ic { 31 | 32 | // Responsible to collect executions and persist them into an output file. 33 | class Reporter { 34 | public: 35 | using Ptr = std::shared_ptr; 36 | static rust::Result from(const flags::Arguments &flags); 37 | 38 | void report(const rpc::Event &event); 39 | 40 | public: 41 | explicit Reporter(ic::collect::db::EventsDatabaseWriter::Ptr database); 42 | 43 | ~Reporter() noexcept = default; 44 | 45 | NON_DEFAULT_CONSTRUCTABLE(Reporter) 46 | NON_COPYABLE_NOR_MOVABLE(Reporter) 47 | 48 | private: 49 | ic::collect::db::EventsDatabaseWriter::Ptr database_; 50 | std::mutex mutex_; 51 | }; 52 | } 53 | -------------------------------------------------------------------------------- /source/intercept/source/collect/Intercept.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "config.h" 23 | #include "libmain/SubcommandFromArgs.h" 24 | #include "Session.h" 25 | #include "Reporter.h" 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include "intercept/intercept-forward.h" 32 | 33 | namespace ic { 34 | 35 | struct Command : ps::Command { 36 | 37 | Command(Execution execution, Session::Ptr session, Reporter::Ptr reporter) 38 | : ps::Command() 39 | , execution_(std::move(execution)) 40 | , session_(std::move(session)) 41 | , reporter_(std::move(reporter)) 42 | { } 43 | 44 | [[nodiscard]] rust::Result execute() const override; 45 | 46 | NON_DEFAULT_CONSTRUCTABLE(Command) 47 | NON_COPYABLE_NOR_MOVABLE(Command) 48 | 49 | private: 50 | Execution execution_; 51 | Session::Ptr session_; 52 | Reporter::Ptr reporter_; 53 | }; 54 | } 55 | -------------------------------------------------------------------------------- /test/cases/citnames/output/clang_plugin.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # RUN: cd %T; %{shell} %s %t 4 | # RUN: %{citnames} --verbose --input %t.commands.json --output %t.compilations.json --config %t.config.json 5 | # RUN: assert_compilation %t.compilations.json count -eq 1 6 | # RUN: assert_compilation %t.compilations.json contains -file /home/user/broken_build.c -directory /home/user -arguments /usr/bin/clang -c -Xclang -load -Xclang /path/to/LLVMHello.so -o broken_build.o broken_build.c 7 | 8 | cat > "$1.config.json" << EOF 9 | { 10 | "compilation": { 11 | "compilers_to_recognize": [] 12 | }, 13 | "output": { 14 | "content": { 15 | "include_only_existing_source": false 16 | }, 17 | "format": { 18 | "command_as_array": true, 19 | "drop_output_field": false 20 | } 21 | } 22 | } 23 | EOF 24 | 25 | cat << EOF | tr '\r\n' ' ' > "$1.commands.json" 26 | { 27 | "rid": "13711651845693228889", 28 | "started": { 29 | "execution": { 30 | "executable": "/usr/bin/clang", 31 | "arguments": [ 32 | "/usr/bin/clang", 33 | "-c", 34 | "-o", 35 | "broken_build.o", 36 | "broken_build.c", 37 | "-Xclang", 38 | "-load", 39 | "-Xclang", 40 | "/path/to/LLVMHello.so" 41 | ], 42 | "working_dir": "/home/user", 43 | "environment": { 44 | "PATH": "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin" 45 | } 46 | }, 47 | "pid": 380296, 48 | "ppid":380286 49 | }, 50 | "timestamp": "2021-07-17T02:59:36.338446Z" 51 | } 52 | EOF 53 | 54 | echo "" >> "$1.commands.json" 55 | 56 | cat << EOF | tr '\r\n' ' ' >> "$1.commands.json" 57 | { 58 | "rid": "13711651845693228889", 59 | "terminated": { 60 | "status": "0" 61 | }, 62 | "timestamp": "2021-07-17T02:59:36.344702Z" 63 | } 64 | EOF 65 | 66 | echo "" >> "$1.commands.json" 67 | -------------------------------------------------------------------------------- /test/cases/compilation/output/config/filter_flags.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | # RUN: %{shell} %s %t 5 | # RUN: cd %T; env CC=%t/wrapper %{bear} --verbose --output %t.json --config %t/config.json -- %{shell} %t/build.sh 6 | # RUN: assert_compilation %t.json count -eq 2 7 | # RUN: assert_compilation %t.json contains -file %t/source_1.c -directory %T -arguments %t/wrapper -c -I. %t/source_1.c 8 | # RUN: assert_compilation %t.json contains -file %t/source_2.c -directory %T -arguments %t/wrapper -c -Werror -I. %t/source_2.c 9 | 10 | # RUN: cd %T; env CC=%t/wrapper %{bear} --verbose --output %t.json --config %t/config.json --force-wrapper -- %{shell} %t/build.sh 11 | # RUN: assert_compilation %t.json count -eq 2 12 | # RUN: assert_compilation %t.json contains -file %t/source_1.c -directory %T -arguments %t/wrapper -c -I. %t/source_1.c 13 | # RUN: assert_compilation %t.json contains -file %t/source_2.c -directory %T -arguments %t/wrapper -c -Werror -I. %t/source_2.c 14 | 15 | TEST=$1 16 | 17 | mkdir $TEST 18 | touch $TEST/source_1.c; 19 | touch $TEST/source_2.c; 20 | 21 | cat > "$TEST/build.sh" << EOF 22 | #!/usr/bin/env sh 23 | 24 | \$CC -c "$TEST/source_1.c" -Wall; 25 | \$CC -c "$TEST/source_2.c" -Werror; 26 | EOF 27 | 28 | 29 | cat > "$TEST/config.json" << EOF 30 | { 31 | "output": { 32 | "content": { 33 | "include_only_existing_source": true 34 | }, 35 | "format": { 36 | "command_as_array": true, 37 | "drop_output_field": true 38 | } 39 | }, 40 | "compilation": { 41 | "compilers_to_recognize": [ 42 | { 43 | "executable": "$TEST/wrapper", 44 | "flags_to_add": ["-I."], 45 | "flags_to_remove": ["-Wall"] 46 | } 47 | ] 48 | } 49 | } 50 | EOF 51 | 52 | cat > "$TEST/wrapper" << EOF 53 | #!/usr/bin/env sh 54 | 55 | echo "wrapper \$*" 56 | EOF 57 | 58 | chmod +x "$TEST/wrapper" 59 | -------------------------------------------------------------------------------- /source/intercept/source/collect/SessionLibrary.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "collect/Session.h" 23 | 24 | namespace ic { 25 | 26 | class LibraryPreloadSession : public ic::Session { 27 | public: 28 | LibraryPreloadSession(bool verbose, const std::string_view &library, const std::string_view &executor); 29 | 30 | static rust::Result from(const flags::Arguments&); 31 | 32 | [[nodiscard]] rust::Result resolve(const ic::Execution &execution) const override; 33 | [[nodiscard]] sys::Process::Builder supervise(const ic::Execution &execution) const override; 34 | 35 | NON_DEFAULT_CONSTRUCTABLE(LibraryPreloadSession) 36 | NON_COPYABLE_NOR_MOVABLE(LibraryPreloadSession) 37 | 38 | private: 39 | [[nodiscard]] std::map update(const std::map& env) const; 40 | 41 | private: 42 | bool verbose_; 43 | std::string library_; 44 | std::string executor_; 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /source/intercept/source/Convert.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "Convert.h" 21 | 22 | namespace domain { 23 | 24 | Execution from(const rpc::Execution &input) noexcept { 25 | return Execution{ 26 | fs::path(input.executable()), 27 | std::list(input.arguments().begin(), input.arguments().end()), 28 | fs::path(input.working_dir()), 29 | std::map(input.environment().begin(), input.environment().end()) 30 | }; 31 | } 32 | 33 | rpc::Execution into(const Execution &input) noexcept { 34 | rpc::Execution result; 35 | result.set_executable(input.executable.string()); 36 | result.mutable_arguments()->Reserve(input.arguments.size()); 37 | for (const auto &argument : input.arguments) { 38 | result.add_arguments(argument); 39 | } 40 | result.set_working_dir(input.working_dir); 41 | result.mutable_environment()->insert(input.environment.begin(), input.environment.end()); 42 | return result; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /test/cases/compilation/output/flag/use_cc.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | 5 | # RUN: cd %T; %{bear} --verbose --force-preload --output %t.known.json -- %{shell} %s 6 | # RUN: assert_compilation %t.known.json count -eq 2 7 | # RUN: assert_compilation %t.known.json contains -file %T/use_cc_1.c -directory %T -arguments %{c_compiler} -c -o use_cc_1.o use_cc_1.c 8 | # RUN: assert_compilation %t.known.json contains -file %T/use_cc_2.c -directory %T -arguments %{c_compiler} -c -o use_cc_2.o use_cc_2.c 9 | 10 | # RUN: cd %T; env CC=%{true} %{bear} --verbose --force-preload --output %t.all.json -- %{shell} %s 11 | # RUN: assert_compilation %t.all.json count -eq 2 12 | # RUN: assert_compilation %t.all.json contains -file %T/use_cc_1.c -directory %T -arguments %{true} -c -o use_cc_1.o use_cc_1.c 13 | # RUN: assert_compilation %t.all.json contains -file %T/use_cc_2.c -directory %T -arguments %{true} -c -o use_cc_2.o use_cc_2.c 14 | 15 | # RUN: cd %T; %{bear} --verbose --force-wrapper --output %t.known.json -- %{shell} %s 16 | # RUN: assert_compilation %t.known.json count -eq 2 17 | # RUN: assert_compilation %t.known.json contains -file %T/use_cc_1.c -directory %T -arguments %{c_compiler} -c -o use_cc_1.o use_cc_1.c 18 | # RUN: assert_compilation %t.known.json contains -file %T/use_cc_2.c -directory %T -arguments %{c_compiler} -c -o use_cc_2.o use_cc_2.c 19 | 20 | # RUN: cd %T; env CC=%{true} %{bear} --verbose --force-wrapper --output %t.all.json -- %{shell} %s 21 | # RUN: assert_compilation %t.all.json count -eq 2 22 | # RUN: assert_compilation %t.all.json contains -file %T/use_cc_1.c -directory %T -arguments %{true} -c -o use_cc_1.o use_cc_1.c 23 | # RUN: assert_compilation %t.all.json contains -file %T/use_cc_2.c -directory %T -arguments %{true} -c -o use_cc_2.o use_cc_2.c 24 | 25 | touch use_cc_1.c use_cc_2.c 26 | 27 | $CC -c -o use_cc_1.o use_cc_1.c; 28 | $CC -c -o use_cc_2.o use_cc_2.c; 29 | -------------------------------------------------------------------------------- /source/intercept/source/report/libexec/Linker.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "config.h" 23 | 24 | #include "libresult/Result.h" 25 | 26 | #ifdef HAVE_SPAWN_H 27 | #include 28 | #endif 29 | 30 | namespace el { 31 | 32 | /** 33 | * It is an abstraction of the symbol resolver. 34 | * 35 | * It uses the provided symbol resolver method and cast the result 36 | * to a specific type. 37 | */ 38 | struct Linker { 39 | virtual ~Linker() noexcept = default; 40 | 41 | [[nodiscard]] 42 | virtual rust::Result execve( 43 | const char* path, 44 | char* const argv[], 45 | char* const envp[]) const noexcept; 46 | 47 | [[nodiscard]] 48 | virtual rust::Result posix_spawn( 49 | pid_t* pid, 50 | const char* path, 51 | const posix_spawn_file_actions_t* file_actions, 52 | const posix_spawnattr_t* attrp, 53 | char* const argv[], 54 | char* const envp[]) const noexcept; 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /source/intercept/source/report/wrapper/EventReporter.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "Domain.h" 23 | #include "report/wrapper/EventFactory.h" 24 | #include "report/wrapper/RpcClients.h" 25 | #include "libresult/Result.h" 26 | #include "libsys/Process.h" 27 | 28 | namespace wr { 29 | 30 | /** 31 | * Reports events to the interceptor gRPC service. 32 | * 33 | * Depend on the implementation, it can collect the events and send at the very 34 | * end, or it can send it immediately (sync or async). 35 | */ 36 | class EventReporter { 37 | public: 38 | explicit EventReporter(const wr::SessionLocator& session_locator) noexcept; 39 | ~EventReporter() noexcept = default; 40 | 41 | void report_start(ProcessId pid, const Execution &execution); 42 | void report_wait(sys::ExitStatus exit_status); 43 | 44 | NON_DEFAULT_CONSTRUCTABLE(EventReporter) 45 | NON_COPYABLE_NOR_MOVABLE(EventReporter) 46 | 47 | private: 48 | EventFactory event_factory; 49 | InterceptorClient client; 50 | }; 51 | } 52 | -------------------------------------------------------------------------------- /test/cases/citnames/output/wrapper_flags_extended.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # RUN: cd %T; %{shell} %s %t 4 | # RUN: %{citnames} --verbose --input %t.commands.json --output %t.compilations.json --config %t.config.json 5 | # RUN: assert_compilation %t.compilations.json count -eq 1 6 | # RUN: assert_compilation %t.compilations.json contains -file /home/user/broken_build.c -directory /home/user -arguments /usr/bin/wrapper -c -Dwrapper -o broken_build.o broken_build.c 7 | 8 | cat > "$1.config.json" << EOF 9 | { 10 | "compilation": { 11 | "compilers_to_recognize": [ 12 | { 13 | "executable": "/usr/bin/wrapper", 14 | "flags_to_add": ["-Dwrapper"], 15 | "flags_to_remove": ["-Wall"] 16 | } 17 | ] 18 | }, 19 | "output": { 20 | "content": { 21 | "include_only_existing_source": false 22 | }, 23 | "format": { 24 | "command_as_array": true, 25 | "drop_output_field": false 26 | } 27 | } 28 | } 29 | EOF 30 | 31 | cat << EOF | tr '\r\n' ' ' > "$1.commands.json" 32 | { 33 | "rid": "13711651845693228889", 34 | "started": { 35 | "execution": { 36 | "executable": "/usr/bin/wrapper", 37 | "arguments": [ 38 | "/usr/bin/wrapper", 39 | "-c", 40 | "-o", 41 | "broken_build.o", 42 | "broken_build.c", 43 | "-Wall" 44 | ], 45 | "working_dir": "/home/user", 46 | "environment": { 47 | "PATH": "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin" 48 | } 49 | }, 50 | "pid": 380296, 51 | "ppid":380286 52 | }, 53 | "timestamp": "2021-07-17T02:59:36.338446Z" 54 | } 55 | EOF 56 | 57 | echo "" >> "$1.commands.json" 58 | 59 | cat << EOF | tr '\r\n' ' ' >> "$1.commands.json" 60 | { 61 | "rid": "13711651845693228889", 62 | "terminated": { 63 | "status": "0" 64 | }, 65 | "timestamp": "2021-07-17T02:59:36.344702Z" 66 | } 67 | EOF 68 | 69 | echo "" >> "$1.commands.json" 70 | -------------------------------------------------------------------------------- /source/libmain/source/SubcommandFromArgs.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2023 by Samu698 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "libmain/SubcommandFromArgs.h" 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #ifdef FMT_NEEDS_OSTREAM_FORMATTER 29 | template <> struct fmt::formatter : ostream_formatter {}; 30 | #endif 31 | 32 | namespace ps { 33 | 34 | SubcommandFromArgs::SubcommandFromArgs(const char* name, const ApplicationLogConfig &log_config) noexcept 35 | : Subcommand() 36 | , name_(name) 37 | , log_config_(log_config) 38 | { 39 | log_config_.initForSilent(); 40 | } 41 | 42 | bool SubcommandFromArgs::matches(const flags::Arguments &args) { 43 | return args.as_string(flags::COMMAND).unwrap_or("") == name_; 44 | } 45 | 46 | rust::Result SubcommandFromArgs::subcommand(const flags::Arguments &args, const char** envp) const { 47 | if (args.as_bool(flags::VERBOSE).unwrap_or(false)) { 48 | log_config_.initForVerbose(); 49 | } 50 | 51 | return this->command(args, envp); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /test/cases/compilation/output/flag/use_cxx.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | 5 | # RUN: cd %T; %{bear} --verbose --force-preload --output %t.known.json -- %{shell} %s 6 | # RUN: assert_compilation %t.known.json count -eq 2 7 | # RUN: assert_compilation %t.known.json contains -file %T/use_cxx_1.cc -directory %T -arguments %{cxx_compiler} -c -o use_cxx_1.o use_cxx_1.cc 8 | # RUN: assert_compilation %t.known.json contains -file %T/use_cxx_2.cc -directory %T -arguments %{cxx_compiler} -c -o use_cxx_2.o use_cxx_2.cc 9 | 10 | # RUN: cd %T; env CXX=%{true} %{bear} --verbose --force-preload --output %t.all.json -- %{shell} %s 11 | # RUN: assert_compilation %t.all.json count -eq 2 12 | # RUN: assert_compilation %t.all.json contains -file %T/use_cxx_1.cc -directory %T -arguments %{true} -c -o use_cxx_1.o use_cxx_1.cc 13 | # RUN: assert_compilation %t.all.json contains -file %T/use_cxx_2.cc -directory %T -arguments %{true} -c -o use_cxx_2.o use_cxx_2.cc 14 | 15 | # RUN: cd %T; %{bear} --verbose --force-wrapper --output %t.known.json -- %{shell} %s 16 | # RUN: assert_compilation %t.known.json count -eq 2 17 | # RUN: assert_compilation %t.known.json contains -file %T/use_cxx_1.cc -directory %T -arguments %{cxx_compiler} -c -o use_cxx_1.o use_cxx_1.cc 18 | # RUN: assert_compilation %t.known.json contains -file %T/use_cxx_2.cc -directory %T -arguments %{cxx_compiler} -c -o use_cxx_2.o use_cxx_2.cc 19 | 20 | # RUN: cd %T; env CXX=%{true} %{bear} --verbose --force-wrapper --output %t.all.json -- %{shell} %s 21 | # RUN: assert_compilation %t.all.json count -eq 2 22 | # RUN: assert_compilation %t.all.json contains -file %T/use_cxx_1.cc -directory %T -arguments %{true} -c -o use_cxx_1.o use_cxx_1.cc 23 | # RUN: assert_compilation %t.all.json contains -file %T/use_cxx_2.cc -directory %T -arguments %{true} -c -o use_cxx_2.o use_cxx_2.cc 24 | 25 | touch use_cxx_1.cc use_cxx_2.cc 26 | 27 | $CXX -c -o use_cxx_1.o use_cxx_1.cc; 28 | $CXX -c -o use_cxx_2.o use_cxx_2.cc; 29 | -------------------------------------------------------------------------------- /source/libmain/include/libmain/main.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "libmain/Application.h" 23 | 24 | #include 25 | 26 | namespace ps { 27 | 28 | template 29 | int main(int argc, char* argv[], char* envp[]) { 30 | App app; 31 | auto ptr = reinterpret_cast(&app); 32 | 33 | return ptr->command(argc, 34 | const_cast(argv), 35 | const_cast(envp)) 36 | .and_then([](const ps::CommandPtr &cmd) { 37 | return cmd->execute(); 38 | }) 39 | // print out the result of the run 40 | .on_error([](auto error) { 41 | spdlog::error("failed with: {}", error.what()); 42 | }) 43 | .on_success([](auto status_code) { 44 | spdlog::debug("succeeded with: {}", status_code); 45 | }) 46 | // set the return code from error 47 | .unwrap_or(EXIT_FAILURE); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /source/intercept/source/report/libexec/Session.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "config.h" 21 | #include "report/libexec/Session.h" 22 | 23 | #include "report/libexec/Buffer.h" 24 | #include "report/libexec/Environment.h" 25 | 26 | namespace el::session { 27 | 28 | void from(Session &session, const char **environment) noexcept 29 | { 30 | if (nullptr == environment) 31 | return; 32 | 33 | session.reporter = env::get_env_value(environment, cmd::library::KEY_REPORTER); 34 | session.destination = env::get_env_value(environment, cmd::library::KEY_DESTINATION); 35 | session.verbose = env::get_env_value(environment, cmd::library::KEY_VERBOSE) != nullptr; 36 | } 37 | 38 | void persist(Session &session, char *begin, char *end) noexcept 39 | { 40 | if (!is_valid(session)) 41 | return; 42 | 43 | Buffer buffer(begin, end); 44 | session.reporter = buffer.store(session.reporter); 45 | session.destination = buffer.store(session.destination); 46 | } 47 | 48 | bool is_valid(Session const &session) noexcept 49 | { 50 | return (session.reporter != nullptr && session.destination != nullptr); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /source/intercept/source/collect/db/EventsDatabaseWriter.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "config.h" 23 | #include "libresult/Result.h" 24 | #include "intercept.pb.h" 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | namespace fs = std::filesystem; 32 | 33 | namespace ic::collect::db { 34 | 35 | class EventsDatabaseWriter { 36 | public: 37 | using Ptr = std::shared_ptr; 38 | 39 | [[nodiscard]] static rust::Result create(const fs::path &file); 40 | [[nodiscard]] rust::Result insert_event(const rpc::Event &event); 41 | 42 | public: 43 | explicit EventsDatabaseWriter(fs::path path, int file) noexcept; 44 | ~EventsDatabaseWriter() noexcept; 45 | 46 | NON_DEFAULT_CONSTRUCTABLE(EventsDatabaseWriter) 47 | NON_COPYABLE_NOR_MOVABLE(EventsDatabaseWriter) 48 | 49 | private: 50 | rust::Result to_json(const rpc::Event &event) noexcept; 51 | rust::Result write_to_file(const std::string &content) noexcept; 52 | 53 | private: 54 | fs::path path_; 55 | int file_; 56 | }; 57 | } 58 | -------------------------------------------------------------------------------- /source/intercept/source/collect/Reporter.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "config.h" 21 | #include "collect/Reporter.h" 22 | 23 | #include 24 | 25 | #include 26 | 27 | namespace ic { 28 | 29 | rust::Result Reporter::from(const flags::Arguments& flags) { 30 | return flags 31 | .as_string(cmd::intercept::FLAG_OUTPUT) 32 | .and_then([](auto file) { 33 | return ic::collect::db::EventsDatabaseWriter::create(file); 34 | }) 35 | .map([](auto events) { 36 | return std::make_shared(events); 37 | }); 38 | } 39 | 40 | Reporter::Reporter(ic::collect::db::EventsDatabaseWriter::Ptr database) 41 | : database_(std::move(database)) 42 | , mutex_() 43 | { } 44 | 45 | void Reporter::report(const rpc::Event& event) { 46 | const std::lock_guard lock(mutex_); 47 | 48 | database_->insert_event(event) 49 | .on_error([](auto error) { 50 | spdlog::warn("Writing event into database failed: {} Ignored.", error.what()); 51 | }); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /source/intercept/test/EventFactoryTest.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "gtest/gtest.h" 21 | 22 | #include "report/wrapper/EventFactory.h" 23 | 24 | namespace { 25 | 26 | const wr::ProcessId TEST_PID = 11; 27 | const wr::ProcessId TEST_PPID = 10; 28 | const wr::Execution TEST_EXECUTION = wr::Execution { 29 | fs::path("/usr/bin/ls"), 30 | {"ls", "-la"}, 31 | fs::path("/home/user"), 32 | { {"PATH", "/usr/bin:/usr/sbin"} } 33 | }; 34 | 35 | TEST(event_factory, same_factory_creates_events_with_same_id) 36 | { 37 | wr::EventFactory sut; 38 | auto start = sut.start(TEST_PID, TEST_PPID, TEST_EXECUTION); 39 | auto signal = sut.signal(11); 40 | auto stop = sut.terminate(5); 41 | 42 | EXPECT_EQ(start.rid(), signal.rid()); 43 | EXPECT_EQ(start.rid(), stop.rid()); 44 | } 45 | 46 | TEST(event_factory, different_factory_creates_event_with_different_id) 47 | { 48 | wr::EventFactory sut1; 49 | auto start1 = sut1.start(TEST_PID, TEST_PPID, TEST_EXECUTION); 50 | 51 | wr::EventFactory sut2; 52 | auto start2 = sut2.start(TEST_PID, TEST_PPID, TEST_EXECUTION); 53 | 54 | EXPECT_NE(start1.rid(), start2.rid()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /source/intercept/source/collect/RpcServices.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "intercept.grpc.pb.h" 23 | #include "supervise.grpc.pb.h" 24 | 25 | namespace ic { 26 | 27 | class Reporter; 28 | class Session; 29 | 30 | class SupervisorImpl final : public rpc::Supervisor::Service { 31 | public: 32 | explicit SupervisorImpl(const Session&); 33 | ~SupervisorImpl() override = default; 34 | 35 | grpc::Status Resolve(grpc::ServerContext *context, const rpc::ResolveRequest *request, rpc::ResolveResponse *response) override; 36 | 37 | NON_DEFAULT_CONSTRUCTABLE(SupervisorImpl) 38 | NON_COPYABLE_NOR_MOVABLE(SupervisorImpl) 39 | 40 | private: 41 | const Session &session_; 42 | }; 43 | 44 | class InterceptorImpl final : public rpc::Interceptor::Service { 45 | public: 46 | explicit InterceptorImpl(Reporter&); 47 | ~InterceptorImpl() override = default; 48 | 49 | ::grpc::Status Register(::grpc::ServerContext* context, const rpc::Event* request, google::protobuf::Empty* response) override; 50 | 51 | NON_DEFAULT_CONSTRUCTABLE(InterceptorImpl) 52 | NON_COPYABLE_NOR_MOVABLE(InterceptorImpl) 53 | 54 | private: 55 | Reporter& reporter_; 56 | }; 57 | } 58 | -------------------------------------------------------------------------------- /source/citnames/source/semantic/ToolAny.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "ToolAny.h" 21 | 22 | #include 23 | 24 | namespace cs::semantic { 25 | 26 | ToolAny::ToolAny(ToolAny::ToolPtrs &&tools, std::list &&to_exclude) noexcept 27 | : tools_(tools) 28 | , to_exclude_(to_exclude) 29 | { } 30 | 31 | rust::Result ToolAny::recognize(const domain::Execution &execution) const { 32 | // do different things if the execution is matching one of the nominated compilers. 33 | if (to_exclude_.end() != std::find(to_exclude_.begin(), to_exclude_.end(), execution.executable)) { 34 | return rust::Err(std::runtime_error("The tool is on the exclude list from configuration.")); 35 | } else { 36 | // check if any tool can recognize the execution. 37 | for (const auto &tool : tools_) { 38 | auto result = tool->recognize(execution); 39 | // return if it recognized in any way. 40 | if (Tool::recognized_ok(result) || Tool::recognized_with_error(result)) { 41 | return result; 42 | } 43 | } 44 | } 45 | return rust::Err(std::runtime_error("No tools recognize this execution.")); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /source/intercept/source/report/libexec/Buffer.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "config.h" 23 | 24 | namespace el { 25 | 26 | /** 27 | * Represents a character buffer. 28 | * 29 | * Define helper methods to persist character sequences. The covered 30 | * functionality is not more than a `memcpy` to a static char array. 31 | */ 32 | class Buffer { 33 | public: 34 | /** 35 | * Takes the memory addresses of the buffer. 36 | * 37 | * @param begin of the buffer. 38 | * @param end of the buffer. 39 | */ 40 | Buffer(char* begin, char* end) noexcept; 41 | 42 | ~Buffer() noexcept = default; 43 | 44 | /** 45 | * Copy the input to the buffer. 46 | * 47 | * @param input to persist. 48 | * @return the address of the persisted input. 49 | */ 50 | char const* store(char const* input) noexcept; 51 | 52 | NON_DEFAULT_CONSTRUCTABLE(Buffer) 53 | NON_COPYABLE_NOR_MOVABLE(Buffer) 54 | 55 | private: 56 | char* top_; 57 | char* const end_; 58 | }; 59 | 60 | inline 61 | Buffer::Buffer(char* const begin, char* const end) noexcept 62 | : top_(begin) 63 | , end_(end) 64 | { 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /source/intercept/source/report/wrapper/Application.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "Domain.h" 23 | #include "libmain/Application.h" 24 | #include "libmain/ApplicationLogConfig.h" 25 | #include "libflags/Flags.h" 26 | #include "libresult/Result.h" 27 | 28 | namespace wr { 29 | using namespace domain; 30 | 31 | struct Command : ps::Command { 32 | Command(wr::SessionLocator session, wr::Execution execution) noexcept; 33 | 34 | [[nodiscard]] rust::Result execute() const override; 35 | 36 | NON_DEFAULT_CONSTRUCTABLE(Command) 37 | NON_COPYABLE_NOR_MOVABLE(Command) 38 | 39 | protected: 40 | wr::SessionLocator session_; 41 | wr::Execution execution_; 42 | }; 43 | 44 | struct Application : ps::Application { 45 | Application() noexcept; 46 | rust::Result command(int argc, const char **argv, const char **envp) const override; 47 | 48 | static rust::Result from_envs(int argc, const char **argv, const char **envp); 49 | static rust::Result from_args(const flags::Arguments &args, const char **envp); 50 | static rust::Result parse(int argc, const char **argv) ; 51 | 52 | private: 53 | ps::ApplicationLogConfig const &log_config; 54 | }; 55 | } 56 | -------------------------------------------------------------------------------- /source/libsys/source/Signal.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "libsys/Signal.h" 21 | #include "libsys/Process.h" 22 | 23 | #include 24 | 25 | namespace { 26 | 27 | inline 28 | constexpr bool shall_forward(const int signum) { 29 | switch (signum) { 30 | case SIGKILL: 31 | case SIGCHLD: 32 | return false; 33 | default: 34 | return true; 35 | } 36 | } 37 | 38 | std::set CHILD_PROCESSES; 39 | 40 | void handler(const int signum) { 41 | if (shall_forward(signum)) { 42 | for (const auto pid : CHILD_PROCESSES) { 43 | ::kill(pid, signum); 44 | } 45 | } 46 | } 47 | } 48 | 49 | namespace sys { 50 | 51 | SignalForwarder::SignalForwarder(const Process &child) noexcept 52 | : pid_(child.get_pid()) 53 | , handlers_() 54 | { 55 | CHILD_PROCESSES.insert(pid_); 56 | for (int signum = 1; signum < NSIG; ++signum) { 57 | handlers_[signum] = ::signal(signum, &handler); 58 | } 59 | } 60 | 61 | SignalForwarder::~SignalForwarder() noexcept 62 | { 63 | CHILD_PROCESSES.erase(pid_); 64 | for (int signum = 1; signum < NSIG; ++signum) { 65 | ::signal(signum, handlers_[signum]); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /source/bear/source/Application.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "config.h" 23 | #include "libflags/Flags.h" 24 | #include "libresult/Result.h" 25 | #include "libsys/Environment.h" 26 | #include "libsys/Process.h" 27 | #include "libsys/Signal.h" 28 | #include "libmain/ApplicationFromArgs.h" 29 | 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | namespace bear { 39 | 40 | struct Command : ps::Command { 41 | public: 42 | Command(const sys::Process::Builder& intercept, const sys::Process::Builder& citnames, fs::path output) noexcept; 43 | 44 | [[nodiscard]] rust::Result execute() const override; 45 | 46 | NON_DEFAULT_CONSTRUCTABLE(Command) 47 | NON_COPYABLE_NOR_MOVABLE(Command) 48 | 49 | private: 50 | sys::Process::Builder intercept_; 51 | sys::Process::Builder citnames_; 52 | fs::path output_; 53 | }; 54 | 55 | struct Application : ps::ApplicationFromArgs { 56 | Application(); 57 | 58 | rust::Result parse(int argc, const char **argv) const override; 59 | 60 | rust::Result command(const flags::Arguments &args, const char **envp) const override; 61 | }; 62 | } 63 | -------------------------------------------------------------------------------- /source/intercept/source/collect/Session.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "libflags/Flags.h" 23 | #include "libresult/Result.h" 24 | #include "libsys/Os.h" 25 | #include "libsys/Process.h" 26 | 27 | #include "Domain.h" 28 | #include "Convert.h" 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | namespace ic { 36 | 37 | using namespace domain; 38 | 39 | class Session { 40 | public: 41 | using Ptr = std::shared_ptr; 42 | static rust::Result from(const flags::Arguments &args, const char **envp); 43 | 44 | public: 45 | virtual ~Session() = default; 46 | 47 | [[nodiscard]] virtual rust::Result resolve(const ic::Execution &execution) const = 0; 48 | [[nodiscard]] virtual sys::Process::Builder supervise(const ic::Execution &execution) const = 0; 49 | 50 | [[nodiscard]] rust::Result run(const ic::Execution &execution, const SessionLocator &session_locator); 51 | 52 | protected: 53 | static std::string keep_front_in_path(const std::string& path, const std::string& paths); 54 | static std::string remove_from_path(const std::string& path, const std::string& paths); 55 | 56 | protected: 57 | std::unique_ptr session_locator_; 58 | }; 59 | } 60 | -------------------------------------------------------------------------------- /source/intercept/source/report/wrapper/RpcClients.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "config.h" 23 | #include "Domain.h" 24 | #include "report/wrapper/EventFactory.h" 25 | #include "libresult/Result.h" 26 | 27 | #include 28 | 29 | #include 30 | #include "intercept.grpc.pb.h" 31 | #include "supervise.grpc.pb.h" 32 | 33 | namespace wr { 34 | using namespace domain; 35 | 36 | class SupervisorClient { 37 | public: 38 | explicit SupervisorClient(const wr::SessionLocator& session_locator); 39 | 40 | rust::Result resolve(const wr::Execution &); 41 | 42 | NON_DEFAULT_CONSTRUCTABLE(SupervisorClient) 43 | NON_COPYABLE_NOR_MOVABLE(SupervisorClient) 44 | 45 | private: 46 | std::shared_ptr<::grpc::Channel> channel_; 47 | std::unique_ptr supervisor_; 48 | }; 49 | 50 | class InterceptorClient { 51 | public: 52 | explicit InterceptorClient(const wr::SessionLocator& session_locator); 53 | 54 | rust::Result report(const rpc::Event &); 55 | 56 | NON_DEFAULT_CONSTRUCTABLE(InterceptorClient) 57 | NON_COPYABLE_NOR_MOVABLE(InterceptorClient) 58 | 59 | private: 60 | std::shared_ptr<::grpc::Channel> channel_; 61 | std::unique_ptr interceptor_; 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /source/intercept/proto/supervise.proto: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | syntax = "proto3"; 21 | 22 | package rpc; 23 | 24 | // This represents the executed command itself. Describes all the 25 | // context that the caller was given. And these are the those parameters 26 | // which are essential for re-run the command. 27 | message Execution { 28 | string executable = 1; 29 | repeated string arguments = 2; 30 | string working_dir = 3; 31 | map environment = 4; 32 | } 33 | 34 | // This represents a (remote) supervisor process to set up program execution. 35 | // 36 | // A supervisor process executes a single program in the hope that it can 37 | // get information about the state of the child process. But to decide what 38 | // is the right strategy to intercept the relevant events from the child 39 | // process is done in the external supervisor process. 40 | // 41 | // This interface describes a remote service which can be queried for how to 42 | // execute the child program. Can resolve the executable name or update the 43 | // environment variables. 44 | service Supervisor { 45 | 46 | // Resolve the execution for future child process. 47 | rpc Resolve (ResolveRequest) returns (ResolveResponse) { 48 | } 49 | } 50 | 51 | message ResolveRequest { 52 | Execution execution = 1; 53 | } 54 | 55 | message ResolveResponse { 56 | Execution execution = 1; 57 | } 58 | -------------------------------------------------------------------------------- /source/intercept/source/report/libexec/Resolver.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "config.h" 23 | #include "libresult/Result.h" 24 | 25 | #include 26 | #include 27 | 28 | namespace el { 29 | 30 | /** 31 | * This class implements the logic how the program execution resolves the 32 | * executable path from the system environment. 33 | * 34 | * The resolution logic implemented as a class to be able to unit test 35 | * the code and avoid memory allocation. 36 | */ 37 | class Resolver { 38 | public: 39 | Resolver() noexcept; 40 | virtual ~Resolver() noexcept = default; 41 | 42 | /** 43 | * Resolve the executable from system environments. 44 | * 45 | * @return resolved executable path as absolute path. 46 | */ 47 | [[nodiscard]] 48 | virtual rust::Result from_current_directory(std::string_view const &file); 49 | 50 | [[nodiscard]] 51 | virtual rust::Result from_path(std::string_view const &file, const char **envp); 52 | 53 | [[nodiscard]] 54 | virtual rust::Result from_search_path(std::string_view const &file, const char *search_path); 55 | 56 | NON_COPYABLE_NOR_MOVABLE(Resolver) 57 | 58 | private: 59 | char result_[PATH_MAX]; 60 | }; 61 | } 62 | -------------------------------------------------------------------------------- /test/cases/compilation/output/flag/append.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # REQUIRES: shell 4 | 5 | # RUN: cd %T; %{bear} --verbose --output %t.json -- %{shell} %s -build 6 | # RUN: assert_compilation %t.json count -eq 2 7 | # RUN: assert_compilation %t.json contains -file %T/append/src/source_1.c -directory %T -arguments %{c_compiler} -c -o append/src/source_1.o append/src/source_1.c 8 | # RUN: assert_compilation %t.json contains -file %T/append/src/source_2.c -directory %T -arguments %{c_compiler} -c -o append/src/source_2.o append/src/source_2.c 9 | 10 | # RUN: cd %T; %{bear} --verbose --output %t.json --append -- %{shell} %s -test 11 | # RUN: assert_compilation %t.json count -eq 4 12 | # RUN: assert_compilation %t.json contains -file %T/append/src/source_1.c -directory %T -arguments %{c_compiler} -c -o append/src/source_1.o append/src/source_1.c 13 | # RUN: assert_compilation %t.json contains -file %T/append/src/source_2.c -directory %T -arguments %{c_compiler} -c -o append/src/source_2.o append/src/source_2.c 14 | # RUN: assert_compilation %t.json contains -file %T/append/test/source_1.c -directory %T -arguments %{c_compiler} -c -o append/test/source_1.o append/test/source_1.c 15 | # RUN: assert_compilation %t.json contains -file %T/append/test/source_2.c -directory %T -arguments %{c_compiler} -c -o append/test/source_2.o append/test/source_2.c 16 | 17 | # RUN: cd %T; %{bear} --verbose --output %t.json --append -- %{shell} %s -clean 18 | # RUN: assert_compilation %t.json count -eq 0 19 | 20 | build() 21 | { 22 | mkdir -p append append/src 23 | touch append/src/source_1.c append/src/source_2.c 24 | $CC -c -o append/src/source_1.o append/src/source_1.c 25 | $CC -c -o append/src/source_2.o append/src/source_2.c 26 | } 27 | 28 | verify() 29 | { 30 | mkdir -p append append/test 31 | touch append/test/source_1.c append/test/source_2.c 32 | $CC -c -o append/test/source_1.o append/test/source_1.c 33 | $CC -c -o append/test/source_2.o append/test/source_2.c 34 | } 35 | 36 | clean() 37 | { 38 | rm -rf append 39 | } 40 | 41 | case $1 in 42 | -build) 43 | build 44 | ;; 45 | -test) 46 | verify 47 | ;; 48 | -clean) 49 | clean 50 | ;; 51 | *) 52 | # unknown option 53 | ;; 54 | esac 55 | 56 | true 57 | -------------------------------------------------------------------------------- /source/libmain/source/ApplicationFromArgs.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "libmain/ApplicationFromArgs.h" 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #ifdef FMT_NEEDS_OSTREAM_FORMATTER 27 | template <> struct fmt::formatter : ostream_formatter {}; 28 | #endif 29 | 30 | namespace ps { 31 | 32 | ApplicationFromArgs::ApplicationFromArgs(const ApplicationLogConfig &log_config) noexcept 33 | : Application() 34 | , log_config_(log_config) 35 | { 36 | log_config_.initForSilent(); 37 | } 38 | 39 | rust::Result ApplicationFromArgs::command(int argc, const char** argv, const char** envp) const 40 | { 41 | return parse(argc, argv) 42 | .on_success([this, &argv, &envp](const auto& args) { 43 | if (args.as_bool(flags::VERBOSE).unwrap_or(false)) { 44 | log_config_.initForVerbose(); 45 | } 46 | log_config_.record(argv, envp); 47 | log_config_.context(); 48 | spdlog::debug("arguments parsed: {0}", args); 49 | }) 50 | // if parsing success, we create the main command and execute it. 51 | .and_then([this, &envp](auto args) { 52 | return this->command(args, envp); 53 | }); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /source/intercept/source/collect/SessionWrapper.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2024 by László Nagy 2 | This file is part of Bear. 3 | 4 | Bear is a tool to generate compilation database for clang tooling. 5 | 6 | Bear is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Bear is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "collect/Session.h" 23 | 24 | namespace ic { 25 | 26 | class WrapperSession : public ic::Session { 27 | public: 28 | WrapperSession( 29 | bool verbose, 30 | std::string wrapper_dir, 31 | std::map mapping, 32 | std::map override); 33 | 34 | static rust::Result from(const flags::Arguments &args, const char **envp); 35 | 36 | [[nodiscard]] rust::Result resolve(const ic::Execution &execution) const override; 37 | [[nodiscard]] sys::Process::Builder supervise(const ic::Execution &execution) const override; 38 | 39 | NON_DEFAULT_CONSTRUCTABLE(WrapperSession) 40 | NON_COPYABLE_NOR_MOVABLE(WrapperSession) 41 | 42 | private: 43 | [[nodiscard]] rust::Result resolve(const fs::path &name) const; 44 | [[nodiscard]] std::map update(const std::map& env) const; 45 | [[nodiscard]] std::map set_up(const std::map& env) const; 46 | 47 | private: 48 | bool verbose_; 49 | std::string wrapper_dir_; 50 | std::map mapping_; 51 | std::map override_; 52 | }; 53 | } 54 | --------------------------------------------------------------------------------