[PATCH] Patch `openjdk@9` so it builds on aarch64

  • Done
  • quality assurance status badge
Details
5 participants
  • Andreas Enge
  • burning2007
  • Maxim Cournoyer
  • Bruno Victal
  • Tim Johann
Owner
unassigned
Submitted by
burning2007
Severity
normal
B
B
burning2007 wrote on 25 Apr 2023 17:23
(address . guix-patches@gnu.org)(name . Anthony)(address . burning2007@ya.ru)
259180feeb7fa9f356b54f7edb44bce69375706d.1682435898.git.burning2007@ya.ru
From: Anthony <burning2007@ya.ru>

Patch openjdk9 so it can build on aarch64. Adapted from here:


I can confirm it builds on real hardware.

--
Anthony
---
gnu/packages/java.scm | 3 +
...19603c1546ce86fe659df3636b5a24b9caeb.patch | 371 ++++++++++++++++++
2 files changed, 374 insertions(+)
create mode 100644 gnu/packages/patches/opendjk-9-aarch64-a0a919603c1546ce86fe659df3636b5a24b9caeb.patch

Toggle diff (395 lines)
diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index de3a0003e5..d389b5a902 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -856,6 +856,9 @@ (define-public openjdk9
(uri (hg-reference (url "https://hg.openjdk.org/jdk/jdk")
(changeset "jdk-9+181")))
(file-name (hg-file-name name version))
+ (patches
+ (search-patches
+ "opendjk-9-aarch64-a0a919603c1546ce86fe659df3636b5a24b9caeb.patch"))
(modules '((guix build utils)))
(snippet `(begin
(for-each delete-file
diff --git a/gnu/packages/patches/opendjk-9-aarch64-a0a919603c1546ce86fe659df3636b5a24b9caeb.patch b/gnu/packages/patches/opendjk-9-aarch64-a0a919603c1546ce86fe659df3636b5a24b9caeb.patch
new file mode 100644
index 0000000000..c55a3253ee
--- /dev/null
+++ b/gnu/packages/patches/opendjk-9-aarch64-a0a919603c1546ce86fe659df3636b5a24b9caeb.patch
@@ -0,0 +1,371 @@
+From a0a919603c1546ce86fe659df3636b5a24b9caeb Mon Sep 17 00:00:00 2001
+From: Nick Gasson <ngasson@openjdk.org>
+Date: Mon, 17 Jun 2019 15:31:49 +0800
+Subject: [PATCH] 8224851: AArch64: fix warnings and errors with Clang and GCC
+ 8.3
+
+Reviewed-by: aph, kbarrett
+---
+ hotspot/src/cpu/aarch64/vm/aarch64.ad | 8 +--
+ hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp | 4 +-
+ .../cpu/aarch64/c1_LIRAssembler_aarch64.cpp | 12 ++--
+ .../cpu/aarch64/c1_LIRGenerator_aarch64.cpp | 4 +-
+ hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp | 10 +--
+ .../cpu/aarch64/interp_masm_aarch64.hpp | 2 -
+ .../cpu/aarch64/macroAssembler_aarch64.cpp | 2 +-
+ .../aarch64/macroAssembler_aarch64_log.cpp | 4 +-
+ .../aarch64/macroAssembler_aarch64_trig.cpp | 30 ++++-----
+ .../cpu/aarch64/vm_version_aarch64.cpp | 2 +-
+ .../linux_aarch64/atomic_linux_aarch64.hpp | 4 +-
+ .../os_cpu/linux_aarch64/copy_linux_aarch64.s | 2 +-
+ .../os_cpu/linux_aarch64/os_linux_aarch64.cpp | 61 ++++++-------------
+ 13 files changed, 62 insertions(+), 83 deletions(-)
+
+diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad
+index e6a1bc8bba98..a5afb2a08fef 100644
+--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad
++++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad
+@@ -14255,7 +14255,7 @@ instruct compF_reg_zero(rFlagsReg cr, vRegF src1, immF0 src2)
+ format %{ "fcmps $src1, 0.0" %}
+
+ ins_encode %{
+- __ fcmps(as_FloatRegister($src1$$reg), 0.0D);
++ __ fcmps(as_FloatRegister($src1$$reg), 0.0);
+ %}
+
+ ins_pipe(pipe_class_compare);
+@@ -14284,7 +14284,7 @@ instruct compD_reg_zero(rFlagsReg cr, vRegD src1, immD0 src2)
+ format %{ "fcmpd $src1, 0.0" %}
+
+ ins_encode %{
+- __ fcmpd(as_FloatRegister($src1$$reg), 0.0D);
++ __ fcmpd(as_FloatRegister($src1$$reg), 0.0);
+ %}
+
+ ins_pipe(pipe_class_compare);
+@@ -14360,7 +14360,7 @@ instruct compF3_reg_immF0(iRegINoSp dst, vRegF src1, immF0 zero, rFlagsReg cr)
+ Label done;
+ FloatRegister s1 = as_FloatRegister($src1$$reg);
+ Register d = as_Register($dst$$reg);
+- __ fcmps(s1, 0.0D);
++ __ fcmps(s1, 0.0);
+ // installs 0 if EQ else -1
+ __ csinvw(d, zr, zr, Assembler::EQ);
+ // keeps -1 if less or unordered else installs 1
+@@ -14387,7 +14387,7 @@ instruct compD3_reg_immD0(iRegINoSp dst, vRegD src1, immD0 zero, rFlagsReg cr)
+ Label done;
+ FloatRegister s1 = as_FloatRegister($src1$$reg);
+ Register d = as_Register($dst$$reg);
+- __ fcmpd(s1, 0.0D);
++ __ fcmpd(s1, 0.0);
+ // installs 0 if EQ else -1
+ __ csinvw(d, zr, zr, Assembler::EQ);
+ // keeps -1 if less or unordered else installs 1
+diff --git a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp
+index 3bb620d52e0a..a95417a467a9 100644
+--- a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp
++++ b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp
+@@ -276,7 +276,7 @@ class Instruction_aarch64 {
+ unsigned get(int msb = 31, int lsb = 0) {
+ int nbits = msb - lsb + 1;
+ unsigned mask = ((1U << nbits) - 1) << lsb;
+- assert_cond(bits & mask == mask);
++ assert_cond((bits & mask) == mask);
+ return (insn & mask) >> lsb;
+ }
+
+@@ -2644,7 +2644,7 @@ void mvnw(Register Rd, Register Rm,
+ // RBIT only allows T8B and T16B but encodes them oddly. Argh...
+ void rbit(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) {
+ assert((ASSERTION), MSG);
+- _rbit(Vd, SIMD_Arrangement(T & 1 | 0b010), Vn);
++ _rbit(Vd, SIMD_Arrangement((T & 1) | 0b010), Vn);
+ }
+ #undef ASSERTION
+
+diff --git a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp
+index 100b9e9c1154..eb013eb52be4 100644
+--- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp
++++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp
+@@ -1078,8 +1078,8 @@ void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) {
+ // Assembler::EQ does not permit unordered branches, so we add
+ // another branch here. Likewise, Assembler::NE does not permit
+ // ordered branches.
+- if (is_unordered && op->cond() == lir_cond_equal
+- || !is_unordered && op->cond() == lir_cond_notEqual)
++ if ((is_unordered && op->cond() == lir_cond_equal)
++ || (!is_unordered && op->cond() == lir_cond_notEqual))
+ __ br(Assembler::VS, *(op->ublock()->label()));
+ switch(op->cond()) {
+ case lir_cond_equal: acond = Assembler::EQ; break;
+@@ -1789,18 +1789,22 @@ void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr
+ switch (code) {
+ case lir_add: __ fadds (dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break;
+ case lir_sub: __ fsubs (dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break;
++ case lir_mul_strictfp: // fall through
+ case lir_mul: __ fmuls (dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break;
++ case lir_div_strictfp: // fall through
+ case lir_div: __ fdivs (dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break;
+ default:
+ ShouldNotReachHere();
+ }
+ } else if (left->is_double_fpu()) {
+ if (right->is_double_fpu()) {
+- // cpu register - cpu register
++ // fpu register - fpu register
+ switch (code) {
+ case lir_add: __ faddd (dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break;
+ case lir_sub: __ fsubd (dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break;
++ case lir_mul_strictfp: // fall through
+ case lir_mul: __ fmuld (dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break;
++ case lir_div_strictfp: // fall through
+ case lir_div: __ fdivd (dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break;
+ default:
+ ShouldNotReachHere();
+diff --git a/hotspot/src/cpu/aarch64/vm/c1_LIRGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/c1_LIRGenerator_aarch64.cpp
+index 19c9ea688f6d..185e93b99f93 100644
+--- a/hotspot/src/cpu/aarch64/vm/c1_LIRGenerator_aarch64.cpp
++++ b/hotspot/src/cpu/aarch64/vm/c1_LIRGenerator_aarch64.cpp
+@@ -426,7 +426,7 @@ void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) {
+ tmp = new_register(T_DOUBLE);
+ }
+
+- arithmetic_op_fpu(x->op(), reg, left.result(), right.result(), NULL);
++ arithmetic_op_fpu(x->op(), reg, left.result(), right.result(), x->is_strictfp());
+
+ set_result(x, round_item(reg));
+ }
+diff --git a/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp
+index 08b8f2b915b7..3019cb01acc6 100644
+--- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp
++++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp
+@@ -768,11 +768,13 @@ extern "C" void npf() {
+
+ extern "C" void pf(unsigned long sp, unsigned long fp, unsigned long pc,
+ unsigned long bcx, unsigned long thread) {
+- RegisterMap map((JavaThread*)thread, false);
+ if (!reg_map) {
+- reg_map = (RegisterMap*)os::malloc(sizeof map, mtNone);
++ reg_map = NEW_C_HEAP_OBJ(RegisterMap, mtNone);
++ ::new (reg_map) RegisterMap((JavaThread*)thread, false);
++ } else {
++ *reg_map = RegisterMap((JavaThread*)thread, false);
+ }
+- memcpy(reg_map, &map, sizeof map);
++
+ {
+ CodeBlob *cb = CodeCache::find_blob((address)pc);
+ if (cb && cb->frame_size())
+diff --git a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp
+index 72ec4cd1e36b..8168b50ec9f1 100644
+--- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp
++++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp
+@@ -38,8 +38,6 @@ class InterpreterMacroAssembler: public MacroAssembler {
+ protected:
+
+ protected:
+- using MacroAssembler::call_VM_leaf_base;
+-
+ // Interpreter specific version of call_VM_base
+ using MacroAssembler::call_VM_leaf_base;
+
+diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
+index 5bfa8133d5bb..1c264b4df248 100644
+--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
++++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
+@@ -2681,7 +2681,7 @@ Address MacroAssembler::spill_address(int size, int offset, Register tmp)
+ if ((offset & (size-1)) && offset >= (1<<8)) {
+ add(tmp, base, offset & ((1<<12)-1));
+ base = tmp;
+- offset &= -1<<12;
++ offset &= -1u<<12;
+ }
+
+ if (offset >= (1<<12) * size) {
+diff --git a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp
+index b917636cb635..dbf1dcdb5409 100644
+--- a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp
++++ b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp
+@@ -177,7 +177,7 @@ void VM_Version::get_processor_features() {
+ if (FILE *f = fopen("/proc/cpuinfo", "r")) {
+ char buf[128], *p;
+ while (fgets(buf, sizeof (buf), f) != NULL) {
+- if (p = strchr(buf, ':')) {
++ if ((p = strchr(buf, ':')) != NULL) {
+ long v = strtol(p+1, NULL, 0);
+ if (strncmp(buf, "CPU implementer", sizeof "CPU implementer" - 1) == 0) {
+ _cpu = v;
+diff --git a/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.s b/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.s
+index 25e3b054f779..4b8ed597c59f 100644
+--- a/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.s
++++ b/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.s
+@@ -159,7 +159,7 @@ bwd_copy_aligned:
+ blo bwd_copy_drain
+
+ bwd_copy_again:
+- prfm pldl1keep, [s, #-256]
++ prfum pldl1keep, [s, #-256]
+ stp t0, t1, [d, #-16]
+ ldp t0, t1, [s, #-16]
+ stp t2, t3, [d, #-32]
+diff --git a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp
+index c728687a4044..e428e89baa09 100644
+--- a/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp
++++ b/hotspot/src/os_cpu/linux_aarch64/vm/os_linux_aarch64.cpp
+@@ -83,19 +83,13 @@
+ #define REG_SP REG_RSP
+ #define REG_PC REG_RIP
+ #define REG_FP REG_RBP
+-#define SPELL_REG_SP "rsp"
+-#define SPELL_REG_FP "rbp"
+ #else
+ #define REG_FP 29
+ #define REG_LR 30
+-
+-#define SPELL_REG_SP "sp"
+-#define SPELL_REG_FP "x29"
+ #endif
+
+-address os::current_stack_pointer() {
+- register void *esp __asm__ (SPELL_REG_SP);
+- return (address) esp;
++NOINLINE address os::current_stack_pointer() {
++ return (address)__builtin_frame_address(0);
+ }
+
+ char* os::non_memory_address_word() {
+@@ -233,14 +233,8 @@ frame os::get_sender_for_C_frame(frame* fr) {
+ #endif
+ }
+
+-intptr_t* _get_previous_fp() {
+- register intptr_t **ebp __asm__ (SPELL_REG_FP);
+- return (intptr_t*) *ebp; // we want what it points to.
+-}
+-
+-
+-frame os::current_frame() {
+- intptr_t* fp = _get_previous_fp();
++NOINLINE frame os::current_frame() {
++ intptr_t *fp = *(intptr_t **)__builtin_frame_address(0);
+ frame myframe((intptr_t*)os::current_stack_pointer(),
+ (intptr_t*)fp,
+ CAST_FROM_FN_PTR(address, os::current_frame));
+@@ -259,12 +238,6 @@ frame os::current_frame() {
+ }
+
+ // Utility functions
+-
+-// From IA32 System Programming Guide
+-enum {
+- trap_page_fault = 0xE
+-};
+-
+ #ifdef BUILTIN_SIM
+ extern "C" void Fetch32PFI () ;
+ extern "C" void Fetch32Resume () ;
+@@ -667,42 +640,42 @@ extern "C" {
+ return 0;
+ }
+
+- void _Copy_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) {
++ void _Copy_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {
+ if (from > to) {
+- jshort *end = from + count;
++ const jshort *end = from + count;
+ while (from < end)
+ *(to++) = *(from++);
+ }
+ else if (from < to) {
+- jshort *end = from;
++ const jshort *end = from;
+ from += count - 1;
+ to += count - 1;
+ while (from >= end)
+ *(to--) = *(from--);
+ }
+ }
+- void _Copy_conjoint_jints_atomic(jint* from, jint* to, size_t count) {
++ void _Copy_conjoint_jints_atomic(const jint* from, jint* to, size_t count) {
+ if (from > to) {
+- jint *end = from + count;
++ const jint *end = from + count;
+ while (from < end)
+ *(to++) = *(from++);
+ }
+ else if (from < to) {
+- jint *end = from;
++ const jint *end = from;
+ from += count - 1;
+ to += count - 1;
+ while (from >= end)
+ *(to--) = *(from--);
+ }
+ }
+- void _Copy_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) {
++ void _Copy_conjoint_jlongs_atomic(volatile jlong* from, volatile jlong* to, size_t count) {
+ if (from > to) {
+- jlong *end = from + count;
++ const jlong *end = (const jlong*)from + count;
+ while (from < end)
+ os::atomic_copy64(from++, to++);
+ }
+ else if (from < to) {
+- jlong *end = from;
++ const jlong *end = (const jlong*)from;
+ from += count - 1;
+ to += count - 1;
+ while (from >= end)
+@@ -710,22 +683,22 @@ extern "C" {
+ }
+ }
+
+- void _Copy_arrayof_conjoint_bytes(HeapWord* from,
++ void _Copy_arrayof_conjoint_bytes(const HeapWord* from,
+ HeapWord* to,
+ size_t count) {
+ memmove(to, from, count);
+ }
+- void _Copy_arrayof_conjoint_jshorts(HeapWord* from,
++ void _Copy_arrayof_conjoint_jshorts(const HeapWord* from,
+ HeapWord* to,
+ size_t count) {
+ memmove(to, from, count * 2);
+ }
+- void _Copy_arrayof_conjoint_jints(HeapWord* from,
++ void _Copy_arrayof_conjoint_jints(const HeapWord* from,
+ HeapWord* to,
+ size_t count) {
+ memmove(to, from, count * 4);
+ }
+- void _Copy_arrayof_conjoint_jlongs(HeapWord* from,
++ void _Copy_arrayof_conjoint_jlongs(const HeapWord* from,
+ HeapWord* to,
+ size_t count) {
+ memmove(to, from, count * 8);
+diff --git a/hotspot/src/os/linux/vm/os_linux.inline.hpp b/hotspot/src/os/linux/vm/os_linux.inline.hpp
+index 937cd47..a6c9a87 100644
+--- a/hotspot/src/os/linux/vm/os_linux.inline.hpp
++++ b/hotspot/src/os/linux/vm/os_linux.inline.hpp
+@@ -99,18 +99,16 @@ inline int os::ftruncate(int fd, jlong length) {
+ inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf)
+ {
+ dirent* p;
+- int status;
+ assert(dirp != NULL, "just checking");
+
+ // NOTE: Linux readdir_r (on RH 6.2 and 7.2 at least) is NOT like the POSIX
+ // version. Here is the doc for this function:
+ // http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_262.html
+
+- if((status = ::readdir_r(dirp, dbuf, &p)) != 0) {
+- errno = status;
+- return NULL;
+- } else
++ if((p = ::readdir(dirp)) != NULL) {
+ return p;
++ } else
++ return NULL;
+ }
+
+ inline int os::closedir(DIR *dirp) {

base-commit: 472706ae2f9160833951a4e4bcc4c206e03097b0
--
2.39.0
A
A
Andreas Enge wrote on 26 Jul 2023 16:04
Still relevant?
(address . 63069@debbugs.gnu.org)
ZMEn9fDpXRXZcpS8@jurong
Hello Anthony,

as written at
the much simpler patch given there enables openjdk@9 to be built on my
aarch64 machine.

So can this bug be closed?

Andreas
A
A
Andreas Enge wrote on 26 Jul 2023 16:23
(address . 63069@debbugs.gnu.org)
ZMEsTy7A3YGVMYbM@jurong
Am Wed, Jul 26, 2023 at 04:04:37PM +0200 schrieb Andreas Enge:
Toggle quote (4 lines)
> the much simpler patch given there enables openjdk@9 to be built on my
> aarch64 machine.

Well, but the new phase does not apply to openjdk@10. At the very least,
it needs to be deleted there.

Andreas
A
A
Andreas Enge wrote on 26 Jul 2023 16:55
(address . 63069@debbugs.gnu.org)(name . Christopher Baines)(address . mail@cbaines.net)
ZMEz8pl23s8jKi_3@jurong
Am Wed, Jul 26, 2023 at 04:23:11PM +0200 schrieb Andreas Enge:
Toggle quote (3 lines)
> Well, but the new phase does not apply to openjdk@10. At the very least,
> it needs to be deleted there.

But this is not enough. Giving up on this and hoping that Chris, in cc,
has an idea...

Andreas
B
B
Bruno Victal wrote on 27 Jul 2023 02:25
Re: [bug#63069] Still relevant?
(name . Andreas Enge)(address . andreas@enge.fr)
0a894f48-cfa8-3b65-55b9-9b8d3e9b21f0@makinata.eu
Hi Andreas,

On 2023-07-26 15:55, Andreas Enge wrote:
Toggle quote (7 lines)
> Am Wed, Jul 26, 2023 at 04:23:11PM +0200 schrieb Andreas Enge:
>> Well, but the new phase does not apply to openjdk@10. At the very least,
>> it needs to be deleted there.
>
> But this is not enough. Giving up on this and hoping that Chris, in cc,
> has an idea...

FWIW I think it's cleaner to use a .patch file for this rather than an extra
phase and dance of substitute-keyword-arguments/phase manipulations.


--
Furthermore, I consider that nonfree software must be eradicated.

Cheers,
Bruno.
T
T
Tim Johann wrote on 29 Jul 2023 13:56
[bug#63069] Alternative solution for both openjdk9 and openjdk10.
(address . 63069@debbugs.gnu.org)
87fs56rkkb.fsf@phrogstar.de
Hi Andreas, hi Bruno, hi Chris,

See my contribution for a fix for both openjdk9 and openjdk10 using separate .patch files. I was able to compile openjdk11 afterward applying this change.


Thanks

and cheers

Tim
Attachment: file
M
M
Maxim Cournoyer wrote on 21 Jan 05:41 +0100
control message for bug #63069
(address . control@debbugs.gnu.org)
87o7dfb8mt.fsf@gmail.com
close 63069
quit
?