yacc.py (SCons-4.3.0) | : | yacc.py (SCons-4.4.0) | ||
---|---|---|---|---|
skipping to change at line 26 | skipping to change at line 26 | |||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY | |||
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE | # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE | |||
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
"""Tool-specific initialization for yacc. | """Tool-specific initialization for yacc. | |||
This tool should support multiple yacc implementations, | ||||
but is in actuality biased towards GNU Bison. | ||||
There normally shouldn't be any need to import this module directly. | There normally shouldn't be any need to import this module directly. | |||
It will usually be imported through the generic SCons.Tool.Tool() | It will usually be imported through the generic SCons.Tool.Tool() | |||
selection method. | selection method. | |||
""" | """ | |||
import os.path | import os.path | |||
import sys | import sys | |||
from typing import Optional | ||||
import SCons.Defaults | import SCons.Defaults | |||
import SCons.Tool | import SCons.Tool | |||
import SCons.Util | ||||
import SCons.Warnings | import SCons.Warnings | |||
from SCons.Platform.mingw import MINGW_DEFAULT_PATHS | from SCons.Platform.mingw import MINGW_DEFAULT_PATHS | |||
from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS | from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS | |||
from SCons.Platform.win32 import CHOCO_DEFAULT_PATH | from SCons.Platform.win32 import CHOCO_DEFAULT_PATH | |||
from SCons.Util import CLVar, to_String | ||||
DEFAULT_PATHS = CHOCO_DEFAULT_PATH + MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS | ||||
YaccAction = SCons.Action.Action("$YACCCOM", "$YACCCOMSTR") | YaccAction = SCons.Action.Action("$YACCCOM", "$YACCCOMSTR") | |||
if sys.platform == 'win32': | if sys.platform == 'win32': | |||
BINS = ['bison', 'yacc', 'win_bison'] | BINS = ['bison', 'yacc', 'win_bison'] | |||
else: | else: | |||
BINS = ["bison", "yacc"] | BINS = ["bison", "yacc"] | |||
def _yaccEmitter(target, source, env, ysuf, hsuf): | def _yaccEmitter(target, source, env, ysuf, hsuf) -> tuple: | |||
yaccflags = env.subst("$YACCFLAGS", target=target, source=source) | """Adds extra files generated by yacc program to target list.""" | |||
flags = SCons.Util.CLVar(yaccflags) | ||||
targetBase, targetExt = os.path.splitext(SCons.Util.to_String(target[0])) | yaccflags = env.subst_list("$YACCFLAGS", target=target, source=source) | |||
flags = yaccflags[0] | ||||
targetBase, targetExt = os.path.splitext(to_String(target[0])) | ||||
if '.ym' in ysuf: # If using Objective-C | if '.ym' in ysuf: # If using Objective-C | |||
target = [targetBase + ".m"] # the extension is ".m". | target = [targetBase + ".m"] # the extension is ".m". | |||
# If -d is specified on the command line, yacc will emit a .h | # If -d is specified on the command line, yacc will emit a .h | |||
# or .hpp file with the same name as the .c or .cpp output file. | # or .hpp file with the same name as the .c or .cpp output file. | |||
if '-d' in flags: | if '-d' in flags: | |||
target.append(targetBase + env.subst(hsuf, target=target, source=source) ) | target.append(targetBase + env.subst(hsuf, target=target, source=source) ) | |||
# If -g is specified on the command line, yacc will emit a .vcg | # If -g is specified on the command line, yacc will emit a .vcg | |||
# file with the same base name as the .y, .yacc, .ym or .yy file. | # file with the same base name as the .y, .yacc, .ym or .yy file. | |||
if "-g" in flags: | if "-g" in flags: | |||
base, ext = os.path.splitext(SCons.Util.to_String(source[0])) | base, ext = os.path.splitext(to_String(source[0])) | |||
target.append(base + env.subst("$YACCVCGFILESUFFIX")) | target.append(base + env.subst("$YACCVCGFILESUFFIX")) | |||
# If -v is specified yacc will create the output debug file | # If -v is specified yacc will create the output debug file | |||
# which is not really source for any process, but should | # which is not really source for any process, but should | |||
# be noted and also be cleaned | # be noted and also be cleaned (issue #2558) | |||
# Bug #2558 | ||||
if "-v" in flags: | if "-v" in flags: | |||
env.SideEffect(targetBase + '.output', target[0]) | env.SideEffect(targetBase + '.output', target[0]) | |||
env.Clean(target[0], targetBase + '.output') | env.Clean(target[0], targetBase + '.output') | |||
# With --defines and --graph, the name of the file is totally defined | # With --defines and --graph, the file to write is defined by the option | |||
# in the options. | # argument. Extract this and include in the list of targets. | |||
fileGenOptions = ["--defines=", "--graph="] | # NOTE: a filename passed to the command this way is not modified by SCons, | |||
# and so will be interpreted relative to the project top directory at | ||||
# execution time, while the name added to the target list will be | ||||
# interpreted relative to the SConscript directory - a possible mismatch. | ||||
# | ||||
# These are GNU bison-only options. | ||||
# Since bison 3.8, --header is the preferred name over --defines | ||||
fileGenOptions = ["--defines=", "--header=", "--graph="] | ||||
for option in flags: | for option in flags: | |||
for fileGenOption in fileGenOptions: | for fileGenOption in fileGenOptions: | |||
l = len(fileGenOption) | l = len(fileGenOption) | |||
if option[:l] == fileGenOption: | if option[:l] == fileGenOption: | |||
# A file generating option is present, so add the file | ||||
# name to the list of targets. | ||||
fileName = option[l:].strip() | fileName = option[l:].strip() | |||
target.append(fileName) | target.append(fileName) | |||
return (target, source) | yaccheaderfile = env.subst("$YACC_HEADER_FILE", target=target, source=source | |||
) | ||||
if yaccheaderfile: | ||||
target.append(yaccheaderfile) | ||||
# rewrite user-supplied file string with a node, we need later | ||||
env.Replace(YACC_HEADER_FILE=env.File(yaccheaderfile)) | ||||
yaccgraphfile = env.subst("$YACC_GRAPH_FILE", target=target, source=source) | ||||
if yaccgraphfile: | ||||
target.append(yaccgraphfile) | ||||
# rewrite user-supplied file string with a node, we need later | ||||
env.Replace(YACC_GRAPH_FILE=env.File(yaccgraphfile)) | ||||
def yEmitter(target, source, env): | return target, source | |||
def yEmitter(target, source, env) -> tuple: | ||||
return _yaccEmitter(target, source, env, ['.y', '.yacc'], '$YACCHFILESUFFIX' ) | return _yaccEmitter(target, source, env, ['.y', '.yacc'], '$YACCHFILESUFFIX' ) | |||
def ymEmitter(target, source, env): | def ymEmitter(target, source, env) -> tuple: | |||
return _yaccEmitter(target, source, env, ['.ym'], '$YACCHFILESUFFIX') | return _yaccEmitter(target, source, env, ['.ym'], '$YACCHFILESUFFIX') | |||
def yyEmitter(target, source, env): | def yyEmitter(target, source, env) -> tuple: | |||
return _yaccEmitter(target, source, env, ['.yy'], '$YACCHXXFILESUFFIX') | return _yaccEmitter(target, source, env, ['.yy'], '$YACCHXXFILESUFFIX') | |||
def get_yacc_path(env, append_paths=False): | def get_yacc_path(env, append_paths=False) -> Optional[str]: | |||
""" | """ | |||
Find the path to the yacc tool, searching several possible names | Returns the path to the yacc tool, searching several possible names. | |||
Only called in the Windows case, so the default_path | Only called in the Windows case, so the `default_path` argument to | |||
can be Windows-specific | :func:`find_program_path` can be Windows-specific. | |||
:param env: current construction environment | Args: | |||
:param append_paths: if set, add the path to the tool to PATH | env: current construction environment | |||
:return: path to yacc tool, if found | append_paths: if true, add the path to the tool to PATH | |||
""" | """ | |||
for prog in BINS: | for prog in BINS: | |||
bin_path = SCons.Tool.find_program_path( | bin_path = SCons.Tool.find_program_path( | |||
env, | env, | |||
prog, | prog, | |||
default_paths=CHOCO_DEFAULT_PATH + MINGW_DEFAULT_PATHS + CYGWIN_DEFA | default_paths=DEFAULT_PATHS, | |||
ULT_PATHS) | add_path=append_paths, | |||
) | ||||
if bin_path: | if bin_path: | |||
if append_paths: | ||||
env.AppendENVPath('PATH', os.path.dirname(bin_path)) | ||||
return bin_path | return bin_path | |||
SCons.Warnings.warn( | SCons.Warnings.warn( | |||
SCons.Warnings.SConsWarning, | SCons.Warnings.SConsWarning, | |||
'yacc tool requested, but yacc or bison binary not found in ENV PATH' | 'yacc tool requested, but yacc or bison binary not found in ENV PATH' | |||
) | ) | |||
def generate(env): | def generate(env) -> None: | |||
"""Add Builders and construction variables for yacc to an Environment.""" | """Add Builders and construction variables for yacc to an Environment.""" | |||
c_file, cxx_file = SCons.Tool.createCFileBuilders(env) | c_file, cxx_file = SCons.Tool.createCFileBuilders(env) | |||
# C | # C | |||
c_file.add_action('.y', YaccAction) | c_file.add_action('.y', YaccAction) | |||
c_file.add_emitter('.y', yEmitter) | c_file.add_emitter('.y', yEmitter) | |||
c_file.add_action('.yacc', YaccAction) | c_file.add_action('.yacc', YaccAction) | |||
c_file.add_emitter('.yacc', yEmitter) | c_file.add_emitter('.yacc', yEmitter) | |||
skipping to change at line 147 | skipping to change at line 172 | |||
c_file.add_emitter('.ym', ymEmitter) | c_file.add_emitter('.ym', ymEmitter) | |||
# C++ | # C++ | |||
cxx_file.add_action('.yy', YaccAction) | cxx_file.add_action('.yy', YaccAction) | |||
cxx_file.add_emitter('.yy', yyEmitter) | cxx_file.add_emitter('.yy', yyEmitter) | |||
if sys.platform == 'win32': | if sys.platform == 'win32': | |||
# ignore the return, all we need is for the path to be added | # ignore the return, all we need is for the path to be added | |||
_ = get_yacc_path(env, append_paths=True) | _ = get_yacc_path(env, append_paths=True) | |||
if 'YACC' not in env: | env.SetDefault( | |||
env["YACC"] = env.Detect(BINS) | YACC=env.Detect(BINS), | |||
YACCFLAGS=CLVar(""), | ||||
YACC_HEADER_FILE="", | ||||
YACC_GRAPH_FILE="", | ||||
) | ||||
env['YACCFLAGS'] = SCons.Util.CLVar('') | env['YACCCOM'] = '$YACC $YACCFLAGS $_YACC_HEADER $_YACC_GRAPH -o $TARGET $SO | |||
env['YACCCOM'] = '$YACC $YACCFLAGS -o $TARGET $SOURCES' | URCES' | |||
env['YACCHFILESUFFIX'] = '.h' | env['YACCHFILESUFFIX'] = '.h' | |||
env['YACCHXXFILESUFFIX'] = '.hpp' | env['YACCHXXFILESUFFIX'] = '.hpp' | |||
env['YACCVCGFILESUFFIX'] = '.vcg' | env['YACCVCGFILESUFFIX'] = '.vcg' | |||
env['_YACC_HEADER'] = '${YACC_HEADER_FILE and "--header=" + str(YACC_HEADER_ | ||||
FILE)}' | ||||
env['_YACC_GRAPH'] = '${YACC_GRAPH_FILE and "--graph=" + str(YACC_GRAPH_FILE | ||||
)}' | ||||
def exists(env): | def exists(env) -> Optional[str]: | |||
if 'YACC' in env: | if 'YACC' in env: | |||
return env.Detect(env['YACC']) | return env.Detect(env['YACC']) | |||
if sys.platform == 'win32': | if sys.platform == 'win32': | |||
return get_yacc_path(env) | return get_yacc_path(env) | |||
else: | else: | |||
return env.Detect(BINS) | return env.Detect(BINS) | |||
# Local Variables: | # Local Variables: | |||
# tab-width:4 | # tab-width:4 | |||
End of changes. 25 change blocks. | ||||
34 lines changed or deleted | 67 lines changed or added |