diff --git a/analyzer/codechecker_analyzer/analyzer_context.py b/analyzer/codechecker_analyzer/analyzer_context.py index 082c508a20..c6fd5cf700 100644 --- a/analyzer/codechecker_analyzer/analyzer_context.py +++ b/analyzer/codechecker_analyzer/analyzer_context.py @@ -14,11 +14,8 @@ from argparse import ArgumentTypeError import os -import platform import sys -from pathlib import Path - from codechecker_analyzer.arg import analyzer_binary from codechecker_common import logger from codechecker_common.checker_labels import CheckerLabels @@ -67,18 +64,12 @@ def __init__(self): self.__analyzers = {} self.__analyzer_env = None - machine = platform.uname().machine - self.logger_lib_dir_path = os.path.join( - self._data_files_dir_path, 'ld_logger', 'lib', machine) + self._data_files_dir_path, 'ld_logger', 'lib') if not os.path.exists(self.logger_lib_dir_path): self.logger_lib_dir_path = os.path.join( - self._lib_dir_path, - 'codechecker_analyzer', - 'ld_logger', - 'lib', - machine) + self._lib_dir_path, 'codechecker_analyzer', 'ld_logger', 'lib') self.logger_bin = None self.logger_file = None @@ -281,12 +272,8 @@ def path_logger_bin(self): return os.path.join(self._bin_dir_path, 'ld_logger') @property - def logger_lib_path(self): - """ - Returns the absolute path to the logger library. - """ - return str(Path(self.logger_lib_dir_path, - self.logger_lib_name).absolute()) + def path_logger_lib(self): + return self.logger_lib_dir_path @property def logger_lib_name(self): diff --git a/analyzer/codechecker_analyzer/env.py b/analyzer/codechecker_analyzer/env.py index 454a59c54c..83c32b5c18 100644 --- a/analyzer/codechecker_analyzer/env.py +++ b/analyzer/codechecker_analyzer/env.py @@ -27,7 +27,18 @@ def get_log_env(logfile, original_env): new_env[context.env_var_cc_logger_bin] = context.path_logger_bin - new_env['LD_PRELOAD'] = context.logger_lib_path + if 'LD_PRELOAD' in new_env: + new_env['LD_PRELOAD'] = new_env['LD_PRELOAD'] \ + + " " + context.logger_lib_name + else: + new_env['LD_PRELOAD'] = context.logger_lib_name + + try: + original_ld_library_path = new_env['LD_LIBRARY_PATH'] + new_env['LD_LIBRARY_PATH'] = context.path_logger_lib + ':' + \ + original_ld_library_path + except KeyError: + new_env['LD_LIBRARY_PATH'] = context.path_logger_lib # Set ld logger logfile. new_env[context.env_var_cc_logger_file] = logfile diff --git a/analyzer/tests/unit/test_log_parser.py b/analyzer/tests/unit/test_log_parser.py index acab5cb9f8..86ed7bb21d 100644 --- a/analyzer/tests/unit/test_log_parser.py +++ b/analyzer/tests/unit/test_log_parser.py @@ -11,13 +11,11 @@ import json import os -import platform import shutil import tempfile import unittest from codechecker_analyzer.buildlog import log_parser -from codechecker_analyzer.env import get_log_env from codechecker_common.skiplist_handler import SkipListHandler, \ SkipListHandlers from codechecker_common.util import load_json @@ -664,24 +662,3 @@ def test_symlink(self): self.assertEqual(len(build_actions), 3) self.assertEqual(build_action.source, file_c_symdir) - - def test_get_log_env(self): - """ - Test if get_log_env returns the correct environment - with LD_PRELOAD set to pointing to the correct directory - of the ldlogger.so lib. - """ - log_file = os.path.join(self.tmp_dir, "compile_commands.json") - original_env = os.environ.copy() - # If this asset fails, make sure that you don't have LD_PRELOAD set - # in your environment. - self.assertNotIn("LD_PRELOAD", original_env) - env = get_log_env(log_file, original_env) - - # The new environment should contain the LD_PRELOAD variable. - self.assertIn("LD_PRELOAD", env) - - # Make sure that the test running machine architecture is in the - # LD_PRELOAD path. - machine = platform.uname().machine - self.assertTrue(env["LD_PRELOAD"].endswith(machine + "/ldlogger.so")) diff --git a/analyzer/tools/build-logger/README.md b/analyzer/tools/build-logger/README.md index 184feafb58..28b2a5a632 100644 --- a/analyzer/tools/build-logger/README.md +++ b/analyzer/tools/build-logger/README.md @@ -14,7 +14,8 @@ make all test Set the following environment variables: ~~~~~~~ -export LD_PRELOAD=`pwd`/build/lib/`uname -m`/ldlogger.so +export LD_PRELOAD=ldlogger.so +export LD_LIBRARY_PATH=`pwd`/build/lib:$LD_LIBRARY_PATH export CC_LOGGER_GCC_LIKE="gcc:g++:clang:clang++:/cc:c++" # The output compilation JSON file. export CC_LOGGER_FILE=`pwd`/compilation.json diff --git a/analyzer/tools/build-logger/tests/unit/__init__.py b/analyzer/tools/build-logger/tests/unit/__init__.py index 2e2364b141..e87a409252 100644 --- a/analyzer/tools/build-logger/tests/unit/__init__.py +++ b/analyzer/tools/build-logger/tests/unit/__init__.py @@ -106,13 +106,10 @@ def read_actual_json(self) -> str: return fd.read() def get_envvars(self) -> Mapping[str, str]: - machine = platform.uname().machine return { "PATH": os.getenv("PATH"), - "LD_PRELOAD": os.path.join(LOGGER_DIR, - "lib", - machine, - "ldlogger.so"), + "LD_PRELOAD": "ldlogger.so", + "LD_LIBRARY_PATH": os.path.join(LOGGER_DIR, "lib"), "CC_LOGGER_GCC_LIKE": "gcc:g++:clang:clang++:/cc:c++", "CC_LOGGER_FILE": self.logger_file, "CC_LOGGER_DEBUG_FILE": self.logger_debug_file, diff --git a/docs/analyzer/user_guide.md b/docs/analyzer/user_guide.md index b19a90360f..cc7bbf7667 100644 --- a/docs/analyzer/user_guide.md +++ b/docs/analyzer/user_guide.md @@ -756,6 +756,16 @@ object files as input) should be captured. For further details see [this documentation](/analyzer/tools/build-logger/README.md). +If your build tool overrides `LD_LIBRARY_PATH` during the build process, then +`ldlogger.so` will not be found. The best solution is to making sure +that the LD_LIBRARY_PATH is not overridden, only extended. +If this is not possible, you can work around the situation by +specifying the absolute path of the `ldlogger.so` in the `LD_PRELOAD`: + +```sh +LD_PRELOAD=/ld_logger/lib/x86_64/ldlogger.so CodeChecker log -o compile_commands.json -b "make -j2" +``` + #### Change user inside the build command If we change user inside the build command of the CodeChecker log command before the actual compiler invocation, the compilation database will be empty: