Skip to content

Commit b5cd6cf

Browse files
committed
Merge FEATURE-ci-native-link-map: Use Darwin linker map option
2 parents 808f7fa + f2ce9fc commit b5cd6cf

3 files changed

Lines changed: 131 additions & 1 deletion

File tree

‎scripts/lib/package_integration.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import json
44
import os
55
from pathlib import Path
6+
import platform
67
import shlex
78
import time
89
from package_commands import dependencies
@@ -19,7 +20,8 @@ def compile_probe(compiler, sources, flags, libraries, executable, command, env,
1920
included.update(dependencies(depfile))
2021
objects.append(str(obj))
2122
matrix.check_dependencies(included, prefix, source, build, private)
22-
command(shlex.split(compiler) + objects + libraries + ['-Wl,-Map,' + str(executable) + '.map', '-o', str(executable)],
23+
map_option = '-Wl,-map,' if platform.system() == 'Darwin' else '-Wl,-Map,'
24+
command(shlex.split(compiler) + objects + libraries + [map_option + str(executable) + '.map', '-o', str(executable)],
2325
executable.parent, env)
2426
return {'compile_options': ['-O0', '-g'] if compile_options is None else list(compile_options), 'dependencies': sorted(included), 'sources': {str(path): hashlib.sha256(path.read_bytes()).hexdigest() for path in sources},
2527
'artifact_sha256': hashlib.sha256(executable.read_bytes()).hexdigest(), 'private_test_headers': private,

‎scripts/test-v3-installed-package.py‎

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,84 @@
11
#!/usr/bin/env python3
22
"""Adversarial policy fixtures; these are not installed-package proof."""
3+
import hashlib
34
import importlib.util
45
import json
56
import os
67
import shlex
78
from pathlib import Path
89
import subprocess
10+
import sys
911
import tempfile
1012
import unittest
1113
from unittest.mock import patch
1214

15+
sys.path.insert(0, str(Path(__file__).parent / 'lib'))
16+
import package_integration as integration
17+
1318
CXX = os.environ.get('CXX', 'c++')
1419

1520
spec = importlib.util.spec_from_file_location('audit', Path(__file__).with_name('audit-v3-installed-package.py'))
1621
audit = importlib.util.module_from_spec(spec)
1722
spec.loader.exec_module(audit)
1823

1924

25+
class CompileProbeTest(unittest.TestCase):
26+
def setUp(self):
27+
self.tmp = tempfile.TemporaryDirectory()
28+
self.addCleanup(self.tmp.cleanup)
29+
self.root = Path(self.tmp.name).resolve()
30+
self.source, self.build, self.prefix = (self.root / name for name in ('source', 'build', 'prefix'))
31+
self.unit = self.root / 'consumer.cpp'
32+
self.unit.write_text('int main() { return 0; }\n')
33+
self.header = self.prefix / 'include/httpserver.hpp'
34+
self.header.parent.mkdir(parents=True)
35+
self.header.write_text('struct installed_server {};\n')
36+
self.executable = self.root / 'consumer'
37+
self.calls = []
38+
39+
def command(self, argv, cwd, env):
40+
self.calls.append((argv, cwd, env))
41+
if '-MF' in argv:
42+
Path(argv[argv.index('-MF') + 1]).write_text(
43+
'consumer.o: ' + shlex.join([str(self.unit), str(self.header)]) + '\n')
44+
Path(argv[argv.index('-o') + 1]).write_text('compiled artifact')
45+
46+
def test_compile_probe_uses_host_link_map_syntax_preserving_arguments_and_receipt(self):
47+
compiler = 'cache-wrapper "compiler path/c++" --driver-mode=g++'
48+
flags = ['-I' + str(self.prefix / 'include'), '-DFIXTURE=1']
49+
libraries = ['-L' + str(self.prefix / 'lib'), '-lhttpserver', '-pthread', '-lssl', '-lcrypto']
50+
env = {'PATH': 'selected-toolchain'}
51+
map_path = str(self.executable) + '.map'
52+
for host, option in (('Darwin', '-Wl,-map,'), ('Linux', '-Wl,-Map,'),
53+
('FreeBSD', '-Wl,-Map,'), ('Windows', '-Wl,-Map,')):
54+
for options in (None, ['-O2', '-DNDEBUG']):
55+
with self.subTest(host=host, compile_options=options), patch('platform.system', return_value=host):
56+
self.calls.clear()
57+
receipt = integration.compile_probe(compiler, [self.unit], flags, libraries,
58+
self.executable, self.command, env, self.source, self.build, self.prefix, False,
59+
compile_options=options)
60+
obj = str(self.root / 'consumer-0.o')
61+
expected_options = ['-O0', '-g'] if options is None else options
62+
self.assertEqual(self.calls, [
63+
(shlex.split(compiler) + ['-std=c++20'] + expected_options + flags +
64+
['-MMD', '-MF', str(self.root / 'consumer-0.d'), '-c', str(self.unit), '-o', obj], self.root, env),
65+
(shlex.split(compiler) + [obj] + libraries + [option + map_path, '-o', str(self.executable)], self.root, env)])
66+
self.assertEqual(receipt['link_map'], map_path)
67+
self.assertEqual(receipt['compile_options'], expected_options)
68+
self.assertEqual(receipt['sources'], {str(self.unit): hashlib.sha256(self.unit.read_bytes()).hexdigest()})
69+
self.assertEqual(receipt['dependency_sha256'], {
70+
str(path): hashlib.sha256(path.read_bytes()).hexdigest() for path in (self.unit, self.header)})
71+
self.assertEqual(receipt['dependencies'], sorted([str(self.unit), str(self.header)]))
72+
self.assertEqual(receipt['artifact_sha256'], hashlib.sha256(self.executable.read_bytes()).hexdigest())
73+
self.assertFalse(receipt['private_test_headers'])
74+
75+
def test_compile_probe_rejects_source_header_before_linking(self):
76+
with patch('platform.system', return_value='Darwin'), self.assertRaisesRegex(ValueError, 'source public header contamination'):
77+
integration.compile_probe('c++', [self.unit], [], [], self.executable, self.command,
78+
{}, self.root, self.build, self.prefix, False)
79+
self.assertEqual(len(self.calls), 1)
80+
81+
2082
class AuditTest(unittest.TestCase):
2183
def setUp(self):
2284
environment = patch.dict(os.environ)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# FEATURE-ci-native-link-map
2+
3+
Status: Complete (local implementation, Groundwork validation and finalization).
4+
Native platform results remain CI / v3 PR owned; no release readiness claimed.
5+
6+
Scope: repair the installed-consumer link-map option rejected by Darwin ld.
7+
Base: v3 at `808f7fa20b0bc2f3c3049140b86189e704c5378e`.
8+
9+
- [x] Create an isolated task worktree using the Groundwork identity helper.
10+
- [x] Reproduce the command defect with a failing compile-probe regression.
11+
- [x] Select Darwin `-Wl,-map,` while retaining GNU `-Wl,-Map,` elsewhere.
12+
- [x] Verify the unchanged map receipt path, ordered library arguments, quoted
13+
compiler wrapper/options, compile-option defaults/overrides, source and
14+
dependency hashes, artifact hash, and dependency contamination rejection.
15+
- [x] Run affected Python module tests and a real local GNU compile/link/run.
16+
- [x] Check the diff and Python syntax; record unavailable native evidence.
17+
- [x] Caller: complete Groundwork validation and finalization.
18+
Three focused reviewers approved with no findings; affected evidence reused.
19+
- [ ] CI / v3 PR: obtain fresh native Darwin installed-consumer and selected
20+
archive results after merge; retain other platform results honestly.
21+
22+
## Failure evidence and causal assessment
23+
24+
The original native macOS failure is retained at
25+
`/tmp/v3-ci-job-120361073477-direct.log`, lines 299–318. Darwin ld rejects the
26+
unconditionally emitted GNU `-Map` option in `compile_probe`. The earlier TCP443
27+
permission probe is followed by the existing privileged setup; it is not the
28+
terminal failure. The caller also retained the same failure from selected-archive
29+
job 120362794854 at `/tmp/v3-ci-job-120362794854-direct.log`.
30+
31+
The focused regression ran against the original implementation first:
32+
`python3 scripts/test-v3-installed-package.py CompileProbeTest -v` failed only
33+
the two Darwin option variants, showing `-Map` instead of `-map`. Linux,
34+
FreeBSD and Windows command variants retained their expected GNU syntax.
35+
36+
## Local verification
37+
38+
- The focused command regression passed after the minimal platform selection.
39+
- `python3 scripts/test-v3-installed-package.py -v`: 37 tests passed.
40+
- `python3 scripts/test-v3-native-benchmark.py`: 18 tests passed, including the
41+
existing compile-probe default/override contract.
42+
- A bounded real `compile_probe` invocation compiled and linked a C++ consumer
43+
against a temporary installed-header fixture with GNU c++, ran the resulting
44+
executable, and verified the receipt's map file existed (20,637 bytes).
45+
The temporary directory contained spaces; dependency parsing also passed.
46+
This is a linker smoke check, not installed-library acceptance evidence.
47+
- `python3 -m py_compile scripts/lib/package_integration.py
48+
scripts/test-v3-installed-package.py` and `git diff --check` passed.
49+
- CLAUDE.md prescribes cpplint for C++; no C++ files changed and no Python
50+
linter is configured. No local Python linter was available.
51+
52+
Darwin ld / ld64.lld was unavailable locally. Native Darwin linking and the
53+
fresh full package matrices remain incomplete until CI executes them. No broad
54+
native/build baseline was rerun, and no previous failed receipt was promoted to
55+
a pass. Prior validation closures remain unchanged. No product sources, audit
56+
policy, dependency/provider/client pins, tags or releases changed.
57+
58+
## Implementation notes
59+
60+
These Python script tests use standard-library unittest and need no dependency
61+
installation. Existing modules load `scripts/lib` through `sys.path`; use
62+
`platform.system()` for native host selection. The repository's general C++
63+
setup remains `./bootstrap`, an out-of-tree configure/build and `make check`.
64+
The isolated task branch was created from v3 using the helper-returned identity;
65+
Git metadata writes required sandbox escalation. The unrelated bauth worktree
66+
was preserved.

0 commit comments

Comments
 (0)