Skip to content

Commit 78b6e14

Browse files
committed
Refuse to publish a host under a name it was not built for
VITASDK_HOST_NAME is what the artifacts are called; the toolchain triplet is what they are. Nothing compared the two, so the build whose toolchain file had gone missing named one host and produced another, and everything downstream agreed with the name: the tarball, the package architecture, the bootstrap, the provenance. The check runs as soon as both are known, which costs seconds instead of the 18 minutes the bootstrap smoke test needed to reach the same conclusion by running a binary. arm64 and aarch64 are one machine here: Apple writes the first, config.sub the second, and both reach this line depending on who was asked. The name derivation moves to cmake/PublishedHostName.cmake so its test can call it instead of keeping a second copy of the FreeBSD rule.
1 parent adb8388 commit 78b6e14

4 files changed

Lines changed: 86 additions & 15 deletions

File tree

CMakeLists.txt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ endif()
113113

114114
include(Utils)
115115
include(GetTriplet)
116+
include(PublishedHostName)
116117
include(ExternalProject)
117118

118119
set(vitasdk_base_c_flags "${CMAKE_C_FLAGS}")
@@ -135,14 +136,12 @@ get_host_triplet(host_native)
135136
get_build_triplet(build_native)
136137

137138
# What this host is called where it is published -- in artifact names, in the
138-
# package architecture, in the vdpm bundle it embeds. It is the toolchain
139-
# triplet on every host but FreeBSD, whose cross compiler carries a release
140-
# number (x86_64-unknown-freebsd14-gcc) that its published name does not.
141-
string(REGEX REPLACE "^(.*-unknown-freebsd)[0-9]+$" "\\1"
142-
host_published_default "${host_native}")
139+
# package architecture, in the vdpm bundle it embeds.
140+
vitasdk_published_host_name("${host_native}" host_published_default)
143141
set(VITASDK_HOST_NAME "${host_published_default}" CACHE STRING
144142
"Name this host publishes under, if not its toolchain triplet")
145143
set(host_published "${VITASDK_HOST_NAME}")
144+
vitasdk_check_published_host_name("${host_published}" "${host_native}")
146145

147146
message(STATUS "Host: ${host_native}")
148147
message(STATUS "Build: ${build_native}")

cmake/PublishedHostName.cmake

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#
2+
# Copyright(c) 2016 codestation
3+
# Distributed under the MIT License (http://opensource.org/licenses/MIT)
4+
#
5+
6+
# A host is called two things: the triplet its cross compiler answers to, and
7+
# the name it publishes under. Keeping them apart is what lets a host be
8+
# published under a name it was not built for, which is silent -- the
9+
# artifacts are well formed, they just belong to another machine.
10+
11+
include_guard(GLOBAL)
12+
13+
# The name a host triplet publishes under. The same everywhere except
14+
# FreeBSD, whose cross compiler carries a release number (x86_64-unknown-
15+
# freebsd14-gcc) that its published name does not.
16+
function(vitasdk_published_host_name triplet out_name)
17+
string(REGEX REPLACE "^(.*-unknown-freebsd)[0-9]+$" "\\1" name "${triplet}")
18+
set(${out_name} "${name}" PARENT_SCOPE)
19+
endfunction()
20+
21+
# arm64 and aarch64 name one machine: Apple writes the first, config.sub the
22+
# second, and both reach here depending on who was asked.
23+
function(vitasdk_canonical_host_name name out_name)
24+
string(REGEX REPLACE "^arm64-" "aarch64-" canonical "${name}")
25+
set(${out_name} "${canonical}" PARENT_SCOPE)
26+
endfunction()
27+
28+
# Fail unless published is the name triplet is entitled to publish under.
29+
function(vitasdk_check_published_host_name published triplet)
30+
vitasdk_published_host_name("${triplet}" expected)
31+
vitasdk_canonical_host_name("${expected}" expected_canonical)
32+
vitasdk_canonical_host_name("${published}" published_canonical)
33+
if(published_canonical STREQUAL expected_canonical)
34+
return()
35+
endif()
36+
message(FATAL_ERROR
37+
"this build publishes as ${published} but its toolchain builds "
38+
"${triplet}. Either it is missing the toolchain file that would make "
39+
"it cross-compile, or VITASDK_HOST_NAME names the wrong host.")
40+
endfunction()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
cmake_minimum_required(VERSION 3.16)
2+
3+
include("${CMAKE_CURRENT_LIST_DIR}/../../cmake/PublishedHostName.cmake")
4+
5+
vitasdk_check_published_host_name("${PUBLISHED}" "${TRIPLET}")
Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
11
cmake_minimum_required(VERSION 3.16)
22

3-
# A host is called two things: the triplet its cross compiler answers to, and
4-
# the name it publishes under. They are the same everywhere except FreeBSD,
5-
# whose compiler carries a release number its published name does not -- and
6-
# mixing them up published a bundle nobody could match to a host.
7-
8-
function(published_name_of triplet out)
9-
string(REGEX REPLACE "^(.*-unknown-freebsd)[0-9]+$" "\\1" name "${triplet}")
10-
set(${out} "${name}" PARENT_SCOPE)
11-
endfunction()
3+
include("${CMAKE_CURRENT_LIST_DIR}/../../cmake/PublishedHostName.cmake")
124

135
function(assert_published triplet expected)
14-
published_name_of("${triplet}" actual)
6+
vitasdk_published_host_name("${triplet}" actual)
157
if(NOT "${actual}" STREQUAL "${expected}")
168
message(FATAL_ERROR
179
"${triplet} publishes as '${actual}', expected '${expected}'")
@@ -28,4 +20,39 @@ foreach(triplet x86_64-linux-gnu aarch64-linux-gnu x86_64-linux-musl
2820
assert_published("${triplet}" "${triplet}")
2921
endforeach()
3022

23+
# The gate: a name may only be published by the toolchain that earns it.
24+
function(assert_gate published triplet expected_result)
25+
execute_process(
26+
COMMAND ${CMAKE_COMMAND}
27+
-DPUBLISHED=${published} -DTRIPLET=${triplet}
28+
-P "${CMAKE_CURRENT_LIST_DIR}/published-host-name-check.cmake"
29+
RESULT_VARIABLE result
30+
OUTPUT_QUIET
31+
ERROR_VARIABLE error)
32+
if(expected_result STREQUAL "accepts" AND NOT result EQUAL 0)
33+
message(FATAL_ERROR "${triplet} must publish as ${published}: ${error}")
34+
endif()
35+
if(expected_result STREQUAL "rejects")
36+
if(result EQUAL 0)
37+
message(FATAL_ERROR "${triplet} must not publish as ${published}")
38+
endif()
39+
if(NOT error MATCHES "${published}" OR NOT error MATCHES "${triplet}")
40+
message(FATAL_ERROR "the rejection must name both, got: ${error}")
41+
endif()
42+
endif()
43+
endfunction()
44+
45+
assert_gate(x86_64-linux-gnu x86_64-linux-gnu accepts)
46+
assert_gate(x86_64-unknown-freebsd x86_64-unknown-freebsd14 accepts)
47+
# Apple's spelling of the machine config.sub calls aarch64.
48+
assert_gate(arm64-apple-darwin aarch64-apple-darwin accepts)
49+
assert_gate(aarch64-apple-darwin arm64-apple-darwin accepts)
50+
51+
# What shipped an arm64 SDK under the Intel name: the cross host lost its
52+
# toolchain file, so the build named one host and produced another.
53+
assert_gate(x86_64-apple-darwin arm64-apple-darwin rejects)
54+
assert_gate(arm64-apple-darwin x86_64-apple-darwin rejects)
55+
assert_gate(x86_64-w64-mingw32 x86_64-linux-gnu rejects)
56+
assert_gate(aarch64-linux-gnu x86_64-linux-gnu rejects)
57+
3158
message(STATUS "published host name checks passed")

0 commit comments

Comments
 (0)