From 60b9c8300c7cb8f3b5afe1e01967f59420f23fb3 Mon Sep 17 00:00:00 2001 From: Niclas Moeslund Overby Date: Tue, 19 Jun 2018 17:24:57 +0200 Subject: [PATCH 1/4] java: implement java linking --- mesonbuild/backend/ninjabackend.py | 15 ++++++++++++++- mesonbuild/build.py | 11 ++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 94eaa4ff8..f0a755c52 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -970,7 +970,7 @@ int dummy; class_list = [] compiler = target.compilers['java'] c = 'c' - m = '' + m = 'm' e = '' f = 'f' main_class = target.get_main_class() @@ -980,11 +980,21 @@ int dummy; plain_class_path = self.generate_single_java_compile(src, target, compiler, outfile) class_list.append(plain_class_path) class_dep_list = [os.path.join(self.get_target_private_dir(target), i) for i in class_list] + manifest_path = os.path.join(self.get_target_private_dir(target), 'Manifest.txt') + os.makedirs(os.path.dirname(os.path.join(self.environment.get_build_dir(), manifest_path)), exist_ok=True) + with open(manifest_path, 'w') as manifest: + if any(target.link_targets): + manifest.write('Class-Path: ') + cp_paths = [os.path.join(self.get_target_dir(l), l.get_filename()) for l in target.link_targets] + manifest.write(' '.join(cp_paths)) + manifest.write('\n') jar_rule = 'java_LINKER' commands = [c + m + e + f] + commands.append(manifest_path) if e != '': commands.append(main_class) commands.append(self.get_target_filename(target)) + commands.append(manifest_path) # Java compilation can produce an arbitrary number of output # class files for a single source file. Thus tell jar to just # grab everything in the final package. @@ -1063,12 +1073,14 @@ int dummy; self.generate_generator_list_rules(target, outfile) def generate_single_java_compile(self, src, target, compiler, outfile): + deps = [os.path.join(self.get_target_dir(l), l.get_filename()) for l in target.link_targets] args = [] args += compiler.get_buildtype_args(self.get_option_for_target('buildtype', target)) args += self.build.get_global_args(compiler) args += self.build.get_project_args(compiler, target.subproject) args += target.get_java_args() args += compiler.get_output_args(self.get_target_private_dir(target)) + args += target.get_classpath_args() curdir = target.get_subdir() sourcepath = os.path.join(self.build_to_src, curdir) + os.pathsep sourcepath += os.path.normpath(curdir) + os.pathsep @@ -1080,6 +1092,7 @@ int dummy; plain_class_path = src.fname[:-4] + 'class' rel_obj = os.path.join(self.get_target_private_dir(target), plain_class_path) element = NinjaBuildElement(self.all_outputs, rel_obj, compiler.get_language() + '_COMPILER', rel_src) + element.add_dep(deps) element.add_item('ARGS', args) element.write(outfile) return plain_class_path diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 7d071e0b9..dc143266c 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1911,6 +1911,9 @@ class Jar(BuildTarget): for s in self.sources: if not s.endswith('.java'): raise InvalidArguments('Jar source %s is not a java file.' % s) + for t in self.link_targets: + if not isinstance(t, Jar): + raise InvalidArguments('Link target %s is not a jar target.' % t) self.filename = self.name + '.jar' self.outputs = [self.filename] self.java_args = kwargs.get('java_args', []) @@ -1928,6 +1931,13 @@ class Jar(BuildTarget): # All jar targets are installable. pass + def is_linkable_target(self): + return True + + def get_classpath_args(self): + cp_paths = [os.path.join(l.get_subdir(), l.get_filename()) for l in self.link_targets] + return ['-cp', os.pathsep.join(cp_paths)] + class CustomTargetIndex: """A special opaque object returned by indexing a CustomTarget. This object @@ -1950,7 +1960,6 @@ class CustomTargetIndex: def get_subdir(self): return self.target.get_subdir() - class ConfigureFile: def __init__(self, subdir, sourcename, targetname, configuration_data): From bc8239ded025d05d924e0e09b359941505e729b5 Mon Sep 17 00:00:00 2001 From: Niclas Moeslund Overby Date: Tue, 12 Jun 2018 13:43:25 +0200 Subject: [PATCH 2/4] java: add jar linking test --- mesonbuild/backend/ninjabackend.py | 6 +++--- test cases/java/7 linking/com/mesonbuild/Linking.java | 9 +++++++++ test cases/java/7 linking/meson.build | 8 ++++++++ .../java/7 linking/sub/com/mesonbuild/SimpleLib.java | 7 +++++++ test cases/java/7 linking/sub/meson.build | 2 ++ 5 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 test cases/java/7 linking/com/mesonbuild/Linking.java create mode 100644 test cases/java/7 linking/meson.build create mode 100644 test cases/java/7 linking/sub/com/mesonbuild/SimpleLib.java create mode 100644 test cases/java/7 linking/sub/meson.build diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index f0a755c52..88415e8cd 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -981,8 +981,9 @@ int dummy; class_list.append(plain_class_path) class_dep_list = [os.path.join(self.get_target_private_dir(target), i) for i in class_list] manifest_path = os.path.join(self.get_target_private_dir(target), 'Manifest.txt') - os.makedirs(os.path.dirname(os.path.join(self.environment.get_build_dir(), manifest_path)), exist_ok=True) - with open(manifest_path, 'w') as manifest: + manifest_fullpath = os.path.join(self.environment.get_build_dir(), manifest_path) + os.makedirs(os.path.dirname(manifest_fullpath), exist_ok=True) + with open(manifest_fullpath, 'w') as manifest: if any(target.link_targets): manifest.write('Class-Path: ') cp_paths = [os.path.join(self.get_target_dir(l), l.get_filename()) for l in target.link_targets] @@ -994,7 +995,6 @@ int dummy; if e != '': commands.append(main_class) commands.append(self.get_target_filename(target)) - commands.append(manifest_path) # Java compilation can produce an arbitrary number of output # class files for a single source file. Thus tell jar to just # grab everything in the final package. diff --git a/test cases/java/7 linking/com/mesonbuild/Linking.java b/test cases/java/7 linking/com/mesonbuild/Linking.java new file mode 100644 index 000000000..170e2aadb --- /dev/null +++ b/test cases/java/7 linking/com/mesonbuild/Linking.java @@ -0,0 +1,9 @@ +package com.mesonbuild; + +import com.mesonbuild.SimpleLib; + +class Linking { + public static void main(String [] args) { + SimpleLib.func(); + } +} diff --git a/test cases/java/7 linking/meson.build b/test cases/java/7 linking/meson.build new file mode 100644 index 000000000..0ae0db39a --- /dev/null +++ b/test cases/java/7 linking/meson.build @@ -0,0 +1,8 @@ +project('linkingjava', 'java') + +subdir('sub') + +javaprog = jar('myprog', 'com/mesonbuild/Linking.java', + main_class : 'com.mesonbuild.Linking', + link_with : simplelib) +test('mytest', javaprog) \ No newline at end of file diff --git a/test cases/java/7 linking/sub/com/mesonbuild/SimpleLib.java b/test cases/java/7 linking/sub/com/mesonbuild/SimpleLib.java new file mode 100644 index 000000000..835b2e4da --- /dev/null +++ b/test cases/java/7 linking/sub/com/mesonbuild/SimpleLib.java @@ -0,0 +1,7 @@ +package com.mesonbuild; + +public class SimpleLib { + public static void func() { + System.out.println("Java linking is working.\n"); + } +} diff --git a/test cases/java/7 linking/sub/meson.build b/test cases/java/7 linking/sub/meson.build new file mode 100644 index 000000000..13fd202ed --- /dev/null +++ b/test cases/java/7 linking/sub/meson.build @@ -0,0 +1,2 @@ +simplelib = jar('simplelib', + 'com/mesonbuild/SimpleLib.java') From c70a051e9352639440532ad969d9b7c215a3e699 Mon Sep 17 00:00:00 2001 From: Niclas Moeslund Overby Date: Mon, 2 Jul 2018 23:19:52 +0200 Subject: [PATCH 3/4] java: remove manifest classpath from installed jar --- mesonbuild/scripts/depfixer.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py index 40f47c0e6..d3d302821 100644 --- a/mesonbuild/scripts/depfixer.py +++ b/mesonbuild/scripts/depfixer.py @@ -396,11 +396,25 @@ def fix_darwin(fname, new_rpath, final_path, install_name_mappings): raise sys.exit(0) +def fix_jar(fname): + subprocess.check_call(['jar', 'xfv', fname, 'META-INF/MANIFEST.MF']) + with open('META-INF/MANIFEST.MF', 'r+') as f: + lines = f.readlines() + f.seek(0) + for line in lines: + if not line.startswith('Class-Path:'): + f.write(line) + f.truncate() + subprocess.check_call(['jar', 'ufm', fname, 'META-INF/MANIFEST.MF']) + def fix_rpath(fname, new_rpath, final_path, install_name_mappings, verbose=True): # Static libraries never have rpaths if fname.endswith('.a'): return try: + if fname.endswith('.jar'): + fix_jar(fname) + return fix_elf(fname, new_rpath, verbose) return except SystemExit as e: From 62a46a9b6ec042ab624dc3563b3c777371bb3ab6 Mon Sep 17 00:00:00 2001 From: Niclas Moeslund Overby Date: Tue, 3 Jul 2018 17:50:42 +0200 Subject: [PATCH 4/4] java: prevent creation of manifest duplicate in jar --- mesonbuild/backend/ninjabackend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 88415e8cd..3ee543d09 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -980,7 +980,7 @@ int dummy; plain_class_path = self.generate_single_java_compile(src, target, compiler, outfile) class_list.append(plain_class_path) class_dep_list = [os.path.join(self.get_target_private_dir(target), i) for i in class_list] - manifest_path = os.path.join(self.get_target_private_dir(target), 'Manifest.txt') + manifest_path = os.path.join(self.get_target_private_dir(target), 'META-INF', 'MANIFEST.MF') manifest_fullpath = os.path.join(self.environment.get_build_dir(), manifest_path) os.makedirs(os.path.dirname(manifest_fullpath), exist_ok=True) with open(manifest_fullpath, 'w') as manifest: