diff --git a/SCSCons/Script/MainTests.py b/SCSCons/Script/MainTests.py deleted file mode 100644 index f7e3263f2..000000000 --- a/SCSCons/Script/MainTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/Tool/JavaCommon.py b/SCSCons/Tool/JavaCommon.py deleted file mode 100644 index adec1d3a7..000000000 --- a/SCSCons/Tool/JavaCommon.py +++ /dev/null @@ -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: diff --git a/SCSCons/Tool/JavaCommonTests.py b/SCSCons/Tool/JavaCommonTests.py deleted file mode 100644 index 75e75efd6..000000000 --- a/SCSCons/Tool/JavaCommonTests.py +++ /dev/null @@ -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 comp = new Comparator() - { - 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: diff --git a/SCSCons/Tool/__init__.py b/SCSCons/Tool/__init__.py index b783912c0..8236739d4 100644 --- a/SCSCons/Tool/__init__.py +++ b/SCSCons/Tool/__init__.py @@ -774,8 +774,6 @@ def tool_list(platform, env): 'lex', 'yacc', # Foreign function interface 'rpcgen', 'swig', - # Java - 'jar', 'javac', 'javah', 'rmic', # Archivers 'tar', 'zip', # File builders (text) diff --git a/SCSCons/Tool/jar.py b/SCSCons/Tool/jar.py deleted file mode 100644 index ae44ff3bd..000000000 --- a/SCSCons/Tool/jar.py +++ /dev/null @@ -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: diff --git a/SCSCons/Tool/javac.py b/SCSCons/Tool/javac.py deleted file mode 100644 index 0c4f5356d..000000000 --- a/SCSCons/Tool/javac.py +++ /dev/null @@ -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: diff --git a/SCSCons/Tool/javacTests.py b/SCSCons/Tool/javacTests.py deleted file mode 100644 index ff0b8d4fd..000000000 --- a/SCSCons/Tool/javacTests.py +++ /dev/null @@ -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() diff --git a/SCSCons/Tool/javah.py b/SCSCons/Tool/javah.py deleted file mode 100644 index c5a75646e..000000000 --- a/SCSCons/Tool/javah.py +++ /dev/null @@ -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: diff --git a/SCSCons/Tool/rmic.py b/SCSCons/Tool/rmic.py deleted file mode 100644 index 5c7a04066..000000000 --- a/SCSCons/Tool/rmic.py +++ /dev/null @@ -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: