Skip to content

Commit f91dddf

Browse files
committed
Merge FEATURE-ci-native-linkage-exeext: Use configured audit executable suffix
2 parents 794ecc0 + fcff7cb commit f91dddf

3 files changed

Lines changed: 146 additions & 2 deletions

File tree

‎Makefile.am‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ check-v3-native-linkage:
306306
@$(MAKE) -n -C src -W libhttpserver_v3core.la libhttpserver.la AM_LDFLAGS= >check-v3-cxx-link.log
307307
@grep -E -- '--tag=CXX.*--mode=link.*-o libhttpserver.la ' check-v3-cxx-link.log >/dev/null || { cat check-v3-cxx-link.log; echo "FAIL: aggregate must use the C++ linker"; exit 1; }
308308
@echo "=== check-v3-native-linkage: native provider surface audit ==="
309-
@$(MAKE) $(AM_MAKEFLAGS) -C "$(top_builddir)/test" native_linkage >/dev/null
309+
@$(MAKE) $(AM_MAKEFLAGS) -C "$(top_builddir)/test" native_linkage$(EXEEXT) >/dev/null
310310
@BUILD_DIR="$(abs_top_builddir)" SRC_DIR="$(top_srcdir)" V3_TLS_MODE="$(enable_v3_tls)" $(top_srcdir)/scripts/audit-v3-native-linkage.sh
311311

312312
# Enforce the explicit native v3 example source/build inventory.

‎scripts/test-v3-native-linkage.py‎

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,95 @@
11
#!/usr/bin/env python3
2-
"""Adversarial inspector-output fixtures; real binary proof runs separately."""
2+
"""Make gate and inspector-output fixtures; real binary proof runs separately."""
33
import os
44
from pathlib import Path
5+
import shutil
56
import subprocess
67
import tempfile
78
import unittest
89

910
SOURCE = Path(__file__).resolve().parent.parent
1011

12+
class MakeGateFixtures(unittest.TestCase):
13+
"""Run the production recipe with GNU make and controlled build/inspector outputs."""
14+
15+
def gate(self, suffix='', mode='no', linker='CXX', dependency=None,
16+
symbols='', build_fails=False):
17+
make = shutil.which('gmake') or shutil.which('make')
18+
self.assertIsNotNone(make, 'GNU make is required for native linkage gate tests')
19+
recipe = (SOURCE / 'Makefile.am').read_text().split(
20+
'\ncheck-v3-native-linkage:\n', 1)[1].split('\n\n', 1)[0]
21+
if dependency is None:
22+
dependency = 'KERNEL32.dll' if suffix else '/usr/lib/libc++.1.dylib'
23+
with tempfile.TemporaryDirectory() as directory:
24+
root = Path(directory).resolve()
25+
for name in ['src', 'test', 'tools']:
26+
(root / name).mkdir()
27+
(root / 'src/Makefile').write_text(
28+
'libhttpserver.la:\n'
29+
f'\tlibtool --tag={linker} --mode=link -o libhttpserver.la archive\n')
30+
# Like Automake, expose only the configured executable target.
31+
(root / 'test/Makefile').write_text(
32+
'native_linkage$(EXEEXT):\n'
33+
+ ('\t@exit 1\n' if build_fails else
34+
'\t@mkdir -p .libs ../src/.libs\n'
35+
'\t@printf "#!/bin/sh\\nexit 0\\n" > .libs/$@\n'
36+
'\t@chmod +x .libs/$@\n'
37+
'\t@touch ../src/.libs/libhttpserver_v3core.a\n'))
38+
inspectors = {'nm': symbols}
39+
if suffix:
40+
inspectors.update(uname='MINGW64_NT-10.0', objdump=(
41+
'fixture.exe: file format pei-x86-64\n'
42+
+ '\n'.join(' DLL Name: ' + n for n in dependency.splitlines())))
43+
else:
44+
inspectors['otool'] = 'fixture:\n' + dependency
45+
for name, output in inspectors.items():
46+
path = root / 'tools' / name
47+
path.write_text("#!/bin/sh\ncat <<'OUTPUT'\n" + output + '\nOUTPUT\n')
48+
path.chmod(0o755)
49+
env = dict(os.environ, PATH=str(root / 'tools') + os.pathsep + os.environ['PATH'])
50+
return subprocess.run(
51+
[make, '--no-print-directory', '-f', '-', 'check-v3-native-linkage',
52+
'top_srcdir=' + str(SOURCE), 'top_builddir=' + str(root),
53+
'abs_top_builddir=' + str(root), 'EXEEXT=' + suffix,
54+
'enable_v3_tls=' + mode],
55+
input='check-v3-native-linkage:\n' + recipe + '\n', cwd=root,
56+
env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
57+
58+
def test_configured_executable_suffix_reaches_real_audit(self):
59+
for suffix in ['', '.exe']:
60+
with self.subTest(suffix=suffix):
61+
result = self.gate(suffix=suffix)
62+
self.assertEqual(0, result.returncode, result.stdout)
63+
self.assertIn('A1 PASS', result.stdout)
64+
self.assertIn('A2 PASS', result.stdout)
65+
66+
def test_configured_tls_mode_reaches_real_audit(self):
67+
for suffix, dependency in [('', '/tmp/libssl.3.dylib'), ('.exe', 'libssl-3.dll')]:
68+
for mode in ['yes', 'no']:
69+
with self.subTest(suffix=suffix, mode=mode):
70+
result = self.gate(suffix=suffix, dependency=dependency, mode=mode)
71+
self.assertEqual(mode == 'yes', result.returncode == 0, result.stdout)
72+
self.assertIn('A2 PASS' if mode == 'yes' else 'TLS-off load dependency',
73+
result.stdout)
74+
75+
def test_cxx_linker_gate_stops_before_audit(self):
76+
result = self.gate(linker='CC')
77+
self.assertNotEqual(0, result.returncode)
78+
self.assertIn('aggregate must use the C++ linker', result.stdout)
79+
self.assertNotIn('A1 PASS', result.stdout)
80+
81+
def test_build_failure_stops_before_audit(self):
82+
result = self.gate(build_fails=True)
83+
self.assertNotEqual(0, result.returncode)
84+
self.assertNotIn('A1 PASS', result.stdout)
85+
86+
def test_static_provider_rejection_propagates(self):
87+
result = self.gate(symbols=' U _SSL_set_quic_tls_cbs')
88+
self.assertNotEqual(0, result.returncode)
89+
self.assertIn('A1 PASS', result.stdout)
90+
self.assertIn('TLS-off provider symbols', result.stdout)
91+
self.assertNotIn('A2 PASS', result.stdout)
92+
1193
class AuditFixtures(unittest.TestCase):
1294
def audit(self, dependency=None, symbols='', mode='no', binary=True, archive=True, windows=False):
1395
if dependency is None:
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# FEATURE-ci-native-linkage-exeext: respect configured executable suffix
2+
3+
Status: Complete (local implementation, validation and finalization).
4+
Base: `v3` at `794ecc08f86e72469eed791c6b13d5a5490cefb4`.
5+
6+
Windows package job `120420001573` in run `39955436208` and archive job
7+
`120420935368` build the library, then fail because the native linkage gate asks
8+
make for `native_linkage`, while Automake exposes `native_linkage.exe`.
9+
The recursive target now uses `native_linkage$(EXEEXT)`, retaining the empty
10+
suffix on Unix and using the configured suffix on Windows.
11+
12+
Action items:
13+
14+
- [x] Create an isolated Groundwork worktree from the recorded v3 head;
15+
preserve the bauth worktree and prior closed repairs.
16+
- [x] Retain both original native Windows logs and bind the relevant unchanged
17+
Makefile/audit inputs to the failed and local base revisions.
18+
- [x] Add a regression executing the actual production recipe with GNU make
19+
for empty and `.exe` suffixes; observe the original missing-target failure
20+
before editing production code.
21+
- [x] Respect configured `EXEEXT` in the recursive native linkage target.
22+
- [x] Verify both suffixes reach the real source/header and artifact audit;
23+
preserve configured TLS mode, C++ linker rejection, build failure propagation
24+
and provider rejection.
25+
- [x] Preserve the complete production inspector and all existing adversarial
26+
tests, including static symbols, missing archive and Windows import controls.
27+
- [x] Run the affected 17-test module, bootstrap, out-of-tree TLS-off configure,
28+
generated-target dry runs for both suffixes, Python syntax and diff checks.
29+
- [x] Retain raw commands, results, source bindings and journal under main
30+
`.debug/FEATURE-ci-native-linkage-exeext/`.
31+
- [x] Caller: Groundwork validation and local finalization into v3.
32+
- [ ] CI / v3 PR: native Windows package and archive builds and audits.
33+
34+
Local verification: the five new make-gate tests and all 12 existing inspector
35+
tests pass. The original `.exe` RED fails with `No rule to make target
36+
'native_linkage'`; empty suffix behavior passes before and after the change.
37+
The regression reads the production recipe from `Makefile.am`, executes it
38+
with real GNU make, and runs the unchanged production audit against the real
39+
source tree. Small build Makefiles and inspector outputs are controlled
40+
fixtures; they do not compile or inspect native Windows binaries. TLS-on
41+
fixtures accept OpenSSL while TLS-off fixtures reject the same dependencies.
42+
The C linker, failed build and static provider cases fail the gate as required.
43+
44+
Bootstrap and configure pass with existing Automake/Autoconf warnings and
45+
missing optional documentation tools recorded in the logs. Generated test
46+
Makefile dry runs resolve both `native_linkage` and `native_linkage.exe`; the
47+
unbuilt v3core archive is explicitly excluded from those dry runs with `-o`.
48+
These are target-resolution checks, not binary build evidence. The production
49+
audit bytes and entire original `AuditFixtures` class are unchanged. Python
50+
scripts have no documented standalone linter; no C++ files changed.
51+
52+
Native Windows execution remains incomplete and CI / v3 PR owned under
53+
AGENTS. No full native baseline, unrelated repairs, CI reruns, validation loop,
54+
merge or publication was performed. Older Linux parity causality remains
55+
UNCERTAIN after its previously closed bounded diagnosis. Prior production
56+
unwind/entropy fixes, audit policy and nonlocal checks remain untouched.
57+
58+
Project notes: Autotools/C++20 setup uses `bash bootstrap`, out-of-tree
59+
`configure --disable-v3-tls --disable-examples`, then make. This task uses only
60+
targeted Python unittest, GNU make fixtures and configure/dry-run checks.
61+
The worktree identity came verbatim from the Groundwork helper; Git metadata
62+
writes required sandbox escalation.

0 commit comments

Comments
 (0)