fbt: reworked tool path handling (#3105)
* fbt: removed absolute paths from env setup; moved abs paths to cdb tool * fbt: moved tool lookup to cdb emitter * fbt: cdb: quote only tools with spaces in path * typo fix * fbt: pvs: suppress license expiration warning
This commit is contained in:
parent
b98631c633
commit
e1030e7999
@ -29,22 +29,26 @@ which is the name that most clang tools search for by default.
|
|||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#
|
#
|
||||||
|
|
||||||
import json
|
|
||||||
import itertools
|
|
||||||
import fnmatch
|
import fnmatch
|
||||||
|
import itertools
|
||||||
|
import json
|
||||||
|
from shlex import quote
|
||||||
|
|
||||||
import SCons
|
import SCons
|
||||||
|
from SCons.Tool.asm import ASPPSuffixes, ASSuffixes
|
||||||
from SCons.Tool.cxx import CXXSuffixes
|
|
||||||
from SCons.Tool.cc import CSuffixes
|
from SCons.Tool.cc import CSuffixes
|
||||||
from SCons.Tool.asm import ASSuffixes, ASPPSuffixes
|
from SCons.Tool.cxx import CXXSuffixes
|
||||||
|
|
||||||
# TODO FL-3542: Is there a better way to do this than this global? Right now this exists so that the
|
# TODO: (-nofl) 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
|
# 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
|
# 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
|
# access to write all of the files. But it seems clunky. How can the emitter and the scanner
|
||||||
# communicate more gracefully?
|
# communicate more gracefully?
|
||||||
__COMPILATION_DB_ENTRIES = []
|
__COMPILATION_DB_ENTRIES = []
|
||||||
|
|
||||||
|
# We cache the tool path lookups to avoid doing them over and over again.
|
||||||
|
_TOOL_PATH_CACHE = {}
|
||||||
|
|
||||||
|
|
||||||
# We make no effort to avoid rebuilding the entries. Someday, perhaps we could and even
|
# 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.
|
# integrate with the cache, but there doesn't seem to be much call for it.
|
||||||
@ -91,7 +95,7 @@ def make_emit_compilation_DB_entry(comstr):
|
|||||||
__COMPILATIONDB_ENV=env,
|
__COMPILATIONDB_ENV=env,
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO FL-3541: Technically, these next two lines should not be required: it should be fine to
|
# TODO: (-nofl) 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
|
# cache the entries. However, they don't seem to update properly. Since they are quick
|
||||||
# to re-generate disable caching and sidestep this problem.
|
# to re-generate disable caching and sidestep this problem.
|
||||||
env.AlwaysBuild(entry)
|
env.AlwaysBuild(entry)
|
||||||
@ -122,6 +126,17 @@ def compilation_db_entry_action(target, source, env, **kw):
|
|||||||
env=env["__COMPILATIONDB_ENV"],
|
env=env["__COMPILATIONDB_ENV"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# We assume first non-space character is the executable
|
||||||
|
executable = command.split(" ", 1)[0]
|
||||||
|
if not (tool_path := _TOOL_PATH_CACHE.get(executable, None)):
|
||||||
|
tool_path = env.WhereIs(executable) or executable
|
||||||
|
_TOOL_PATH_CACHE[executable] = tool_path
|
||||||
|
# If there are spaces in the executable path, we need to quote it
|
||||||
|
if " " in tool_path:
|
||||||
|
tool_path = quote(tool_path)
|
||||||
|
# Replacing the executable with the full path
|
||||||
|
command = tool_path + command[len(executable) :]
|
||||||
|
|
||||||
entry = {
|
entry = {
|
||||||
"directory": env.Dir("#").abspath,
|
"directory": env.Dir("#").abspath,
|
||||||
"command": command,
|
"command": command,
|
||||||
@ -242,10 +257,7 @@ def generate(env, **kwargs):
|
|||||||
for entry in components_by_suffix:
|
for entry in components_by_suffix:
|
||||||
suffix = entry[0]
|
suffix = entry[0]
|
||||||
builder, base_emitter, command = entry[1]
|
builder, base_emitter, command = entry[1]
|
||||||
|
if emitter := builder.emitter.get(suffix, False):
|
||||||
# Assumes a dictionary emitter
|
|
||||||
emitter = builder.emitter.get(suffix, False)
|
|
||||||
if emitter:
|
|
||||||
# We may not have tools installed which initialize all or any of
|
# We may not have tools installed which initialize all or any of
|
||||||
# cxx, cc, or assembly. If not skip resetting the respective emitter.
|
# cxx, cc, or assembly. If not skip resetting the respective emitter.
|
||||||
builder.emitter[suffix] = SCons.Builder.ListEmitter(
|
builder.emitter[suffix] = SCons.Builder.ListEmitter(
|
||||||
|
|||||||
@ -2,8 +2,6 @@ import subprocess
|
|||||||
|
|
||||||
import gdb
|
import gdb
|
||||||
import objdump
|
import objdump
|
||||||
import shutil
|
|
||||||
|
|
||||||
import strip
|
import strip
|
||||||
from SCons.Action import _subproc
|
from SCons.Action import _subproc
|
||||||
from SCons.Errors import StopError
|
from SCons.Errors import StopError
|
||||||
@ -13,20 +11,25 @@ from SCons.Tool import ar, asm, gcc, gnulink, gxx
|
|||||||
def prefix_commands(env, command_prefix, cmd_list):
|
def prefix_commands(env, command_prefix, cmd_list):
|
||||||
for command in cmd_list:
|
for command in cmd_list:
|
||||||
if command in env:
|
if command in env:
|
||||||
env[command] = shutil.which(command_prefix + env[command])
|
prefixed_binary = command_prefix + env[command]
|
||||||
|
if not env.WhereIs(prefixed_binary):
|
||||||
|
raise StopError(
|
||||||
|
f"Toolchain binary {prefixed_binary} not found in PATH."
|
||||||
|
)
|
||||||
|
env.Replace(**{command: prefixed_binary})
|
||||||
|
|
||||||
|
|
||||||
def _get_tool_version(env, tool):
|
def _get_tool_version(env, tool):
|
||||||
verstr = "version unknown"
|
verstr = "version unknown"
|
||||||
proc = _subproc(
|
proc = _subproc(
|
||||||
env,
|
env,
|
||||||
env.subst("${%s} --version" % tool),
|
[env.subst("${%s}" % tool), "--version"],
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr="devnull",
|
stderr="devnull",
|
||||||
stdin="devnull",
|
stdin="devnull",
|
||||||
universal_newlines=True,
|
universal_newlines=True,
|
||||||
error="raise",
|
error="raise",
|
||||||
shell=True,
|
shell=False,
|
||||||
)
|
)
|
||||||
if proc:
|
if proc:
|
||||||
verstr = proc.stdout.readline()
|
verstr = proc.stdout.readline()
|
||||||
|
|||||||
@ -48,6 +48,7 @@ def generate(env):
|
|||||||
"@.pvsoptions",
|
"@.pvsoptions",
|
||||||
"-j${PVSNCORES}",
|
"-j${PVSNCORES}",
|
||||||
# "--incremental", # kinda broken on PVS side
|
# "--incremental", # kinda broken on PVS side
|
||||||
|
"--disableLicenseExpirationCheck",
|
||||||
],
|
],
|
||||||
PVSCONVOPTIONS=[
|
PVSCONVOPTIONS=[
|
||||||
"-a",
|
"-a",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user