lex.py (SCons-4.3.0) | : | lex.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 lex. | """Tool-specific initialization for lex. | |||
This tool should support multiple lex implementations, | ||||
but is in actuality biased towards GNU Flex. | ||||
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.Action | import SCons.Action | |||
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 | ||||
LexAction = SCons.Action.Action("$LEXCOM", "$LEXCOMSTR") | LexAction = SCons.Action.Action("$LEXCOM", "$LEXCOMSTR") | |||
if sys.platform == 'win32': | if sys.platform == 'win32': | |||
BINS = ['flex', 'lex', 'win_flex'] | BINS = ['flex', 'lex', 'win_flex'] | |||
else: | else: | |||
BINS = ["flex", "lex"] | BINS = ["flex", "lex"] | |||
def lexEmitter(target, source, env): | def lexEmitter(target, source, env) -> tuple: | |||
sourceBase, sourceExt = os.path.splitext(SCons.Util.to_String(source[0])) | """Adds extra files generated by lex program to target list.""" | |||
sourceBase, sourceExt = os.path.splitext(to_String(source[0])) | ||||
if sourceExt == ".lm": # If using Objective-C | if sourceExt == ".lm": # If using Objective-C | |||
target = [sourceBase + ".m"] # the extension is ".m". | target = [sourceBase + ".m"] # the extension is ".m". | |||
# This emitter essentially tries to add to the target all extra | # With --header-file and ----tables-file, the file to write is defined | |||
# files generated by flex. | # by the option argument. Extract this and include in the list of targets. | |||
# NOTE: a filename passed to the command this way is not modified by SCons, | ||||
# Different options that are used to trigger the creation of extra files. | # and so will be interpreted relative to the project top directory at | |||
fileGenOptions = ["--header-file=", "--tables-file="] | # execution time, while the name added to the target list will be | |||
# interpreted relative to the SConscript directory - a possible mismatch. | ||||
lexflags = env.subst("$LEXFLAGS", target=target, source=source) | # | |||
for option in SCons.Util.CLVar(lexflags): | # These are GNU flex-only options. | |||
for fileGenOption in fileGenOptions: | # TODO: recognize --outfile also? | |||
file_gen_options = ["--header-file=", "--tables-file="] | ||||
lexflags = env.subst_list("$LEXFLAGS", target=target, source=source) | ||||
for option in lexflags[0]: | ||||
for fileGenOption in file_gen_options: | ||||
l = len(fileGenOption) | l = len(fileGenOption) | |||
if option[:l] == fileGenOption: | if option[:l] == fileGenOption: | |||
# A file generating option is present, so add the | # A file generating option is present, so add the | |||
# file name to the target list. | # file name to the target list. | |||
fileName = option[l:].strip() | file_name = option[l:].strip() | |||
target.append(fileName) | target.append(file_name) | |||
return (target, source) | ||||
lexheaderfile = env.subst("$LEX_HEADER_FILE", target=target, source=source) | ||||
if lexheaderfile: | ||||
target.append(lexheaderfile) | ||||
# rewrite user-supplied file string with a node, we need later | ||||
env.Replace(LEX_HEADER_FILE=env.File(lexheaderfile)) | ||||
lextablesfile = env.subst("$LEX_TABLES_FILE", target=target, source=source) | ||||
if lextablesfile: | ||||
target.append(lextablesfile) | ||||
# rewrite user-supplied file string with a node, we need later | ||||
env.Replace(LEX_TABLES_FILE=env.File(lextablesfile)) | ||||
return target, source | ||||
def get_lex_path(env, append_paths=False): | def get_lex_path(env, append_paths=False) -> Optional[str]: | |||
""" | """ | |||
Find the path to the lex tool, searching several possible names | Returns the path to the lex 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 lex tool, if found | append_paths: if set, 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, | |||
'lex tool requested, but lex or flex binary not found in ENV PATH' | 'lex tool requested, but lex or flex binary not found in ENV PATH' | |||
) | ) | |||
def generate(env): | def generate(env) -> None: | |||
"""Add Builders and construction variables for lex to an Environment.""" | """Add Builders and construction variables for lex 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(".l", LexAction) | c_file.add_action(".l", LexAction) | |||
c_file.add_emitter(".l", lexEmitter) | c_file.add_emitter(".l", lexEmitter) | |||
c_file.add_action(".lex", LexAction) | c_file.add_action(".lex", LexAction) | |||
c_file.add_emitter(".lex", lexEmitter) | c_file.add_emitter(".lex", lexEmitter) | |||
# Objective-C | # Objective-C | |||
cxx_file.add_action(".lm", LexAction) | cxx_file.add_action(".lm", LexAction) | |||
cxx_file.add_emitter(".lm", lexEmitter) | cxx_file.add_emitter(".lm", lexEmitter) | |||
# C++ | # C++ | |||
cxx_file.add_action(".ll", LexAction) | cxx_file.add_action(".ll", LexAction) | |||
cxx_file.add_emitter(".ll", lexEmitter) | cxx_file.add_emitter(".ll", lexEmitter) | |||
env["LEXFLAGS"] = SCons.Util.CLVar("") | ||||
if sys.platform == 'win32': | if sys.platform == 'win32': | |||
# ignore the return - we do not need the full path here | # ignore the return, all we need is for the path to be added | |||
_ = get_lex_path(env, append_paths=True) | _ = get_lex_path(env, append_paths=True) | |||
env["LEX"] = env.Detect(BINS) | ||||
if not env.get("LEXUNISTD"): | env.SetDefault( | |||
env["LEXUNISTD"] = SCons.Util.CLVar("") | LEX=env.Detect(BINS), | |||
env["LEXCOM"] = "$LEX $LEXUNISTD $LEXFLAGS -t $SOURCES > $TARGET" | LEXFLAGS=CLVar(""), | |||
LEX_HEADER_FILE="", | ||||
LEX_TABLES_FILE="", | ||||
) | ||||
if sys.platform == 'win32': | ||||
env.SetDefault(LEXUNISTD=CLVar("")) | ||||
env["LEXCOM"] = "$LEX $LEXUNISTD $LEXFLAGS $_LEX_HEADER $_LEX_TABLES -t | ||||
$SOURCES > $TARGET" | ||||
else: | else: | |||
env["LEX"] = env.Detect(BINS) | env["LEXCOM"] = "$LEX $LEXFLAGS $_LEX_HEADER $_LEX_TABLES -t $SOURCES > | |||
env["LEXCOM"] = "$LEX $LEXFLAGS -t $SOURCES > $TARGET" | $TARGET" | |||
env['_LEX_HEADER'] = '${LEX_HEADER_FILE and "--header-file=" + str(LEX_HEADE | ||||
R_FILE)}' | ||||
env['_LEX_TABLES'] = '${LEX_TABLES_FILE and "--tables-file=" + str(LEX_TABLE | ||||
S_FILE)}' | ||||
def exists(env): | def exists(env) -> Optional[str]: | |||
if sys.platform == 'win32': | if sys.platform == 'win32': | |||
return get_lex_path(env) | return get_lex_path(env) | |||
else: | else: | |||
return env.Detect(BINS) | return env.Detect(BINS) | |||
# Local Variables: | # Local Variables: | |||
# tab-width:4 | # tab-width:4 | |||
# indent-tabs-mode:nil | # indent-tabs-mode:nil | |||
# End: | # End: | |||
# vim: set expandtab tabstop=4 shiftwidth=4: | # vim: set expandtab tabstop=4 shiftwidth=4: | |||
End of changes. 20 change blocks. | ||||
37 lines changed or deleted | 71 lines changed or added |