mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2025-01-22 09:07:17 +01:00
Removed java from scons.
This commit is contained in:
parent
53151b3437
commit
b7650adcea
@ -1,43 +0,0 @@
|
|||||||
# MIT License
|
|
||||||
#
|
|
||||||
# Copyright The SCons Foundation
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
# Unit tests of various classes within SCons.Script.Main.py.
|
|
||||||
#
|
|
||||||
# Most of the tests of this functionality are actually end-to-end scripts
|
|
||||||
# in the test/ hierarchy.
|
|
||||||
#
|
|
||||||
# This module is for specific bits of functionality that we can test
|
|
||||||
# more effectively here, instead of in an end-to-end test that would
|
|
||||||
# have to reach into SCons.Script.Main for various classes or other bits
|
|
||||||
# of private functionality.
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
||||||
|
|
||||||
# Local Variables:
|
|
||||||
# tab-width:4
|
|
||||||
# indent-tabs-mode:nil
|
|
||||||
# End:
|
|
||||||
# vim: set expandtab tabstop=4 shiftwidth=4:
|
|
@ -1,584 +0,0 @@
|
|||||||
# MIT License
|
|
||||||
#
|
|
||||||
# Copyright The SCons Foundation
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
"""Common routines for processing Java. """
|
|
||||||
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import glob
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import List
|
|
||||||
|
|
||||||
java_parsing = True
|
|
||||||
|
|
||||||
default_java_version = '1.4'
|
|
||||||
|
|
||||||
# a switch for which jdk versions to use the Scope state for smarter
|
|
||||||
# anonymous inner class parsing.
|
|
||||||
scopeStateVersions = ('1.8',)
|
|
||||||
|
|
||||||
# Glob patterns for use in finding where the JDK is.
|
|
||||||
#
|
|
||||||
# These are pairs, (*dir_glob, *version_dir_glob) depending on whether
|
|
||||||
# a JDK version was requested or not.
|
|
||||||
# For now only used for Windows, which doesn't install JDK in a
|
|
||||||
# path that would be in env['ENV']['PATH']. The specific tool will
|
|
||||||
# add the discovered path to this. Since Oracle changed the rules,
|
|
||||||
# there are many possible vendors, we can't guess them all, but take a shot.
|
|
||||||
java_win32_dir_glob = 'C:/Program Files*/*/*jdk*/bin'
|
|
||||||
|
|
||||||
# On windows, since Java 9, there is a dash between 'jdk' and the version
|
|
||||||
# string that wasn't there before. this glob should catch either way.
|
|
||||||
java_win32_version_dir_glob = 'C:/Program Files*/*/*jdk*%s*/bin'
|
|
||||||
|
|
||||||
# Glob patterns for use in finding where the JDK headers are.
|
|
||||||
# These are pairs, *dir_glob used in the general case,
|
|
||||||
# *version_dir_glob if matching only a specific version.
|
|
||||||
java_macos_include_dir_glob = '/System/Library/Frameworks/JavaVM.framework/Headers/'
|
|
||||||
java_macos_version_include_dir_glob = '/System/Library/Frameworks/JavaVM.framework/Versions/%s*/Headers/'
|
|
||||||
|
|
||||||
java_linux_include_dirs_glob = [
|
|
||||||
'/usr/lib/jvm/default-java/include',
|
|
||||||
'/usr/lib/jvm/java-*/include',
|
|
||||||
'/opt/oracle-jdk-bin-*/include',
|
|
||||||
'/opt/openjdk-bin-*/include',
|
|
||||||
'/usr/lib/openjdk-*/include',
|
|
||||||
]
|
|
||||||
# Need to match path like below (from Centos 7)
|
|
||||||
# /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-0.el7_5.x86_64/include/
|
|
||||||
java_linux_version_include_dirs_glob = [
|
|
||||||
'/usr/lib/jvm/java-*-sun-%s*/include',
|
|
||||||
'/usr/lib/jvm/java-%s*-openjdk*/include',
|
|
||||||
'/usr/java/jdk%s*/include',
|
|
||||||
]
|
|
||||||
|
|
||||||
if java_parsing:
|
|
||||||
# Parse Java files for class names.
|
|
||||||
#
|
|
||||||
# This is a really cool parser from Charles Crain
|
|
||||||
# that finds appropriate class names in Java source.
|
|
||||||
|
|
||||||
# A regular expression that will find, in a java file:
|
|
||||||
# newlines;
|
|
||||||
# double-backslashes;
|
|
||||||
# a single-line comment "//";
|
|
||||||
# single or double quotes preceeded by a backslash;
|
|
||||||
# single quotes, double quotes, open or close braces, semi-colons,
|
|
||||||
# periods, open or close parentheses;
|
|
||||||
# floating-point numbers;
|
|
||||||
# any alphanumeric token (keyword, class name, specifier);
|
|
||||||
# any alphanumeric token surrounded by angle brackets (generics);
|
|
||||||
# the multi-line comment begin and end tokens /* and */;
|
|
||||||
# array declarations "[]".
|
|
||||||
# Lambda function symbols: ->
|
|
||||||
_reToken = re.compile(r'(\n|\\\\|//|\\[\'"]|[\'"{\};.()]|' +
|
|
||||||
r'\d*\.\d*|[A-Za-z_][\w$.]*|<[A-Za-z_]\w+>|' +
|
|
||||||
r'/\*|\*/|\[\]|->)')
|
|
||||||
|
|
||||||
|
|
||||||
class OuterState:
|
|
||||||
"""The initial state for parsing a Java file for classes,
|
|
||||||
interfaces, and anonymous inner classes."""
|
|
||||||
|
|
||||||
def __init__(self, version=default_java_version):
|
|
||||||
if version not in (
|
|
||||||
'1.1',
|
|
||||||
'1.2',
|
|
||||||
'1.3',
|
|
||||||
'1.4',
|
|
||||||
'1.5',
|
|
||||||
'1.6',
|
|
||||||
'1.7',
|
|
||||||
'1.8',
|
|
||||||
'5',
|
|
||||||
'6',
|
|
||||||
'9.0',
|
|
||||||
'10.0',
|
|
||||||
'11.0',
|
|
||||||
'12.0',
|
|
||||||
'13.0',
|
|
||||||
'14.0',
|
|
||||||
'15.0',
|
|
||||||
'16.0',
|
|
||||||
'17.0',
|
|
||||||
):
|
|
||||||
msg = "Java version %s not supported" % version
|
|
||||||
raise NotImplementedError(msg)
|
|
||||||
|
|
||||||
self.version = version
|
|
||||||
self.listClasses = []
|
|
||||||
self.listOutputs = []
|
|
||||||
self.stackBrackets = []
|
|
||||||
self.brackets = 0
|
|
||||||
self.nextAnon = 1
|
|
||||||
self.localClasses = []
|
|
||||||
self.stackAnonClassBrackets = []
|
|
||||||
self.anonStacksStack = [[0]]
|
|
||||||
self.package = None
|
|
||||||
|
|
||||||
def trace(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __getClassState(self):
|
|
||||||
try:
|
|
||||||
return self.classState
|
|
||||||
except AttributeError:
|
|
||||||
ret = ClassState(self)
|
|
||||||
self.classState = ret
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def __getPackageState(self):
|
|
||||||
try:
|
|
||||||
return self.packageState
|
|
||||||
except AttributeError:
|
|
||||||
ret = PackageState(self)
|
|
||||||
self.packageState = ret
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def __getAnonClassState(self):
|
|
||||||
try:
|
|
||||||
return self.anonState
|
|
||||||
except AttributeError:
|
|
||||||
self.outer_state = self
|
|
||||||
ret = SkipState(1, AnonClassState(self))
|
|
||||||
self.anonState = ret
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def __getSkipState(self):
|
|
||||||
try:
|
|
||||||
return self.skipState
|
|
||||||
except AttributeError:
|
|
||||||
ret = SkipState(1, self)
|
|
||||||
self.skipState = ret
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def _getAnonStack(self):
|
|
||||||
return self.anonStacksStack[-1]
|
|
||||||
|
|
||||||
def openBracket(self):
|
|
||||||
self.brackets = self.brackets + 1
|
|
||||||
|
|
||||||
def closeBracket(self):
|
|
||||||
self.brackets = self.brackets - 1
|
|
||||||
if len(self.stackBrackets) and \
|
|
||||||
self.brackets == self.stackBrackets[-1]:
|
|
||||||
self.listOutputs.append('$'.join(self.listClasses))
|
|
||||||
self.localClasses.pop()
|
|
||||||
self.listClasses.pop()
|
|
||||||
self.anonStacksStack.pop()
|
|
||||||
self.stackBrackets.pop()
|
|
||||||
if len(self.stackAnonClassBrackets) and \
|
|
||||||
self.brackets == self.stackAnonClassBrackets[-1] and \
|
|
||||||
self.version not in scopeStateVersions:
|
|
||||||
self._getAnonStack().pop()
|
|
||||||
self.stackAnonClassBrackets.pop()
|
|
||||||
|
|
||||||
def parseToken(self, token):
|
|
||||||
if token[:2] == '//':
|
|
||||||
return IgnoreState('\n', self)
|
|
||||||
elif token == '/*':
|
|
||||||
return IgnoreState('*/', self)
|
|
||||||
elif token == '{':
|
|
||||||
self.openBracket()
|
|
||||||
elif token == '}':
|
|
||||||
self.closeBracket()
|
|
||||||
elif token in ['"', "'"]:
|
|
||||||
return IgnoreState(token, self)
|
|
||||||
elif token == "new":
|
|
||||||
# anonymous inner class
|
|
||||||
if len(self.listClasses) > 0:
|
|
||||||
return self.__getAnonClassState()
|
|
||||||
return self.__getSkipState() # Skip the class name
|
|
||||||
elif token in ['class', 'interface', 'enum']:
|
|
||||||
if len(self.listClasses) == 0:
|
|
||||||
self.nextAnon = 1
|
|
||||||
self.stackBrackets.append(self.brackets)
|
|
||||||
return self.__getClassState()
|
|
||||||
elif token == 'package':
|
|
||||||
return self.__getPackageState()
|
|
||||||
elif token == '.':
|
|
||||||
# Skip the attribute, it might be named "class", in which
|
|
||||||
# case we don't want to treat the following token as
|
|
||||||
# an inner class name...
|
|
||||||
return self.__getSkipState()
|
|
||||||
return self
|
|
||||||
|
|
||||||
def addAnonClass(self):
|
|
||||||
"""Add an anonymous inner class"""
|
|
||||||
if self.version in ('1.1', '1.2', '1.3', '1.4'):
|
|
||||||
clazz = self.listClasses[0]
|
|
||||||
self.listOutputs.append('%s$%d' % (clazz, self.nextAnon))
|
|
||||||
# TODO: shouldn't need to repeat versions here and in OuterState
|
|
||||||
elif self.version in (
|
|
||||||
'1.5',
|
|
||||||
'1.6',
|
|
||||||
'1.7',
|
|
||||||
'1.8',
|
|
||||||
'5',
|
|
||||||
'6',
|
|
||||||
'9.0',
|
|
||||||
'10.0',
|
|
||||||
'11.0',
|
|
||||||
'12.0',
|
|
||||||
'13.0',
|
|
||||||
'14.0',
|
|
||||||
'15.0',
|
|
||||||
'16.0',
|
|
||||||
'17.0',
|
|
||||||
):
|
|
||||||
self.stackAnonClassBrackets.append(self.brackets)
|
|
||||||
className = []
|
|
||||||
className.extend(self.listClasses)
|
|
||||||
self._getAnonStack()[-1] = self._getAnonStack()[-1] + 1
|
|
||||||
for anon in self._getAnonStack():
|
|
||||||
className.append(str(anon))
|
|
||||||
self.listOutputs.append('$'.join(className))
|
|
||||||
|
|
||||||
self.nextAnon = self.nextAnon + 1
|
|
||||||
self._getAnonStack().append(0)
|
|
||||||
|
|
||||||
def setPackage(self, package):
|
|
||||||
self.package = package
|
|
||||||
|
|
||||||
|
|
||||||
class ScopeState:
|
|
||||||
"""
|
|
||||||
A state that parses code within a scope normally,
|
|
||||||
within the confines of a scope.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, old_state):
|
|
||||||
self.outer_state = old_state.outer_state
|
|
||||||
self.old_state = old_state
|
|
||||||
self.brackets = 0
|
|
||||||
|
|
||||||
def __getClassState(self):
|
|
||||||
try:
|
|
||||||
return self.classState
|
|
||||||
except AttributeError:
|
|
||||||
ret = ClassState(self)
|
|
||||||
self.classState = ret
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def __getAnonClassState(self):
|
|
||||||
try:
|
|
||||||
return self.anonState
|
|
||||||
except AttributeError:
|
|
||||||
ret = SkipState(1, AnonClassState(self))
|
|
||||||
self.anonState = ret
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def __getSkipState(self):
|
|
||||||
try:
|
|
||||||
return self.skipState
|
|
||||||
except AttributeError:
|
|
||||||
ret = SkipState(1, self)
|
|
||||||
self.skipState = ret
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def openBracket(self):
|
|
||||||
self.brackets = self.brackets + 1
|
|
||||||
|
|
||||||
def closeBracket(self):
|
|
||||||
self.brackets = self.brackets - 1
|
|
||||||
|
|
||||||
def parseToken(self, token):
|
|
||||||
# if self.brackets == 0:
|
|
||||||
# return self.old_state.parseToken(token)
|
|
||||||
if token[:2] == '//':
|
|
||||||
return IgnoreState('\n', self)
|
|
||||||
elif token == '/*':
|
|
||||||
return IgnoreState('*/', self)
|
|
||||||
elif token == '{':
|
|
||||||
self.openBracket()
|
|
||||||
elif token == '}':
|
|
||||||
self.closeBracket()
|
|
||||||
if self.brackets == 0:
|
|
||||||
self.outer_state._getAnonStack().pop()
|
|
||||||
return self.old_state
|
|
||||||
elif token in ['"', "'"]:
|
|
||||||
return IgnoreState(token, self)
|
|
||||||
elif token == "new":
|
|
||||||
# anonymous inner class
|
|
||||||
return self.__getAnonClassState()
|
|
||||||
elif token == '.':
|
|
||||||
# Skip the attribute, it might be named "class", in which
|
|
||||||
# case we don't want to treat the following token as
|
|
||||||
# an inner class name...
|
|
||||||
return self.__getSkipState()
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class AnonClassState:
|
|
||||||
"""A state that looks for anonymous inner classes."""
|
|
||||||
|
|
||||||
def __init__(self, old_state):
|
|
||||||
# outer_state is always an instance of OuterState
|
|
||||||
self.outer_state = old_state.outer_state
|
|
||||||
self.old_state = old_state
|
|
||||||
self.brace_level = 0
|
|
||||||
|
|
||||||
def parseToken(self, token):
|
|
||||||
# This is an anonymous class if and only if the next
|
|
||||||
# non-whitespace token is a bracket. Everything between
|
|
||||||
# braces should be parsed as normal java code.
|
|
||||||
if token[:2] == '//':
|
|
||||||
return IgnoreState('\n', self)
|
|
||||||
elif token == '/*':
|
|
||||||
return IgnoreState('*/', self)
|
|
||||||
elif token == '\n':
|
|
||||||
return self
|
|
||||||
elif token[0] == '<' and token[-1] == '>':
|
|
||||||
return self
|
|
||||||
elif token == '(':
|
|
||||||
self.brace_level = self.brace_level + 1
|
|
||||||
return self
|
|
||||||
if self.brace_level > 0:
|
|
||||||
if token == 'new':
|
|
||||||
# look further for anonymous inner class
|
|
||||||
return SkipState(1, AnonClassState(self))
|
|
||||||
elif token in ['"', "'"]:
|
|
||||||
return IgnoreState(token, self)
|
|
||||||
elif token == ')':
|
|
||||||
self.brace_level = self.brace_level - 1
|
|
||||||
return self
|
|
||||||
if token == '{':
|
|
||||||
self.outer_state.addAnonClass()
|
|
||||||
if self.outer_state.version in scopeStateVersions:
|
|
||||||
return ScopeState(old_state=self.old_state).parseToken(token)
|
|
||||||
return self.old_state.parseToken(token)
|
|
||||||
|
|
||||||
|
|
||||||
class SkipState:
|
|
||||||
"""A state that will skip a specified number of tokens before
|
|
||||||
reverting to the previous state."""
|
|
||||||
|
|
||||||
def __init__(self, tokens_to_skip, old_state):
|
|
||||||
self.tokens_to_skip = tokens_to_skip
|
|
||||||
self.old_state = old_state
|
|
||||||
|
|
||||||
def parseToken(self, token):
|
|
||||||
self.tokens_to_skip = self.tokens_to_skip - 1
|
|
||||||
if self.tokens_to_skip < 1:
|
|
||||||
return self.old_state
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class ClassState:
|
|
||||||
"""A state we go into when we hit a class or interface keyword."""
|
|
||||||
|
|
||||||
def __init__(self, outer_state):
|
|
||||||
# outer_state is always an instance of OuterState
|
|
||||||
self.outer_state = outer_state
|
|
||||||
|
|
||||||
def parseToken(self, token):
|
|
||||||
# the next non-whitespace token should be the name of the class
|
|
||||||
if token == '\n':
|
|
||||||
return self
|
|
||||||
# If that's an inner class which is declared in a method, it
|
|
||||||
# requires an index prepended to the class-name, e.g.
|
|
||||||
# 'Foo$1Inner'
|
|
||||||
# https://github.com/SCons/scons/issues/2087
|
|
||||||
if self.outer_state.localClasses and \
|
|
||||||
self.outer_state.stackBrackets[-1] > \
|
|
||||||
self.outer_state.stackBrackets[-2] + 1:
|
|
||||||
locals = self.outer_state.localClasses[-1]
|
|
||||||
try:
|
|
||||||
idx = locals[token]
|
|
||||||
locals[token] = locals[token] + 1
|
|
||||||
except KeyError:
|
|
||||||
locals[token] = 1
|
|
||||||
token = str(locals[token]) + token
|
|
||||||
self.outer_state.localClasses.append({})
|
|
||||||
self.outer_state.listClasses.append(token)
|
|
||||||
self.outer_state.anonStacksStack.append([0])
|
|
||||||
return self.outer_state
|
|
||||||
|
|
||||||
|
|
||||||
class IgnoreState:
|
|
||||||
"""A state that will ignore all tokens until it gets to a
|
|
||||||
specified token."""
|
|
||||||
|
|
||||||
def __init__(self, ignore_until, old_state):
|
|
||||||
self.ignore_until = ignore_until
|
|
||||||
self.old_state = old_state
|
|
||||||
|
|
||||||
def parseToken(self, token):
|
|
||||||
if self.ignore_until == token:
|
|
||||||
return self.old_state
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class PackageState:
|
|
||||||
"""The state we enter when we encounter the package keyword.
|
|
||||||
We assume the next token will be the package name."""
|
|
||||||
|
|
||||||
def __init__(self, outer_state):
|
|
||||||
# outer_state is always an instance of OuterState
|
|
||||||
self.outer_state = outer_state
|
|
||||||
|
|
||||||
def parseToken(self, token):
|
|
||||||
self.outer_state.setPackage(token)
|
|
||||||
return self.outer_state
|
|
||||||
|
|
||||||
|
|
||||||
def parse_java_file(fn, version=default_java_version):
|
|
||||||
with open(fn, 'r', encoding='utf-8') as f:
|
|
||||||
data = f.read()
|
|
||||||
return parse_java(data, version)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_java(contents, version=default_java_version, trace=None):
|
|
||||||
"""Parse a .java file and return a double of package directory,
|
|
||||||
plus a list of .class files that compiling that .java file will
|
|
||||||
produce"""
|
|
||||||
package = None
|
|
||||||
initial = OuterState(version)
|
|
||||||
currstate = initial
|
|
||||||
for token in _reToken.findall(contents):
|
|
||||||
# The regex produces a bunch of groups, but only one will
|
|
||||||
# have anything in it.
|
|
||||||
currstate = currstate.parseToken(token)
|
|
||||||
if trace: trace(token, currstate)
|
|
||||||
if initial.package:
|
|
||||||
package = initial.package.replace('.', os.sep)
|
|
||||||
return (package, initial.listOutputs)
|
|
||||||
|
|
||||||
else:
|
|
||||||
# Don't actually parse Java files for class names.
|
|
||||||
#
|
|
||||||
# We might make this a configurable option in the future if
|
|
||||||
# Java-file parsing takes too long (although it shouldn't relative
|
|
||||||
# to how long the Java compiler itself seems to take...).
|
|
||||||
|
|
||||||
def parse_java_file(fn):
|
|
||||||
""" "Parse" a .java file.
|
|
||||||
|
|
||||||
This actually just splits the file name, so the assumption here
|
|
||||||
is that the file name matches the public class name, and that
|
|
||||||
the path to the file is the same as the package name.
|
|
||||||
"""
|
|
||||||
return os.path.split(fn)
|
|
||||||
|
|
||||||
|
|
||||||
def get_java_install_dirs(platform, version=None) -> List[str]:
|
|
||||||
""" Find possible java jdk installation directories.
|
|
||||||
|
|
||||||
Returns a list for use as `default_paths` when looking up actual
|
|
||||||
java binaries with :meth:`SCons.Tool.find_program_path`.
|
|
||||||
The paths are sorted by version, latest first.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
platform: selector for search algorithm.
|
|
||||||
version: if not None, restrict the search to this version.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list of default paths for jdk.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if platform == 'win32':
|
|
||||||
paths = []
|
|
||||||
if version:
|
|
||||||
paths = glob.glob(java_win32_version_dir_glob % version)
|
|
||||||
else:
|
|
||||||
paths = glob.glob(java_win32_dir_glob)
|
|
||||||
|
|
||||||
def win32getvnum(java):
|
|
||||||
""" Generates a sort key for win32 jdk versions.
|
|
||||||
|
|
||||||
We'll have gotten a path like ...something/*jdk*/bin because
|
|
||||||
that is the pattern we glob for. To generate the sort key,
|
|
||||||
extracts the next-to-last component, then trims it further if
|
|
||||||
it had a complex name, like 'java-1.8.0-openjdk-1.8.0.312-1',
|
|
||||||
to try and put it on a common footing with the more common style,
|
|
||||||
which looks like 'jdk-11.0.2'.
|
|
||||||
|
|
||||||
This is certainly fragile, and if someone has a 9.0 it won't
|
|
||||||
sort right since this will still be alphabetic, BUT 9.0 was
|
|
||||||
not an LTS release and is 30 mos out of support as this note
|
|
||||||
is written so just assume it will be okay.
|
|
||||||
"""
|
|
||||||
d = Path(java).parts[-2]
|
|
||||||
if not d.startswith('jdk'):
|
|
||||||
d = 'jdk' + d.rsplit('jdk', 1)[-1]
|
|
||||||
return d
|
|
||||||
|
|
||||||
return sorted(paths, key=win32getvnum, reverse=True)
|
|
||||||
|
|
||||||
# other platforms, do nothing for now: we expect the standard
|
|
||||||
# paths to be enough to find a jdk (e.g. use alternatives system)
|
|
||||||
return []
|
|
||||||
|
|
||||||
|
|
||||||
def get_java_include_paths(env, javac, version) -> List[str]:
|
|
||||||
"""Find java include paths for JNI building.
|
|
||||||
|
|
||||||
Cannot be called in isolation - `javac` refers to an already detected
|
|
||||||
compiler. Normally would would call :func:`get_java_install_dirs` first
|
|
||||||
and then do lookups on the paths it returns before calling us.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
env: construction environment, used to extract platform.
|
|
||||||
javac: path to detected javac.
|
|
||||||
version: if not None, restrict the search to this version.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list of include directory paths.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if not javac:
|
|
||||||
return []
|
|
||||||
|
|
||||||
# on Windows, we have a path to the actual javac, so look locally
|
|
||||||
if env['PLATFORM'] == 'win32':
|
|
||||||
javac_bin_dir = os.path.dirname(javac)
|
|
||||||
java_inc_dir = os.path.normpath(os.path.join(javac_bin_dir, '..', 'include'))
|
|
||||||
paths = [java_inc_dir, os.path.join(java_inc_dir, 'win32')]
|
|
||||||
|
|
||||||
# for the others, we probably found something which isn't in the JDK dir,
|
|
||||||
# so use the predefined patterns to glob for an include directory.
|
|
||||||
elif env['PLATFORM'] == 'darwin':
|
|
||||||
if not version:
|
|
||||||
paths = [java_macos_include_dir_glob]
|
|
||||||
else:
|
|
||||||
paths = sorted(glob.glob(java_macos_version_include_dir_glob % version))
|
|
||||||
else:
|
|
||||||
base_paths = []
|
|
||||||
if not version:
|
|
||||||
for p in java_linux_include_dirs_glob:
|
|
||||||
base_paths.extend(glob.glob(p))
|
|
||||||
else:
|
|
||||||
for p in java_linux_version_include_dirs_glob:
|
|
||||||
base_paths.extend(glob.glob(p % version))
|
|
||||||
|
|
||||||
paths = []
|
|
||||||
for p in base_paths:
|
|
||||||
paths.extend([p, os.path.join(p, 'linux')])
|
|
||||||
|
|
||||||
return paths
|
|
||||||
|
|
||||||
# Local Variables:
|
|
||||||
# tab-width:4
|
|
||||||
# indent-tabs-mode:nil
|
|
||||||
# End:
|
|
||||||
# vim: set expandtab tabstop=4 shiftwidth=4:
|
|
@ -1,783 +0,0 @@
|
|||||||
# MIT License
|
|
||||||
#
|
|
||||||
# Copyright The SCons Foundation
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
import os.path
|
|
||||||
import unittest
|
|
||||||
import fnmatch
|
|
||||||
|
|
||||||
import SCons.Scanner.IDL
|
|
||||||
import SCons.Tool.JavaCommon
|
|
||||||
|
|
||||||
import TestSCons
|
|
||||||
|
|
||||||
# Adding trace=trace to any of the parse_jave() calls below will cause
|
|
||||||
# the parser to spit out trace messages of the tokens it sees and the
|
|
||||||
# attendant transitions.
|
|
||||||
|
|
||||||
def trace(token, newstate):
|
|
||||||
from SCons.Debug import Trace
|
|
||||||
statename = newstate.__class__.__name__
|
|
||||||
Trace('token = %s, state = %s\n' % (repr(token), statename))
|
|
||||||
|
|
||||||
class parse_javaTestCase(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_bare_bones(self):
|
|
||||||
"""Test a bare-bones class"""
|
|
||||||
|
|
||||||
input = """\
|
|
||||||
package com.sub.bar;
|
|
||||||
|
|
||||||
public class Foo
|
|
||||||
{
|
|
||||||
|
|
||||||
public static void main(String[] args)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* This tests a former bug where strings would eat later code. */
|
|
||||||
String hello1 = new String("Hello, world!");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
|
|
||||||
assert pkg_dir == os.path.join('com', 'sub', 'bar'), pkg_dir
|
|
||||||
assert classes == ['Foo'], classes
|
|
||||||
|
|
||||||
|
|
||||||
def test_file_parser(self):
|
|
||||||
"""Test the file parser"""
|
|
||||||
input = """\
|
|
||||||
package com.sub.bar;
|
|
||||||
|
|
||||||
public class Foo
|
|
||||||
{
|
|
||||||
public static void main(String[] args)
|
|
||||||
{
|
|
||||||
/* This tests that unicde is handled . */
|
|
||||||
String hello1 = new String("ఎత్తువెడల్పు");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
file_name = 'test_file_parser.java'
|
|
||||||
with open(file_name, 'w', encoding='UTF-8') as jf:
|
|
||||||
print(input, file=jf)
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java_file(file_name)
|
|
||||||
if os.path.exists(file_name):
|
|
||||||
os.remove(file_name)
|
|
||||||
assert pkg_dir == os.path.join('com', 'sub', 'bar'), pkg_dir
|
|
||||||
assert classes == ['Foo'], classes
|
|
||||||
|
|
||||||
|
|
||||||
def test_dollar_sign(self):
|
|
||||||
"""Test class names with $ in them"""
|
|
||||||
|
|
||||||
input = """\
|
|
||||||
public class BadDep {
|
|
||||||
public void new$rand () {}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
|
|
||||||
assert pkg_dir is None, pkg_dir
|
|
||||||
assert classes == ['BadDep'], classes
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_inner_classes(self):
|
|
||||||
"""Test parsing various forms of inner classes"""
|
|
||||||
|
|
||||||
input = """\
|
|
||||||
class Empty {
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Listener {
|
|
||||||
public void execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
public
|
|
||||||
class
|
|
||||||
Test implements Listener {
|
|
||||||
class Inner {
|
|
||||||
void go() {
|
|
||||||
use(new Listener() {
|
|
||||||
public void execute() {
|
|
||||||
System.out.println("In Inner");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
String s1 = "class A";
|
|
||||||
String s2 = "new Listener() { }";
|
|
||||||
/* class B */
|
|
||||||
/* new Listener() { } */
|
|
||||||
}
|
|
||||||
|
|
||||||
class Inner2 {
|
|
||||||
Inner2() { Listener l = new Listener(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure this class doesn't get interpreted as an inner class of the previous one, when "new" is used in the previous class. */
|
|
||||||
class Inner3 {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
new Test().run();
|
|
||||||
}
|
|
||||||
|
|
||||||
void run() {
|
|
||||||
use(new Listener() {
|
|
||||||
public void execute() {
|
|
||||||
use(new Listener( ) {
|
|
||||||
public void execute() {
|
|
||||||
System.out.println("Inside execute()");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
new Inner().go();
|
|
||||||
}
|
|
||||||
|
|
||||||
void use(Listener l) {
|
|
||||||
l.execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Private {
|
|
||||||
void run() {
|
|
||||||
new Listener() {
|
|
||||||
public void execute() {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.4')
|
|
||||||
assert pkg_dir is None, pkg_dir
|
|
||||||
expect = [
|
|
||||||
'Empty',
|
|
||||||
'Listener',
|
|
||||||
'Test$1',
|
|
||||||
'Test$Inner',
|
|
||||||
'Test$Inner2',
|
|
||||||
'Test$Inner3',
|
|
||||||
'Test$2',
|
|
||||||
'Test$3',
|
|
||||||
'Test',
|
|
||||||
'Private$1',
|
|
||||||
'Private',
|
|
||||||
]
|
|
||||||
assert classes == expect, classes
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.5')
|
|
||||||
assert pkg_dir is None, pkg_dir
|
|
||||||
expect = [
|
|
||||||
'Empty',
|
|
||||||
'Listener',
|
|
||||||
'Test$Inner$1',
|
|
||||||
'Test$Inner',
|
|
||||||
'Test$Inner2',
|
|
||||||
'Test$Inner3',
|
|
||||||
'Test$1',
|
|
||||||
'Test$1$1',
|
|
||||||
'Test',
|
|
||||||
'Private$1',
|
|
||||||
'Private',
|
|
||||||
]
|
|
||||||
assert classes == expect, (expect, classes)
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '5')
|
|
||||||
assert pkg_dir is None, pkg_dir
|
|
||||||
expect = [
|
|
||||||
'Empty',
|
|
||||||
'Listener',
|
|
||||||
'Test$Inner$1',
|
|
||||||
'Test$Inner',
|
|
||||||
'Test$Inner2',
|
|
||||||
'Test$Inner3',
|
|
||||||
'Test$1',
|
|
||||||
'Test$1$1',
|
|
||||||
'Test',
|
|
||||||
'Private$1',
|
|
||||||
'Private',
|
|
||||||
]
|
|
||||||
assert classes == expect, (expect, classes)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_comments(self):
|
|
||||||
"""Test a class with comments"""
|
|
||||||
|
|
||||||
input = """\
|
|
||||||
package com.sub.foo;
|
|
||||||
|
|
||||||
import java.rmi.Naming;
|
|
||||||
import java.rmi.RemoteException;
|
|
||||||
import java.rmi.RMISecurityManager;
|
|
||||||
import java.rmi.server.UnicastRemoteObject;
|
|
||||||
|
|
||||||
public class Example1 extends UnicastRemoteObject implements Hello {
|
|
||||||
|
|
||||||
public Example1() throws RemoteException {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String sayHello() {
|
|
||||||
return "Hello World!";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String args[]) {
|
|
||||||
if (System.getSecurityManager() == null) {
|
|
||||||
System.setSecurityManager(new RMISecurityManager());
|
|
||||||
}
|
|
||||||
// a comment
|
|
||||||
try {
|
|
||||||
Example1 obj = new Example1();
|
|
||||||
|
|
||||||
Naming.rebind("//myhost/HelloServer", obj);
|
|
||||||
|
|
||||||
System.out.println("HelloServer bound in registry");
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("Example1 err: " + e.getMessage());
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
|
|
||||||
assert pkg_dir == os.path.join('com', 'sub', 'foo'), pkg_dir
|
|
||||||
assert classes == ['Example1'], classes
|
|
||||||
|
|
||||||
|
|
||||||
def test_arrays(self):
|
|
||||||
"""Test arrays of class instances"""
|
|
||||||
|
|
||||||
input = """\
|
|
||||||
public class Test {
|
|
||||||
MyClass abc = new MyClass();
|
|
||||||
MyClass xyz = new MyClass();
|
|
||||||
MyClass _array[] = new MyClass[] {
|
|
||||||
abc,
|
|
||||||
xyz
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
|
|
||||||
assert pkg_dir is None, pkg_dir
|
|
||||||
assert classes == ['Test'], classes
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_backslash(self):
|
|
||||||
"""Test backslash handling"""
|
|
||||||
|
|
||||||
input = """\
|
|
||||||
public class MyTabs
|
|
||||||
{
|
|
||||||
private class MyInternal
|
|
||||||
{
|
|
||||||
}
|
|
||||||
private final static String PATH = "images\\\\";
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
|
|
||||||
assert pkg_dir is None, pkg_dir
|
|
||||||
assert classes == ['MyTabs$MyInternal', 'MyTabs'], classes
|
|
||||||
|
|
||||||
|
|
||||||
def test_enum(self):
|
|
||||||
"""Test the Java 1.5 enum keyword"""
|
|
||||||
|
|
||||||
input = """\
|
|
||||||
package p;
|
|
||||||
public enum a {}
|
|
||||||
"""
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
|
|
||||||
assert pkg_dir == 'p', pkg_dir
|
|
||||||
assert classes == ['a'], classes
|
|
||||||
|
|
||||||
|
|
||||||
def test_anon_classes(self):
|
|
||||||
"""Test anonymous classes"""
|
|
||||||
|
|
||||||
input = """\
|
|
||||||
public abstract class TestClass
|
|
||||||
{
|
|
||||||
public void completed()
|
|
||||||
{
|
|
||||||
new Thread()
|
|
||||||
{
|
|
||||||
}.start();
|
|
||||||
|
|
||||||
new Thread()
|
|
||||||
{
|
|
||||||
}.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
|
|
||||||
assert pkg_dir is None, pkg_dir
|
|
||||||
assert classes == ['TestClass$1', 'TestClass$2', 'TestClass'], classes
|
|
||||||
|
|
||||||
|
|
||||||
def test_closing_bracket(self):
|
|
||||||
"""Test finding a closing bracket instead of an anonymous class"""
|
|
||||||
|
|
||||||
input = """\
|
|
||||||
class TestSCons {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
Foo[] fooArray = new Foo[] { new Foo() };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Foo { }
|
|
||||||
"""
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
|
|
||||||
assert pkg_dir is None, pkg_dir
|
|
||||||
assert classes == ['TestSCons', 'Foo'], classes
|
|
||||||
|
|
||||||
|
|
||||||
def test_dot_class_attributes(self):
|
|
||||||
"""Test handling ".class" attributes"""
|
|
||||||
|
|
||||||
input = """\
|
|
||||||
public class Test extends Object
|
|
||||||
{
|
|
||||||
static {
|
|
||||||
Class c = Object[].class;
|
|
||||||
Object[] s = new Object[] {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
|
|
||||||
assert classes == ['Test'], classes
|
|
||||||
|
|
||||||
input = """\
|
|
||||||
public class A {
|
|
||||||
public class B {
|
|
||||||
public void F(Object[] o) {
|
|
||||||
F(new Object[] {Object[].class});
|
|
||||||
}
|
|
||||||
public void G(Object[] o) {
|
|
||||||
F(new Object[] {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input)
|
|
||||||
assert pkg_dir is None, pkg_dir
|
|
||||||
assert classes == ['A$B', 'A'], classes
|
|
||||||
|
|
||||||
def test_anonymous_classes_with_parentheses(self):
|
|
||||||
"""Test finding anonymous classes marked by parentheses"""
|
|
||||||
|
|
||||||
input = """\
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
public class Foo {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
File f = new File(
|
|
||||||
new File("a") {
|
|
||||||
public String toString() {
|
|
||||||
return "b";
|
|
||||||
}
|
|
||||||
} to String()
|
|
||||||
) {
|
|
||||||
public String toString() {
|
|
||||||
return "c";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.4')
|
|
||||||
assert classes == ['Foo$1', 'Foo$2', 'Foo'], classes
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.5')
|
|
||||||
assert classes == ['Foo$1', 'Foo$1$1', 'Foo'], classes
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '6')
|
|
||||||
assert classes == ['Foo$1', 'Foo$1$1', 'Foo'], classes
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_nested_anonymous_inner_classes(self):
|
|
||||||
"""Test finding nested anonymous inner classes"""
|
|
||||||
|
|
||||||
input = """\
|
|
||||||
// import java.util.*;
|
|
||||||
|
|
||||||
public class NestedExample
|
|
||||||
{
|
|
||||||
public NestedExample()
|
|
||||||
{
|
|
||||||
Thread t = new Thread() {
|
|
||||||
public void start()
|
|
||||||
{
|
|
||||||
Thread t = new Thread() {
|
|
||||||
public void start()
|
|
||||||
{
|
|
||||||
try {Thread.sleep(200);}
|
|
||||||
catch (Exception e) {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
try {Thread.sleep(200);}
|
|
||||||
catch (Exception e) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void main(String argv[])
|
|
||||||
{
|
|
||||||
NestedExample e = new NestedExample();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.4')
|
|
||||||
expect = [ 'NestedExample$1', 'NestedExample$2', 'NestedExample' ]
|
|
||||||
assert expect == classes, (expect, classes)
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.5')
|
|
||||||
expect = [ 'NestedExample$1', 'NestedExample$1$1', 'NestedExample' ]
|
|
||||||
assert expect == classes, (expect, classes)
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '6')
|
|
||||||
expect = [ 'NestedExample$1', 'NestedExample$1$1', 'NestedExample' ]
|
|
||||||
assert expect == classes, (expect, classes)
|
|
||||||
|
|
||||||
def test_lambda_after_new(self):
|
|
||||||
"""Test lamdas after new"""
|
|
||||||
|
|
||||||
input = """\
|
|
||||||
// import java.util.*;
|
|
||||||
|
|
||||||
public class LamdaExample
|
|
||||||
{
|
|
||||||
|
|
||||||
public void testFunc (int arg1, String arg2, Runnable lambda){
|
|
||||||
}
|
|
||||||
public LamdaExample()
|
|
||||||
{
|
|
||||||
testFunc(
|
|
||||||
5,
|
|
||||||
new String("test"),
|
|
||||||
// Lambda symbol is after new, and used curly braces so
|
|
||||||
// we should not parse this as a new class.
|
|
||||||
() -> {}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void main(String argv[])
|
|
||||||
{
|
|
||||||
LamdaExample e = new LamdaExample();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.4')
|
|
||||||
expect = [ 'LamdaExample' ]
|
|
||||||
assert expect == classes, (expect, classes)
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.8')
|
|
||||||
expect = [ 'LamdaExample' ]
|
|
||||||
assert expect == classes, (expect, classes)
|
|
||||||
|
|
||||||
def test_private_inner_class_instantiation(self):
|
|
||||||
"""Test anonymous inner class generated by private instantiation"""
|
|
||||||
|
|
||||||
input = """\
|
|
||||||
class test
|
|
||||||
{
|
|
||||||
test()
|
|
||||||
{
|
|
||||||
super();
|
|
||||||
new inner();
|
|
||||||
}
|
|
||||||
|
|
||||||
static class inner
|
|
||||||
{
|
|
||||||
private inner() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
# This is what we *should* generate, apparently due to the
|
|
||||||
# private instantiation of the inner class, but don't today.
|
|
||||||
#expect = [ 'test$1', 'test$inner', 'test' ]
|
|
||||||
|
|
||||||
# What our parser currently generates, which doesn't match
|
|
||||||
# what the Java compiler actually generates.
|
|
||||||
expect = [ 'test$inner', 'test' ]
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.4')
|
|
||||||
assert expect == classes, (expect, classes)
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.5')
|
|
||||||
assert expect == classes, (expect, classes)
|
|
||||||
|
|
||||||
def test_floating_point_numbers(self):
|
|
||||||
"""Test floating-point numbers in the input stream"""
|
|
||||||
input = """
|
|
||||||
// Broken.java
|
|
||||||
class Broken
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Detected.
|
|
||||||
*/
|
|
||||||
Object anonymousInnerOK = new Runnable() { public void run () {} };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detected.
|
|
||||||
*/
|
|
||||||
class InnerOK { InnerOK () { } }
|
|
||||||
|
|
||||||
{
|
|
||||||
System.out.println("a number: " + 1000.0 + "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not detected.
|
|
||||||
*/
|
|
||||||
Object anonymousInnerBAD = new Runnable() { public void run () {} };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Not detected.
|
|
||||||
*/
|
|
||||||
class InnerBAD { InnerBAD () { } }
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
expect = ['Broken$1', 'Broken$InnerOK', 'Broken$2', 'Broken$InnerBAD', 'Broken']
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.4')
|
|
||||||
assert expect == classes, (expect, classes)
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.5')
|
|
||||||
assert expect == classes, (expect, classes)
|
|
||||||
|
|
||||||
|
|
||||||
def test_genercis(self):
|
|
||||||
"""Test that generics don't interfere with detecting anonymous classes"""
|
|
||||||
|
|
||||||
input = """\
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
public class Foo
|
|
||||||
{
|
|
||||||
public void foo()
|
|
||||||
{
|
|
||||||
Comparator<Date> comp = new Comparator<Date>()
|
|
||||||
{
|
|
||||||
static final long serialVersionUID = 1L;
|
|
||||||
public int compare(Date lhs, Date rhs)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
expect = [ 'Foo$1', 'Foo' ]
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.6')
|
|
||||||
assert expect == classes, (expect, classes)
|
|
||||||
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '6')
|
|
||||||
assert expect == classes, (expect, classes)
|
|
||||||
|
|
||||||
|
|
||||||
def test_in_function_class_declaration(self):
|
|
||||||
"""
|
|
||||||
Test that implementing a class in a function call doesn't confuse SCons.
|
|
||||||
"""
|
|
||||||
|
|
||||||
input = """
|
|
||||||
package com.Matthew;
|
|
||||||
|
|
||||||
public class AnonDemo {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
new AnonDemo().execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void execute() {
|
|
||||||
Foo bar = new Foo(new Foo() {
|
|
||||||
@Override
|
|
||||||
public int getX() { return this.x; }
|
|
||||||
}) {
|
|
||||||
@Override
|
|
||||||
public int getX() { return this.x; }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class Foo {
|
|
||||||
public int x;
|
|
||||||
public abstract int getX();
|
|
||||||
|
|
||||||
public Foo(Foo f) {
|
|
||||||
this.x = f.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Foo() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
expect = ['AnonDemo$1',
|
|
||||||
'AnonDemo$2',
|
|
||||||
'AnonDemo$Foo',
|
|
||||||
'AnonDemo']
|
|
||||||
pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.8')
|
|
||||||
assert expect == classes, (expect, classes)
|
|
||||||
|
|
||||||
def test_jdk_globs(self):
|
|
||||||
"""
|
|
||||||
Verify that the java path globs work with specific examples.
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
from SCons.Tool.JavaCommon import (
|
|
||||||
java_linux_include_dirs_glob,
|
|
||||||
java_linux_version_include_dirs_glob,
|
|
||||||
java_win32_dir_glob,
|
|
||||||
java_win32_version_dir_glob,
|
|
||||||
java_macos_include_dir_glob,
|
|
||||||
java_macos_version_include_dir_glob,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Test windows globs
|
|
||||||
win_java_dirs = [
|
|
||||||
(r'C:/Program Files/Java/jdk1.8.0_201/bin', '1.8.0'),
|
|
||||||
(r'C:/Program Files/Java/jdk-11.0.2/bin', '11.0.2'),
|
|
||||||
(r'C:/Program Files/AdoptOpenJDK/jdk-16.0.1.9-hotspot/bin', '16.0.1'),
|
|
||||||
(r'C:/Program Files/Microsoft/jdk-17.0.0.35-hotspot/bin', '17.0.0'),
|
|
||||||
(r'C:/Program Files/OpenJDK/openjdk-11.0.13_8/bin', '11.0.13'),
|
|
||||||
(r'C:/Program Files/RedHat/java-1.8.0-openjdk-1.8.0.312-1/bin', '1.8.0'),
|
|
||||||
(r'C:/Program Files/RedHat/java-11-openjdk-11.0.13-1/bin', '11.0.13'),
|
|
||||||
]
|
|
||||||
|
|
||||||
for (wjd, version) in win_java_dirs:
|
|
||||||
if not fnmatch.fnmatch(wjd, java_win32_dir_glob):
|
|
||||||
self.fail(
|
|
||||||
"Didn't properly match %s with pattern %s"
|
|
||||||
% (wjd, java_win32_dir_glob)
|
|
||||||
)
|
|
||||||
if not fnmatch.fnmatch(wjd, java_win32_version_dir_glob % version):
|
|
||||||
self.fail(
|
|
||||||
"Didn't properly match %s with version (%s) specific pattern %s"
|
|
||||||
% (wjd, version, java_win32_version_dir_glob % version)
|
|
||||||
)
|
|
||||||
|
|
||||||
non_win_java_include_dirs = [
|
|
||||||
(
|
|
||||||
'/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-0.el7_5.x86_64/include',
|
|
||||||
'1.8.0',
|
|
||||||
),
|
|
||||||
('/usr/lib/jvm/java-1.8.0-openjdk-amd64/include', '1.8.0'),
|
|
||||||
('/usr/lib/jvm/java-8-openjdk-amd64/include', '8'),
|
|
||||||
]
|
|
||||||
|
|
||||||
# Test non-windows/non-macos globs
|
|
||||||
for (wjd, version) in non_win_java_include_dirs:
|
|
||||||
match = False
|
|
||||||
globs_tried = []
|
|
||||||
for jlig in java_linux_include_dirs_glob:
|
|
||||||
globs_tried.append(jlig)
|
|
||||||
|
|
||||||
if fnmatch.fnmatch(wjd, jlig):
|
|
||||||
match = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if not match:
|
|
||||||
self.fail(
|
|
||||||
"Didn't properly match %s with pattern %s" % (wjd, globs_tried)
|
|
||||||
)
|
|
||||||
|
|
||||||
match = False
|
|
||||||
globs_tried = []
|
|
||||||
for jlvig in java_linux_version_include_dirs_glob:
|
|
||||||
globs_tried.append(jlvig % version)
|
|
||||||
if fnmatch.fnmatch(wjd, jlvig % version):
|
|
||||||
match = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if not match:
|
|
||||||
self.fail(
|
|
||||||
"Didn't properly match %s with version (%s) specific pattern %s"
|
|
||||||
% (wjd, version, globs_tried)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Test macos globs
|
|
||||||
# Test windows globs
|
|
||||||
macos_java_dirs = [
|
|
||||||
# ('/System/Library/Frameworks/JavaVM.framework/Headers/', None),
|
|
||||||
(
|
|
||||||
'/System/Library/Frameworks/JavaVM.framework/Versions/11.0.2/Headers/',
|
|
||||||
'11.0.2',
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
if not fnmatch.fnmatch(
|
|
||||||
'/System/Library/Frameworks/JavaVM.framework/Headers/',
|
|
||||||
java_macos_include_dir_glob,
|
|
||||||
):
|
|
||||||
self.fail(
|
|
||||||
"Didn't properly match %s with pattern %s"
|
|
||||||
% (
|
|
||||||
'/System/Library/Frameworks/JavaVM.framework/Headers/',
|
|
||||||
java_macos_include_dir_glob,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
for (wjd, version) in macos_java_dirs:
|
|
||||||
if not fnmatch.fnmatch(wjd, java_macos_version_include_dir_glob % version):
|
|
||||||
self.fail(
|
|
||||||
"Didn't properly match %s with version (%s) specific pattern %s"
|
|
||||||
% (wjd, version, java_macos_version_include_dir_glob % version)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
||||||
|
|
||||||
# Local Variables:
|
|
||||||
# tab-width:4
|
|
||||||
# indent-tabs-mode:nil
|
|
||||||
# End:
|
|
||||||
# vim: set expandtab tabstop=4 shiftwidth=4:
|
|
@ -774,8 +774,6 @@ def tool_list(platform, env):
|
|||||||
'lex', 'yacc',
|
'lex', 'yacc',
|
||||||
# Foreign function interface
|
# Foreign function interface
|
||||||
'rpcgen', 'swig',
|
'rpcgen', 'swig',
|
||||||
# Java
|
|
||||||
'jar', 'javac', 'javah', 'rmic',
|
|
||||||
# Archivers
|
# Archivers
|
||||||
'tar', 'zip',
|
'tar', 'zip',
|
||||||
# File builders (text)
|
# File builders (text)
|
||||||
|
@ -1,256 +0,0 @@
|
|||||||
# MIT License
|
|
||||||
#
|
|
||||||
# Copyright The SCons Foundation
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
"""Tool-specific initialization for jar.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
from typing import List
|
|
||||||
|
|
||||||
import SCons.Node
|
|
||||||
import SCons.Node.FS
|
|
||||||
import SCons.Subst
|
|
||||||
import SCons.Tool
|
|
||||||
import SCons.Util
|
|
||||||
import SCons.Warnings
|
|
||||||
from SCons.Node.FS import _my_normcase
|
|
||||||
from SCons.Tool.JavaCommon import get_java_install_dirs
|
|
||||||
|
|
||||||
|
|
||||||
def jarSources(target, source, env, for_signature) -> List[str]:
|
|
||||||
"""Only include sources that are not a manifest file."""
|
|
||||||
try:
|
|
||||||
env['JARCHDIR']
|
|
||||||
except KeyError:
|
|
||||||
jarchdir_set = False
|
|
||||||
else:
|
|
||||||
jarchdir_set = True
|
|
||||||
jarchdir = env.subst('$JARCHDIR', target=target, source=source)
|
|
||||||
if jarchdir:
|
|
||||||
jarchdir = env.fs.Dir(jarchdir)
|
|
||||||
result = []
|
|
||||||
for src in source:
|
|
||||||
contents = src.get_text_contents()
|
|
||||||
if contents.startswith("Manifest-Version"):
|
|
||||||
continue
|
|
||||||
if jarchdir_set:
|
|
||||||
_chdir = jarchdir
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
_chdir = src.attributes.java_classdir
|
|
||||||
except AttributeError:
|
|
||||||
_chdir = None
|
|
||||||
if _chdir:
|
|
||||||
# If we are changing the dir with -C, then sources should
|
|
||||||
# be relative to that directory.
|
|
||||||
src = SCons.Subst.Literal(src.get_path(_chdir))
|
|
||||||
result.append('-C')
|
|
||||||
result.append(_chdir)
|
|
||||||
result.append(src)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def jarManifest(target, source, env, for_signature):
|
|
||||||
"""Look in sources for a manifest file, if any."""
|
|
||||||
for src in source:
|
|
||||||
contents = src.get_text_contents()
|
|
||||||
if contents.startswith("Manifest-Version"):
|
|
||||||
return src
|
|
||||||
return ''
|
|
||||||
|
|
||||||
def jarFlags(target, source, env, for_signature) -> str:
|
|
||||||
"""If we have a manifest, make sure that the 'm'
|
|
||||||
flag is specified."""
|
|
||||||
jarflags = env.subst('$JARFLAGS', target=target, source=source)
|
|
||||||
for src in source:
|
|
||||||
contents = src.get_text_contents()
|
|
||||||
if contents.startswith("Manifest-Version"):
|
|
||||||
if 'm' not in jarflags:
|
|
||||||
return jarflags + 'm'
|
|
||||||
break
|
|
||||||
return jarflags
|
|
||||||
|
|
||||||
def Jar(env, target=None, source=[], *args, **kw):
|
|
||||||
"""The Jar Builder.
|
|
||||||
|
|
||||||
This is a pseudo-Builder wrapper around the separate jar builders
|
|
||||||
depending on whether the sources are a file list or a directory.
|
|
||||||
"""
|
|
||||||
# TODO: W1113: Keyword argument before variable positional arguments list in the definition of Jar function
|
|
||||||
# TODO: W0102: Dangerous default value [] as argument
|
|
||||||
|
|
||||||
# jar target should not be a list so assume they passed
|
|
||||||
# no target and want implicit target to be made and the arg
|
|
||||||
# was actaully the list of sources
|
|
||||||
if SCons.Util.is_List(target) and source == []:
|
|
||||||
SCons.Warnings.warn(
|
|
||||||
SCons.Warnings.SConsWarning,
|
|
||||||
"Making implicit target jar file, and treating the list as sources"
|
|
||||||
)
|
|
||||||
source = target
|
|
||||||
target = None
|
|
||||||
|
|
||||||
# mutiple targets passed so build each target the same from the
|
|
||||||
# same source
|
|
||||||
#TODO Maybe this should only be done once, and the result copied
|
|
||||||
# for each target since it should result in the same?
|
|
||||||
if SCons.Util.is_List(target) and SCons.Util.is_List(source):
|
|
||||||
jars = []
|
|
||||||
for single_target in target:
|
|
||||||
jars += env.Jar(target=single_target, source=source, *args, **kw)
|
|
||||||
return jars
|
|
||||||
|
|
||||||
# they passed no target so make a target implicitly
|
|
||||||
if target is None:
|
|
||||||
try:
|
|
||||||
# make target from the first source file
|
|
||||||
target = os.path.splitext(str(source[0]))[0] + env.subst('$JARSUFFIX')
|
|
||||||
except:
|
|
||||||
# TODO: W0702: No exception type(s) specified
|
|
||||||
# something strange is happening but attempt anyways
|
|
||||||
SCons.Warnings.warn(
|
|
||||||
SCons.Warnings.SConsWarning,
|
|
||||||
"Could not make implicit target from sources, using directory"
|
|
||||||
)
|
|
||||||
target = os.path.basename(str(env.Dir('.'))) + env.subst('$JARSUFFIX')
|
|
||||||
|
|
||||||
# make lists out of our target and sources
|
|
||||||
if not SCons.Util.is_List(target):
|
|
||||||
target = [target]
|
|
||||||
if not SCons.Util.is_List(source):
|
|
||||||
source = [source]
|
|
||||||
|
|
||||||
# setup for checking through all the sources and handle accordingly
|
|
||||||
java_class_suffix = env.subst('$JAVACLASSSUFFIX')
|
|
||||||
java_suffix = env.subst('$JAVASUFFIX')
|
|
||||||
target_nodes = []
|
|
||||||
|
|
||||||
# function for determining what to do with a file and not a directory
|
|
||||||
# if its already a class file then it can be used as a
|
|
||||||
# source for jar, otherwise turn it into a class file then
|
|
||||||
# return the source
|
|
||||||
def file_to_class(src):
|
|
||||||
if _my_normcase(str(src)).endswith(java_suffix):
|
|
||||||
return env.JavaClassFile(source=src, *args, **kw)
|
|
||||||
return [env.fs.File(src)]
|
|
||||||
|
|
||||||
# function for calling the JavaClassDir builder if a directory is
|
|
||||||
# passed as a source to Jar builder. The JavaClassDir builder will
|
|
||||||
# return an empty list if there were no target classes built from
|
|
||||||
# the directory, in this case assume the user wanted the directory
|
|
||||||
# copied into the jar as is (it contains other files such as
|
|
||||||
# resources or class files compiled from prior commands)
|
|
||||||
# TODO: investigate the expexcted behavior for directories that
|
|
||||||
# have mixed content, such as Java files along side other files
|
|
||||||
# files.
|
|
||||||
def dir_to_class(src):
|
|
||||||
dir_targets = env.JavaClassDir(source=src, *args, **kw)
|
|
||||||
if dir_targets == []:
|
|
||||||
# no classes files could be built from the source dir
|
|
||||||
# so pass the dir as is.
|
|
||||||
return [env.fs.Dir(src)]
|
|
||||||
return dir_targets
|
|
||||||
|
|
||||||
# loop through the sources and handle each accordingly
|
|
||||||
# the goal here is to get all the source files into a class
|
|
||||||
# file or a directory that contains class files
|
|
||||||
for src in SCons.Util.flatten(source):
|
|
||||||
src = env.subst(src)
|
|
||||||
if isinstance(src, SCons.Node.FS.Base):
|
|
||||||
if isinstance(src, SCons.Node.FS.File):
|
|
||||||
# found a file so make sure its a class file
|
|
||||||
target_nodes.extend(file_to_class(src))
|
|
||||||
else:
|
|
||||||
# found a dir so get the class files out of it
|
|
||||||
target_nodes.extend(dir_to_class(src))
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
# source is string try to convert it to file
|
|
||||||
target_nodes.extend(file_to_class(env.fs.File(src)))
|
|
||||||
continue
|
|
||||||
except:
|
|
||||||
# TODO: W0702: No exception type(s) specified
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
# source is string try to covnert it to dir
|
|
||||||
target_nodes.extend(dir_to_class(env.fs.Dir(src)))
|
|
||||||
continue
|
|
||||||
except:
|
|
||||||
# TODO: W0702: No exception type(s) specified
|
|
||||||
pass
|
|
||||||
|
|
||||||
SCons.Warnings.warn(
|
|
||||||
SCons.Warnings.SConsWarning,
|
|
||||||
("File: " + str(src)
|
|
||||||
+ " could not be identified as File or Directory, skipping.")
|
|
||||||
)
|
|
||||||
|
|
||||||
# at this point all our sources have been converted to classes or
|
|
||||||
# directories of class so pass it to the Jar builder
|
|
||||||
return env.JarFile(target=target, source=target_nodes, *args, **kw)
|
|
||||||
|
|
||||||
def generate(env) -> None:
|
|
||||||
"""Add Builders and construction variables for jar to an Environment."""
|
|
||||||
SCons.Tool.CreateJarBuilder(env)
|
|
||||||
|
|
||||||
SCons.Tool.CreateJavaFileBuilder(env)
|
|
||||||
SCons.Tool.CreateJavaClassFileBuilder(env)
|
|
||||||
SCons.Tool.CreateJavaClassDirBuilder(env)
|
|
||||||
|
|
||||||
env.AddMethod(Jar)
|
|
||||||
|
|
||||||
if env['PLATFORM'] == 'win32':
|
|
||||||
# Ensure that we have a proper path for jar
|
|
||||||
paths = get_java_install_dirs('win32')
|
|
||||||
jar = SCons.Tool.find_program_path(env, 'jar', default_paths=paths)
|
|
||||||
if jar:
|
|
||||||
jar_bin_dir = os.path.dirname(jar)
|
|
||||||
env.AppendENVPath('PATH', jar_bin_dir)
|
|
||||||
|
|
||||||
env['JAR'] = 'jar'
|
|
||||||
env['JARFLAGS'] = SCons.Util.CLVar('cf')
|
|
||||||
env['_JARFLAGS'] = jarFlags
|
|
||||||
env['_JARMANIFEST'] = jarManifest
|
|
||||||
env['_JARSOURCES'] = jarSources
|
|
||||||
env['_JARCOM'] = '$JAR $_JARFLAGS $TARGET $_JARMANIFEST $_JARSOURCES'
|
|
||||||
env['JARCOM'] = "${TEMPFILE('$_JARCOM','$JARCOMSTR')}"
|
|
||||||
env['JARSUFFIX'] = '.jar'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
# As reported by Jan Nijtmans in issue #2730, the simple
|
|
||||||
# return env.Detect('jar')
|
|
||||||
# doesn't always work during initialization. For now, we
|
|
||||||
# stop trying to detect an executable (analogous to the
|
|
||||||
# javac Builder).
|
|
||||||
# TODO: Come up with a proper detect() routine...and enable it.
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Local Variables:
|
|
||||||
# tab-width:4
|
|
||||||
# indent-tabs-mode:nil
|
|
||||||
# End:
|
|
||||||
# vim: set expandtab tabstop=4 shiftwidth=4:
|
|
@ -1,249 +0,0 @@
|
|||||||
# MIT License
|
|
||||||
#
|
|
||||||
# Copyright The SCons Foundation
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
"""SCons.Tool.javac
|
|
||||||
|
|
||||||
Tool-specific initialization for javac.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
from collections import OrderedDict
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Builder
|
|
||||||
from SCons.Node.FS import _my_normcase
|
|
||||||
from SCons.Tool.JavaCommon import parse_java_file, get_java_install_dirs, get_java_include_paths
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
def classname(path):
|
|
||||||
"""Turn a string (path name) into a Java class name."""
|
|
||||||
return os.path.normpath(path).replace(os.sep, '.')
|
|
||||||
|
|
||||||
def emit_java_classes(target, source, env):
|
|
||||||
"""Create and return lists of source java files
|
|
||||||
and their corresponding target class files.
|
|
||||||
"""
|
|
||||||
java_suffix = env.get('JAVASUFFIX', '.java')
|
|
||||||
class_suffix = env.get('JAVACLASSSUFFIX', '.class')
|
|
||||||
|
|
||||||
target[0].must_be_same(SCons.Node.FS.Dir)
|
|
||||||
classdir = target[0]
|
|
||||||
|
|
||||||
s = source[0].rentry().disambiguate()
|
|
||||||
if isinstance(s, SCons.Node.FS.File):
|
|
||||||
sourcedir = s.dir.rdir()
|
|
||||||
elif isinstance(s, SCons.Node.FS.Dir):
|
|
||||||
sourcedir = s.rdir()
|
|
||||||
else:
|
|
||||||
raise SCons.Errors.UserError("Java source must be File or Dir, not '%s'" % s.__class__)
|
|
||||||
|
|
||||||
slist = []
|
|
||||||
js = _my_normcase(java_suffix)
|
|
||||||
for entry in source:
|
|
||||||
entry = entry.rentry().disambiguate()
|
|
||||||
if isinstance(entry, SCons.Node.FS.File):
|
|
||||||
slist.append(entry)
|
|
||||||
elif isinstance(entry, SCons.Node.FS.Dir):
|
|
||||||
result = OrderedDict()
|
|
||||||
dirnode = entry.rdir()
|
|
||||||
def find_java_files(arg, dirpath, filenames):
|
|
||||||
java_files = sorted([n for n in filenames
|
|
||||||
if _my_normcase(n).endswith(js)])
|
|
||||||
mydir = dirnode.Dir(dirpath)
|
|
||||||
java_paths = [mydir.File(f) for f in java_files]
|
|
||||||
for jp in java_paths:
|
|
||||||
arg[jp] = True
|
|
||||||
for dirpath, dirnames, filenames in os.walk(dirnode.get_abspath()):
|
|
||||||
find_java_files(result, dirpath, filenames)
|
|
||||||
entry.walk(find_java_files, result)
|
|
||||||
|
|
||||||
slist.extend(list(result.keys()))
|
|
||||||
else:
|
|
||||||
raise SCons.Errors.UserError("Java source must be File or Dir, not '%s'" % entry.__class__)
|
|
||||||
|
|
||||||
version = env.get('JAVAVERSION', '1.4')
|
|
||||||
full_tlist = []
|
|
||||||
for f in slist:
|
|
||||||
tlist = []
|
|
||||||
source_file_based = True
|
|
||||||
pkg_dir = None
|
|
||||||
if not f.is_derived():
|
|
||||||
pkg_dir, classes = parse_java_file(f.rfile().get_abspath(), version)
|
|
||||||
if classes:
|
|
||||||
source_file_based = False
|
|
||||||
if pkg_dir:
|
|
||||||
d = target[0].Dir(pkg_dir)
|
|
||||||
p = pkg_dir + os.sep
|
|
||||||
else:
|
|
||||||
d = target[0]
|
|
||||||
p = ''
|
|
||||||
for c in classes:
|
|
||||||
t = d.File(c + class_suffix)
|
|
||||||
t.attributes.java_classdir = classdir
|
|
||||||
t.attributes.java_sourcedir = sourcedir
|
|
||||||
t.attributes.java_classname = classname(p + c)
|
|
||||||
tlist.append(t)
|
|
||||||
|
|
||||||
if source_file_based:
|
|
||||||
base = f.name[:-len(java_suffix)]
|
|
||||||
if pkg_dir:
|
|
||||||
t = target[0].Dir(pkg_dir).File(base + class_suffix)
|
|
||||||
else:
|
|
||||||
t = target[0].File(base + class_suffix)
|
|
||||||
t.attributes.java_classdir = classdir
|
|
||||||
t.attributes.java_sourcedir = f.dir
|
|
||||||
t.attributes.java_classname = classname(base)
|
|
||||||
tlist.append(t)
|
|
||||||
|
|
||||||
for t in tlist:
|
|
||||||
t.set_specific_source([f])
|
|
||||||
|
|
||||||
full_tlist.extend(tlist)
|
|
||||||
|
|
||||||
return full_tlist, slist
|
|
||||||
|
|
||||||
JavaAction = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR')
|
|
||||||
|
|
||||||
JavaBuilder = SCons.Builder.Builder(action = JavaAction,
|
|
||||||
emitter = emit_java_classes,
|
|
||||||
target_factory = SCons.Node.FS.Entry,
|
|
||||||
source_factory = SCons.Node.FS.Entry)
|
|
||||||
|
|
||||||
class pathopt:
|
|
||||||
"""
|
|
||||||
Callable object for generating javac-style path options from
|
|
||||||
a construction variable (e.g. -classpath, -sourcepath).
|
|
||||||
"""
|
|
||||||
def __init__(self, opt, var, default=None):
|
|
||||||
self.opt = opt
|
|
||||||
self.var = var
|
|
||||||
self.default = default
|
|
||||||
|
|
||||||
def __call__(self, target, source, env, for_signature):
|
|
||||||
path = env[self.var]
|
|
||||||
if path and not SCons.Util.is_List(path):
|
|
||||||
path = [path]
|
|
||||||
if self.default:
|
|
||||||
default = env[self.default]
|
|
||||||
if default:
|
|
||||||
if not SCons.Util.is_List(default):
|
|
||||||
default = [default]
|
|
||||||
path = path + default
|
|
||||||
if path:
|
|
||||||
return [self.opt, os.pathsep.join(map(str, path))]
|
|
||||||
else:
|
|
||||||
return []
|
|
||||||
|
|
||||||
def Java(env, target, source, *args, **kw):
|
|
||||||
"""
|
|
||||||
A pseudo-Builder wrapper around the separate JavaClass{File,Dir}
|
|
||||||
Builders.
|
|
||||||
"""
|
|
||||||
if not SCons.Util.is_List(target):
|
|
||||||
target = [target]
|
|
||||||
if not SCons.Util.is_List(source):
|
|
||||||
source = [source]
|
|
||||||
|
|
||||||
# Pad the target list with repetitions of the last element in the
|
|
||||||
# list so we have a target for every source element.
|
|
||||||
target = target + ([target[-1]] * (len(source) - len(target)))
|
|
||||||
|
|
||||||
java_suffix = env.subst('$JAVASUFFIX')
|
|
||||||
result = []
|
|
||||||
|
|
||||||
for t, s in zip(target, source):
|
|
||||||
if isinstance(s, SCons.Node.FS.Base):
|
|
||||||
if isinstance(s, SCons.Node.FS.File):
|
|
||||||
b = env.JavaClassFile
|
|
||||||
else:
|
|
||||||
b = env.JavaClassDir
|
|
||||||
else:
|
|
||||||
if os.path.isfile(s):
|
|
||||||
b = env.JavaClassFile
|
|
||||||
elif os.path.isdir(s):
|
|
||||||
b = env.JavaClassDir
|
|
||||||
elif s[-len(java_suffix):] == java_suffix:
|
|
||||||
b = env.JavaClassFile
|
|
||||||
else:
|
|
||||||
b = env.JavaClassDir
|
|
||||||
result.extend(b(t, s, *args, **kw))
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for javac to an Environment."""
|
|
||||||
java_file = SCons.Tool.CreateJavaFileBuilder(env)
|
|
||||||
java_class = SCons.Tool.CreateJavaClassFileBuilder(env)
|
|
||||||
java_class_dir = SCons.Tool.CreateJavaClassDirBuilder(env)
|
|
||||||
java_class.add_emitter(None, emit_java_classes)
|
|
||||||
java_class.add_emitter(env.subst('$JAVASUFFIX'), emit_java_classes)
|
|
||||||
java_class_dir.emitter = emit_java_classes
|
|
||||||
|
|
||||||
env.AddMethod(Java)
|
|
||||||
|
|
||||||
version = env.get('JAVAVERSION', None)
|
|
||||||
|
|
||||||
if env['PLATFORM'] == 'win32':
|
|
||||||
# Ensure that we have a proper path for javac
|
|
||||||
paths = get_java_install_dirs('win32', version=version)
|
|
||||||
javac = SCons.Tool.find_program_path(env, 'javac', default_paths=paths)
|
|
||||||
if javac:
|
|
||||||
javac_bin_dir = os.path.dirname(javac)
|
|
||||||
env.AppendENVPath('PATH', javac_bin_dir)
|
|
||||||
else:
|
|
||||||
javac = SCons.Tool.find_program_path(env, 'javac')
|
|
||||||
|
|
||||||
|
|
||||||
env.SetDefault(
|
|
||||||
JAVAC='javac',
|
|
||||||
JAVACFLAGS=SCons.Util.CLVar(''),
|
|
||||||
JAVAINCLUDES=get_java_include_paths(env, javac, version),
|
|
||||||
JAVACLASSSUFFIX='.class',
|
|
||||||
JAVASUFFIX='.java',
|
|
||||||
JAVABOOTCLASSPATH=[],
|
|
||||||
JAVACLASSPATH=[],
|
|
||||||
JAVASOURCEPATH=[],
|
|
||||||
)
|
|
||||||
env['_javapathopt'] = pathopt
|
|
||||||
env['_JAVABOOTCLASSPATH'] = '${_javapathopt("-bootclasspath", "JAVABOOTCLASSPATH")} '
|
|
||||||
env['_JAVACLASSPATH'] = '${_javapathopt("-classpath", "JAVACLASSPATH")} '
|
|
||||||
env['_JAVASOURCEPATH'] = '${_javapathopt("-sourcepath", "JAVASOURCEPATH", "_JAVASOURCEPATHDEFAULT")} '
|
|
||||||
env['_JAVASOURCEPATHDEFAULT'] = '${TARGET.attributes.java_sourcedir}'
|
|
||||||
env['_JAVACCOM'] = '$JAVAC $JAVACFLAGS $_JAVABOOTCLASSPATH $_JAVACLASSPATH -d ${TARGET.attributes.java_classdir} $_JAVASOURCEPATH $SOURCES'
|
|
||||||
env['JAVACCOM'] = "${TEMPFILE('$_JAVACCOM','$JAVACCOMSTR')}"
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return 1
|
|
||||||
|
|
||||||
# Local Variables:
|
|
||||||
# tab-width:4
|
|
||||||
# indent-tabs-mode:nil
|
|
||||||
# End:
|
|
||||||
# vim: set expandtab tabstop=4 shiftwidth=4:
|
|
@ -1,102 +0,0 @@
|
|||||||
#
|
|
||||||
# __COPYRIGHT__
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
import os
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import SCons.Tool.javac
|
|
||||||
|
|
||||||
class DummyNode:
|
|
||||||
def __init__(self, val):
|
|
||||||
self.val = val
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return str(self.val)
|
|
||||||
|
|
||||||
class pathoptTestCase(unittest.TestCase):
|
|
||||||
def assert_pathopt(self, expect, path):
|
|
||||||
popt = SCons.Tool.javac.pathopt('-foopath', 'FOOPATH')
|
|
||||||
env = {'FOOPATH': path}
|
|
||||||
actual = popt(None, None, env, None)
|
|
||||||
self.assertEqual(expect, actual)
|
|
||||||
|
|
||||||
def assert_pathopt_default(self, expect, path, default):
|
|
||||||
popt = SCons.Tool.javac.pathopt('-foopath', 'FOOPATH', default='DPATH')
|
|
||||||
env = {'FOOPATH': path,
|
|
||||||
'DPATH': default}
|
|
||||||
actual = popt(None, None, env, None)
|
|
||||||
self.assertEqual(expect, actual)
|
|
||||||
|
|
||||||
def test_unset(self):
|
|
||||||
self.assert_pathopt([], None)
|
|
||||||
self.assert_pathopt([], '')
|
|
||||||
|
|
||||||
def test_str(self):
|
|
||||||
self.assert_pathopt(['-foopath', '/foo/bar'],
|
|
||||||
'/foo/bar')
|
|
||||||
|
|
||||||
def test_list_str(self):
|
|
||||||
self.assert_pathopt(['-foopath', '/foo%s/bar' % os.pathsep],
|
|
||||||
['/foo', '/bar'])
|
|
||||||
|
|
||||||
def test_uses_pathsep(self):
|
|
||||||
save = os.pathsep
|
|
||||||
try:
|
|
||||||
os.pathsep = '!'
|
|
||||||
self.assert_pathopt(['-foopath', 'foo!bar'],
|
|
||||||
['foo', 'bar'])
|
|
||||||
finally:
|
|
||||||
os.pathsep = save
|
|
||||||
|
|
||||||
def test_node(self):
|
|
||||||
self.assert_pathopt(['-foopath', '/foo'],
|
|
||||||
DummyNode('/foo'))
|
|
||||||
|
|
||||||
def test_list_node(self):
|
|
||||||
self.assert_pathopt(['-foopath', os.pathsep.join(['/foo','/bar'])],
|
|
||||||
['/foo', DummyNode('/bar')])
|
|
||||||
|
|
||||||
def test_default_str(self):
|
|
||||||
self.assert_pathopt_default(
|
|
||||||
['-foopath', os.pathsep.join(['/foo','/bar','/baz'])],
|
|
||||||
['/foo', '/bar'],
|
|
||||||
'/baz')
|
|
||||||
|
|
||||||
def test_default_list(self):
|
|
||||||
self.assert_pathopt_default(
|
|
||||||
['-foopath', os.pathsep.join(['/foo','/bar','/baz'])],
|
|
||||||
['/foo', '/bar'],
|
|
||||||
['/baz'])
|
|
||||||
|
|
||||||
def test_default_unset(self):
|
|
||||||
self.assert_pathopt_default(
|
|
||||||
['-foopath', '/foo'],
|
|
||||||
'/foo',
|
|
||||||
None)
|
|
||||||
self.assert_pathopt_default(
|
|
||||||
['-foopath', '/foo'],
|
|
||||||
'/foo',
|
|
||||||
'')
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
@ -1,148 +0,0 @@
|
|||||||
# MIT License
|
|
||||||
#
|
|
||||||
# Copyright The SCons Foundation
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
"""SCons.Tool.javah
|
|
||||||
|
|
||||||
Tool-specific initialization for javah.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Builder
|
|
||||||
import SCons.Node.FS
|
|
||||||
import SCons.Tool.javac
|
|
||||||
import SCons.Util
|
|
||||||
from SCons.Tool.JavaCommon import get_java_install_dirs
|
|
||||||
|
|
||||||
|
|
||||||
def emit_java_headers(target, source, env):
|
|
||||||
"""Create and return lists of Java stub header files that will
|
|
||||||
be created from a set of class files.
|
|
||||||
"""
|
|
||||||
class_suffix = env.get('JAVACLASSSUFFIX', '.class')
|
|
||||||
classdir = env.get('JAVACLASSDIR')
|
|
||||||
|
|
||||||
if not classdir:
|
|
||||||
try:
|
|
||||||
s = source[0]
|
|
||||||
except IndexError:
|
|
||||||
classdir = '.'
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
classdir = s.attributes.java_classdir
|
|
||||||
except AttributeError:
|
|
||||||
classdir = '.'
|
|
||||||
classdir = env.Dir(classdir).rdir()
|
|
||||||
|
|
||||||
if str(classdir) == '.':
|
|
||||||
c_ = None
|
|
||||||
else:
|
|
||||||
c_ = str(classdir) + os.sep
|
|
||||||
|
|
||||||
slist = []
|
|
||||||
for src in source:
|
|
||||||
try:
|
|
||||||
classname = src.attributes.java_classname
|
|
||||||
except AttributeError:
|
|
||||||
classname = str(src)
|
|
||||||
if c_ and classname[:len(c_)] == c_:
|
|
||||||
classname = classname[len(c_):]
|
|
||||||
if class_suffix and classname[-len(class_suffix):] == class_suffix:
|
|
||||||
classname = classname[:-len(class_suffix)]
|
|
||||||
classname = SCons.Tool.javac.classname(classname)
|
|
||||||
s = src.rfile()
|
|
||||||
s.attributes.java_classname = classname
|
|
||||||
slist.append(s)
|
|
||||||
|
|
||||||
s = source[0].rfile()
|
|
||||||
if not hasattr(s.attributes, 'java_classdir'):
|
|
||||||
s.attributes.java_classdir = classdir
|
|
||||||
|
|
||||||
if target[0].__class__ is SCons.Node.FS.File:
|
|
||||||
tlist = target
|
|
||||||
else:
|
|
||||||
if not isinstance(target[0], SCons.Node.FS.Dir):
|
|
||||||
target[0].__class__ = SCons.Node.FS.Dir
|
|
||||||
target[0]._morph()
|
|
||||||
tlist = []
|
|
||||||
for s in source:
|
|
||||||
fname = s.attributes.java_classname.replace('.', '_') + '.h'
|
|
||||||
t = target[0].File(fname)
|
|
||||||
t.attributes.java_lookupdir = target[0]
|
|
||||||
tlist.append(t)
|
|
||||||
|
|
||||||
return tlist, source
|
|
||||||
|
|
||||||
def JavaHOutFlagGenerator(target, source, env, for_signature):
|
|
||||||
try:
|
|
||||||
t = target[0]
|
|
||||||
except (AttributeError, IndexError, TypeError):
|
|
||||||
t = target
|
|
||||||
try:
|
|
||||||
return '-d ' + str(t.attributes.java_lookupdir)
|
|
||||||
except AttributeError:
|
|
||||||
return '-o ' + str(t)
|
|
||||||
|
|
||||||
def getJavaHClassPath(env,target, source, for_signature):
|
|
||||||
path = "${SOURCE.attributes.java_classdir}"
|
|
||||||
if 'JAVACLASSPATH' in env and env['JAVACLASSPATH']:
|
|
||||||
path = SCons.Util.AppendPath(path, env['JAVACLASSPATH'])
|
|
||||||
return "-classpath %s" % path
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for javah to an Environment."""
|
|
||||||
java_javah = SCons.Tool.CreateJavaHBuilder(env)
|
|
||||||
java_javah.emitter = emit_java_headers
|
|
||||||
|
|
||||||
if env['PLATFORM'] == 'win32':
|
|
||||||
# Ensure that we have a proper path for javah
|
|
||||||
paths = get_java_install_dirs('win32')
|
|
||||||
javah = SCons.Tool.find_program_path(env, 'javah', default_paths=paths)
|
|
||||||
if javah:
|
|
||||||
javah_bin_dir = os.path.dirname(javah)
|
|
||||||
env.AppendENVPath('PATH', javah_bin_dir)
|
|
||||||
|
|
||||||
env.SetDefault(
|
|
||||||
JAVAH='javah',
|
|
||||||
JAVAHFLAGS=SCons.Util.CLVar(''),
|
|
||||||
JAVACLASSSUFFIX='.class',
|
|
||||||
JAVASUFFIX='.java',
|
|
||||||
)
|
|
||||||
env['_JAVAHOUTFLAG'] = JavaHOutFlagGenerator
|
|
||||||
env['_JAVAHCLASSPATH'] = getJavaHClassPath
|
|
||||||
env['JAVAHCOM'] = '$JAVAH $JAVAHFLAGS $_JAVAHOUTFLAG $_JAVAHCLASSPATH ${SOURCES.attributes.java_classname}'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
return env.Detect('javah')
|
|
||||||
|
|
||||||
# Local Variables:
|
|
||||||
# tab-width:4
|
|
||||||
# indent-tabs-mode:nil
|
|
||||||
# End:
|
|
||||||
# vim: set expandtab tabstop=4 shiftwidth=4:
|
|
@ -1,139 +0,0 @@
|
|||||||
"""SCons.Tool.rmic
|
|
||||||
|
|
||||||
Tool-specific initialization for rmic.
|
|
||||||
|
|
||||||
There normally shouldn't be any need to import this module directly.
|
|
||||||
It will usually be imported through the generic SCons.Tool.Tool()
|
|
||||||
selection method.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#
|
|
||||||
# __COPYRIGHT__
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
|
|
||||||
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
import SCons.Action
|
|
||||||
import SCons.Builder
|
|
||||||
import SCons.Node.FS
|
|
||||||
import SCons.Util
|
|
||||||
|
|
||||||
from SCons.Tool.JavaCommon import get_java_install_dirs
|
|
||||||
|
|
||||||
|
|
||||||
def emit_rmic_classes(target, source, env):
|
|
||||||
"""Create and return lists of Java RMI stub and skeleton
|
|
||||||
class files to be created from a set of class files.
|
|
||||||
"""
|
|
||||||
class_suffix = env.get('JAVACLASSSUFFIX', '.class')
|
|
||||||
classdir = env.get('JAVACLASSDIR')
|
|
||||||
|
|
||||||
if not classdir:
|
|
||||||
try:
|
|
||||||
s = source[0]
|
|
||||||
except IndexError:
|
|
||||||
classdir = '.'
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
classdir = s.attributes.java_classdir
|
|
||||||
except AttributeError:
|
|
||||||
classdir = '.'
|
|
||||||
classdir = env.Dir(classdir).rdir()
|
|
||||||
if str(classdir) == '.':
|
|
||||||
c_ = None
|
|
||||||
else:
|
|
||||||
c_ = str(classdir) + os.sep
|
|
||||||
|
|
||||||
slist = []
|
|
||||||
for src in source:
|
|
||||||
try:
|
|
||||||
classname = src.attributes.java_classname
|
|
||||||
except AttributeError:
|
|
||||||
classname = str(src)
|
|
||||||
if c_ and classname[:len(c_)] == c_:
|
|
||||||
classname = classname[len(c_):]
|
|
||||||
if class_suffix and classname[:-len(class_suffix)] == class_suffix:
|
|
||||||
classname = classname[-len(class_suffix):]
|
|
||||||
s = src.rfile()
|
|
||||||
s.attributes.java_classdir = classdir
|
|
||||||
s.attributes.java_classname = classname
|
|
||||||
slist.append(s)
|
|
||||||
|
|
||||||
stub_suffixes = ['_Stub']
|
|
||||||
if env.get('JAVAVERSION') == '1.4':
|
|
||||||
stub_suffixes.append('_Skel')
|
|
||||||
|
|
||||||
tlist = []
|
|
||||||
for s in source:
|
|
||||||
for suff in stub_suffixes:
|
|
||||||
fname = s.attributes.java_classname.replace('.', os.sep) + \
|
|
||||||
suff + class_suffix
|
|
||||||
t = target[0].File(fname)
|
|
||||||
t.attributes.java_lookupdir = target[0]
|
|
||||||
tlist.append(t)
|
|
||||||
|
|
||||||
return tlist, source
|
|
||||||
|
|
||||||
RMICAction = SCons.Action.Action('$RMICCOM', '$RMICCOMSTR')
|
|
||||||
|
|
||||||
RMICBuilder = SCons.Builder.Builder(action = RMICAction,
|
|
||||||
emitter = emit_rmic_classes,
|
|
||||||
src_suffix = '$JAVACLASSSUFFIX',
|
|
||||||
target_factory = SCons.Node.FS.Dir,
|
|
||||||
source_factory = SCons.Node.FS.File)
|
|
||||||
|
|
||||||
def generate(env):
|
|
||||||
"""Add Builders and construction variables for rmic to an Environment."""
|
|
||||||
env['BUILDERS']['RMIC'] = RMICBuilder
|
|
||||||
|
|
||||||
if env['PLATFORM'] == 'win32':
|
|
||||||
version = env.get('JAVAVERSION', None)
|
|
||||||
# Ensure that we have a proper path for rmic
|
|
||||||
paths = get_java_install_dirs('win32', version=version)
|
|
||||||
rmic = SCons.Tool.find_program_path(env, 'rmic', default_paths=paths)
|
|
||||||
# print("RMIC: %s"%rmic)
|
|
||||||
if rmic:
|
|
||||||
rmic_bin_dir = os.path.dirname(rmic)
|
|
||||||
env.AppendENVPath('PATH', rmic_bin_dir)
|
|
||||||
|
|
||||||
env['RMIC'] = 'rmic'
|
|
||||||
env['RMICFLAGS'] = SCons.Util.CLVar('')
|
|
||||||
env['RMICCOM'] = '$RMIC $RMICFLAGS -d ${TARGET.attributes.java_lookupdir} -classpath ${SOURCE.attributes.java_classdir} ${SOURCES.attributes.java_classname}'
|
|
||||||
env['JAVACLASSSUFFIX'] = '.class'
|
|
||||||
|
|
||||||
def exists(env):
|
|
||||||
# As reported by Jan Nijtmans in issue #2730, the simple
|
|
||||||
# return env.Detect('rmic')
|
|
||||||
# doesn't always work during initialization. For now, we
|
|
||||||
# stop trying to detect an executable (analogous to the
|
|
||||||
# javac Builder).
|
|
||||||
# TODO: Come up with a proper detect() routine...and enable it.
|
|
||||||
return 1
|
|
||||||
|
|
||||||
# Local Variables:
|
|
||||||
# tab-width:4
|
|
||||||
# indent-tabs-mode:nil
|
|
||||||
# End:
|
|
||||||
# vim: set expandtab tabstop=4 shiftwidth=4:
|
|
Loading…
Reference in New Issue
Block a user