From 62e9589851547c563844cc828eeafb4e18e2f15c Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Sun, 26 Mar 2023 14:36:51 -0600 Subject: [PATCH] Use the built-in SCons "compile_db" tool --- platformio/builder/main.py | 9 +- platformio/builder/tools/compilation_db.py | 224 --------------------- 2 files changed, 8 insertions(+), 225 deletions(-) delete mode 100644 platformio/builder/tools/compilation_db.py diff --git a/platformio/builder/main.py b/platformio/builder/main.py index 844118ed..f80435f2 100644 --- a/platformio/builder/main.py +++ b/platformio/builder/main.py @@ -30,7 +30,7 @@ from SCons.Script import Variables # pylint: disable=import-error from platformio import app, compat, fs from platformio.platform.base import PlatformBase -from platformio.proc import get_pythonexe_path +from platformio.proc import get_pythonexe_path, where_is_program from platformio.project.helpers import get_project_dir AllowSubstExceptions(NameError) @@ -209,6 +209,13 @@ if env.get("SIZETOOL") and not ( Default("checkprogsize") if "compiledb" in COMMAND_LINE_TARGETS: + # Resolve absolute path of toolchain + for cmd in ("CC", "CXX", "AS"): + if cmd not in env: + continue + if os.path.isabs(env[cmd]): + continue + env[cmd] = where_is_program(env.subst("$%s" % cmd), env.subst("${ENV['PATH']}")) env.Alias("compiledb", env.CompilationDatabase("$COMPILATIONDB_PATH")) # Print configured protocols diff --git a/platformio/builder/tools/compilation_db.py b/platformio/builder/tools/compilation_db.py deleted file mode 100644 index 9fa11c86..00000000 --- a/platformio/builder/tools/compilation_db.py +++ /dev/null @@ -1,224 +0,0 @@ -# Copyright (c) 2014-present PlatformIO -# Copyright 2020 MongoDB Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -# pylint: disable=unused-argument, protected-access, unused-variable, import-error -# Original: https://github.com/mongodb/mongo/blob/master/site_scons/site_tools/compilation_db.py - -import itertools -import json -import os - -import SCons - -from platformio.builder.tools.piobuild import SRC_ASM_EXT, SRC_C_EXT, SRC_CXX_EXT -from platformio.proc import where_is_program - -# Implements the ability for SCons to emit a compilation database for the MongoDB project. See -# http://clang.llvm.org/docs/JSONCompilationDatabase.html for details on what a compilation -# database is, and why you might want one. The only user visible entry point here is -# 'env.CompilationDatabase'. This method takes an optional 'target' to name the file that -# should hold the compilation database, otherwise, the file defaults to compile_commands.json, -# which is the name that most clang tools search for by default. - -# Is there a better way to do this than this global? Right now this exists so that the -# emitter we add can record all of the things it emits, so that the scanner for the top level -# compilation database can access the complete list, and also so that the writer has easy -# access to write all of the files. But it seems clunky. How can the emitter and the scanner -# communicate more gracefully? -__COMPILATION_DB_ENTRIES = [] - - -# We make no effort to avoid rebuilding the entries. Someday, perhaps we could and even -# integrate with the cache, but there doesn't seem to be much call for it. -class __CompilationDbNode(SCons.Node.Python.Value): - def __init__(self, value): - SCons.Node.Python.Value.__init__(self, value) - self.Decider(changed_since_last_build_node) - - -def changed_since_last_build_node(*args, **kwargs): - """Dummy decider to force always building""" - return True - - -def makeEmitCompilationDbEntry(comstr): - """ - Effectively this creates a lambda function to capture: - * command line - * source - * target - :param comstr: unevaluated command line - :return: an emitter which has captured the above - """ - user_action = SCons.Action.Action(comstr) - - def EmitCompilationDbEntry(target, source, env): - """ - This emitter will be added to each c/c++ object build to capture the info needed - for clang tools - :param target: target node(s) - :param source: source node(s) - :param env: Environment for use building this node - :return: target(s), source(s) - """ - - # Resolve absolute path of toolchain - for cmd in ("CC", "CXX", "AS"): - if cmd not in env: - continue - if os.path.isabs(env[cmd]): - continue - env[cmd] = where_is_program( - env.subst("$%s" % cmd), env.subst("${ENV['PATH']}") - ) - - dbtarget = __CompilationDbNode(source) - - entry = env.__COMPILATIONDB_Entry( - target=dbtarget, - source=[], - __COMPILATIONDB_UTARGET=target, - __COMPILATIONDB_USOURCE=source, - __COMPILATIONDB_UACTION=user_action, - __COMPILATIONDB_ENV=env, - ) - - # Technically, these next two lines should not be required: it should be fine to - # cache the entries. However, they don't seem to update properly. Since they are quick - # to re-generate disable caching and sidestep this problem. - env.AlwaysBuild(entry) - env.NoCache(entry) - - __COMPILATION_DB_ENTRIES.append(dbtarget) - - return target, source - - return EmitCompilationDbEntry - - -def CompilationDbEntryAction(target, source, env, **kw): - """ - Create a dictionary with evaluated command line, target, source - and store that info as an attribute on the target - (Which has been stored in __COMPILATION_DB_ENTRIES array - :param target: target node(s) - :param source: source node(s) - :param env: Environment for use building this node - :param kw: - :return: None - """ - - command = env["__COMPILATIONDB_UACTION"].strfunction( - target=env["__COMPILATIONDB_UTARGET"], - source=env["__COMPILATIONDB_USOURCE"], - env=env["__COMPILATIONDB_ENV"], - ) - - entry = { - "directory": env.Dir("#").abspath, - "command": command, - "file": str(env["__COMPILATIONDB_USOURCE"][0]), - } - - target[0].write(entry) - - -def WriteCompilationDb(target, source, env): - entries = [] - - for s in __COMPILATION_DB_ENTRIES: - item = s.read() - item["file"] = os.path.abspath(item["file"]) - entries.append(item) - - with open(str(target[0]), mode="w", encoding="utf8") as target_file: - json.dump( - entries, target_file, sort_keys=True, indent=4, separators=(",", ": ") - ) - - -def ScanCompilationDb(node, env, path): - return __COMPILATION_DB_ENTRIES - - -def generate(env, **kwargs): - static_obj, shared_obj = SCons.Tool.createObjBuilders(env) - - env["COMPILATIONDB_COMSTR"] = kwargs.get( - "COMPILATIONDB_COMSTR", "Building compilation database $TARGET" - ) - - components_by_suffix = itertools.chain( - itertools.product( - [".%s" % ext for ext in SRC_C_EXT], - [ - (static_obj, SCons.Defaults.StaticObjectEmitter, "$CCCOM"), - (shared_obj, SCons.Defaults.SharedObjectEmitter, "$SHCCCOM"), - ], - ), - itertools.product( - [".%s" % ext for ext in SRC_CXX_EXT], - [ - (static_obj, SCons.Defaults.StaticObjectEmitter, "$CXXCOM"), - (shared_obj, SCons.Defaults.SharedObjectEmitter, "$SHCXXCOM"), - ], - ), - itertools.product( - [".%s" % ext for ext in SRC_ASM_EXT], - [(static_obj, SCons.Defaults.StaticObjectEmitter, "$ASCOM")], - ), - ) - - for entry in components_by_suffix: - suffix = entry[0] - builder, base_emitter, command = entry[1] - - # Assumes a dictionary emitter - emitter = builder.emitter[suffix] - builder.emitter[suffix] = SCons.Builder.ListEmitter( - [emitter, makeEmitCompilationDbEntry(command)] - ) - - env["BUILDERS"]["__COMPILATIONDB_Entry"] = SCons.Builder.Builder( - action=SCons.Action.Action(CompilationDbEntryAction, None), - ) - - env["BUILDERS"]["__COMPILATIONDB_Database"] = SCons.Builder.Builder( - action=SCons.Action.Action(WriteCompilationDb, "$COMPILATIONDB_COMSTR"), - target_scanner=SCons.Scanner.Scanner( - function=ScanCompilationDb, node_class=None - ), - ) - - def CompilationDatabase(env, target): - result = env.__COMPILATIONDB_Database(target=target, source=[]) - - env.AlwaysBuild(result) - env.NoCache(result) - - return result - - env.AddMethod(CompilationDatabase, "CompilationDatabase") - - -def exists(env): - return True