mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Build] (P13 W7): the library links from module OBJECT targets along the ratchet's partition, and a server-only link check target must link without the frontend modules.
This commit is contained in:
+125
-42
@@ -794,8 +794,80 @@ endif()
|
||||
# find <glvnd/libeglabi.h>; a Linux host only built because its system has the header).
|
||||
list(APPEND MOBILEGL_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/3rdparty/glvnd/include)
|
||||
|
||||
# ---- P13 W7 (D12): MODULE TARGETS ------------------------------------------------------------
|
||||
#
|
||||
# One flat SOURCE_FILES list used to feed MobileGL and MobileGL_s separately (every file compiled
|
||||
# twice). It is split here into OBJECT libraries along the link ratchet's partition
|
||||
# (scripts/link_ratchet.py PARTITION, which is the written form of these boundaries):
|
||||
#
|
||||
# mg_util MG_Util, Init / GlobalObjects / ConfigLoader, MG_Remote/FatalFunnel SHARED
|
||||
# mg_pipe MG_Pipe SERVER
|
||||
# mg_backend MG_Backend (both backends, the record arm's staged stores) SERVER
|
||||
# mg_frontend MG_Impl + MG_State FRONTEND
|
||||
# mg_remote_transport MG_Remote/{Transport,Protocol,Wire}, CapsCodec SERVER
|
||||
# mg_remote_client MG_Remote/Client FRONTEND
|
||||
# mg_remote_server MG_Remote/Server SERVER
|
||||
#
|
||||
# Both MobileGL and MobileGL_s link the same objects. mgl_build_iface carries every compile-side
|
||||
# usage requirement (include directories, definitions, the link libraries whose headers the
|
||||
# sources include), so a property set on it reaches every module and both libraries; a property
|
||||
# that only matters at link time may still be set on the libraries themselves.
|
||||
add_library(mgl_build_iface INTERFACE)
|
||||
target_include_directories(mgl_build_iface INTERFACE ${MOBILEGL_INCLUDE_DIR})
|
||||
target_link_libraries(mgl_build_iface INTERFACE ${MOBILEGL_LINK_LIBRARIES})
|
||||
target_compile_definitions(mgl_build_iface INTERFACE
|
||||
${MOBILEGL_COMPILE_DEF}
|
||||
MOBILEGL_LOG_ACTIVE_LEVEL=${MOBILEGL_LOG_ACTIVE_LEVEL}
|
||||
$<$<BOOL:${MOBILEGL_TRACE_ANGLE_VARIANTS}>:MOBILEGL_TRACE_ANGLE_VARIANTS=1>
|
||||
)
|
||||
|
||||
set(MGL_MODULES util pipe backend frontend remote_transport remote_client remote_server)
|
||||
foreach(MGL_MODULE IN LISTS MGL_MODULES)
|
||||
set(MGL_MODULE_SOURCES_${MGL_MODULE})
|
||||
endforeach()
|
||||
foreach(MGL_SOURCE IN LISTS SOURCE_FILES)
|
||||
if (MGL_SOURCE MATCHES "^MobileGL/MG_Remote/Client/")
|
||||
list(APPEND MGL_MODULE_SOURCES_remote_client ${MGL_SOURCE})
|
||||
elseif (MGL_SOURCE MATCHES "^MobileGL/MG_Remote/Server/")
|
||||
list(APPEND MGL_MODULE_SOURCES_remote_server ${MGL_SOURCE})
|
||||
elseif (MGL_SOURCE MATCHES "^MobileGL/MG_Remote/(Transport|Protocol|Wire)/" OR
|
||||
MGL_SOURCE STREQUAL "MobileGL/MG_Remote/CapsCodec.cpp")
|
||||
list(APPEND MGL_MODULE_SOURCES_remote_transport ${MGL_SOURCE})
|
||||
elseif (MGL_SOURCE MATCHES "^MobileGL/MG_(Impl|State)/")
|
||||
list(APPEND MGL_MODULE_SOURCES_frontend ${MGL_SOURCE})
|
||||
elseif (MGL_SOURCE MATCHES "^MobileGL/MG_Backend/")
|
||||
list(APPEND MGL_MODULE_SOURCES_backend ${MGL_SOURCE})
|
||||
elseif (MGL_SOURCE MATCHES "^MobileGL/MG_Pipe/")
|
||||
list(APPEND MGL_MODULE_SOURCES_pipe ${MGL_SOURCE})
|
||||
else()
|
||||
list(APPEND MGL_MODULE_SOURCES_util ${MGL_SOURCE})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(MGL_MODULE_OBJECTS)
|
||||
set(MGL_SERVER_MODULE_OBJECTS)
|
||||
foreach(MGL_MODULE IN LISTS MGL_MODULES)
|
||||
if (NOT MGL_MODULE_SOURCES_${MGL_MODULE})
|
||||
continue() # MG_Remote's modules are empty without MOBILEGL_BUILD_DISAGGREGATED
|
||||
endif()
|
||||
add_library(mg_${MGL_MODULE} OBJECT ${MGL_MODULE_SOURCES_${MGL_MODULE}})
|
||||
target_link_libraries(mg_${MGL_MODULE} PUBLIC mgl_build_iface)
|
||||
set_target_properties(mg_${MGL_MODULE} PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set_target_properties(mg_${MGL_MODULE} PROPERTIES
|
||||
C_VISIBILITY_PRESET default CXX_VISIBILITY_PRESET default VISIBILITY_INLINES_HIDDEN OFF)
|
||||
else()
|
||||
set_target_properties(mg_${MGL_MODULE} PROPERTIES
|
||||
C_VISIBILITY_PRESET hidden CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN ON)
|
||||
endif()
|
||||
list(APPEND MGL_MODULE_OBJECTS $<TARGET_OBJECTS:mg_${MGL_MODULE}>)
|
||||
if (NOT MGL_MODULE STREQUAL "frontend" AND NOT MGL_MODULE STREQUAL "remote_client")
|
||||
list(APPEND MGL_SERVER_MODULE_OBJECTS $<TARGET_OBJECTS:mg_${MGL_MODULE}>)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
add_library(${CMAKE_PROJECT_NAME} SHARED
|
||||
${SOURCE_FILES}
|
||||
${MGL_MODULE_OBJECTS}
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
@@ -820,21 +892,7 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC
|
||||
${MOBILEGL_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}
|
||||
PUBLIC
|
||||
${MOBILEGL_LINK_LIBRARIES}
|
||||
)
|
||||
|
||||
target_compile_definitions(${CMAKE_PROJECT_NAME}
|
||||
PUBLIC
|
||||
${MOBILEGL_COMPILE_DEF}
|
||||
MOBILEGL_LOG_ACTIVE_LEVEL=${MOBILEGL_LOG_ACTIVE_LEVEL}
|
||||
$<$<BOOL:${MOBILEGL_TRACE_ANGLE_VARIANTS}>:MOBILEGL_TRACE_ANGLE_VARIANTS=1>
|
||||
)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC mgl_build_iface)
|
||||
|
||||
if(UNIX AND NOT APPLE AND NOT ANDROID)
|
||||
foreach(MOBILEGL_LOADER_ALIAS
|
||||
@@ -861,8 +919,8 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
if(NOT ANDROID)
|
||||
add_library(${CMAKE_PROJECT_NAME}_s STATIC
|
||||
${SOURCE_FILES}
|
||||
add_library(${CMAKE_PROJECT_NAME}_s STATIC
|
||||
${MGL_MODULE_OBJECTS}
|
||||
)
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
@@ -879,27 +937,12 @@ if(NOT ANDROID)
|
||||
)
|
||||
endif()
|
||||
|
||||
target_include_directories(${CMAKE_PROJECT_NAME}_s PUBLIC
|
||||
${MOBILEGL_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}_s
|
||||
PUBLIC
|
||||
${MOBILEGL_LINK_LIBRARIES}
|
||||
)
|
||||
|
||||
target_compile_definitions(${CMAKE_PROJECT_NAME}_s
|
||||
PUBLIC
|
||||
${MOBILEGL_COMPILE_DEF}
|
||||
MOBILEGL_LOG_ACTIVE_LEVEL=${MOBILEGL_LOG_ACTIVE_LEVEL}
|
||||
)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}_s PUBLIC mgl_build_iface)
|
||||
endif()
|
||||
|
||||
if (TRACY_ENABLE)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC Tracy::TracyClient)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}_s PUBLIC Tracy::TracyClient)
|
||||
target_compile_definitions(${CMAKE_PROJECT_NAME} PUBLIC -DTRACY_ENABLE)
|
||||
target_compile_definitions(${CMAKE_PROJECT_NAME}_s PUBLIC -DTRACY_ENABLE)
|
||||
target_link_libraries(mgl_build_iface INTERFACE Tracy::TracyClient)
|
||||
target_compile_definitions(mgl_build_iface INTERFACE -DTRACY_ENABLE)
|
||||
endif ()
|
||||
|
||||
# GLVND, AND WHY THIS IS A LINKER FLAG RATHER THAN A VISIBILITY ONE.
|
||||
@@ -924,6 +967,49 @@ if (MOBILEGL_BUILD_DISAGGREGATED AND UNIX AND NOT APPLE AND NOT ANDROID)
|
||||
add_subdirectory(MobileGL/MG_Gbm)
|
||||
endif()
|
||||
|
||||
# ---- P13 W7 (D12): THE SERVER-ONLY LINK CHECK ---------------------------------------------------
|
||||
# The server and shared modules linked WITHOUT mg_frontend / mg_remote_client, with --no-undefined:
|
||||
# the server half has to link from its own half of the tree. The frontend references it still makes
|
||||
# are the link ratchet's baseline, each a named exemption that resolves to an aborting stub through
|
||||
# a generated linker response file (scripts/ci/server_link_check.py refuses, before the link, any
|
||||
# server reference the baseline does not name). Built with the split shape on Linux hosts; never
|
||||
# installed or loaded.
|
||||
if (MOBILEGL_BUILD_DISAGGREGATED AND UNIX AND NOT APPLE AND NOT ANDROID)
|
||||
find_package(Python3 COMPONENTS Interpreter QUIET)
|
||||
if (Python3_Interpreter_FOUND)
|
||||
set(MGL_SERVER_LINK_RSP "${CMAKE_BINARY_DIR}/mgl_server_link_exemptions.rsp")
|
||||
set(MGL_ALL_MODULE_OBJECT_DEPS)
|
||||
foreach(MGL_MODULE IN LISTS MGL_MODULES)
|
||||
if (TARGET mg_${MGL_MODULE})
|
||||
list(APPEND MGL_ALL_MODULE_OBJECT_DEPS $<TARGET_OBJECTS:mg_${MGL_MODULE}>)
|
||||
endif()
|
||||
endforeach()
|
||||
add_custom_command(
|
||||
OUTPUT "${MGL_SERVER_LINK_RSP}"
|
||||
COMMAND "${Python3_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/scripts/ci/server_link_check.py"
|
||||
--build-dir "${CMAKE_BINARY_DIR}"
|
||||
--baseline "${CMAKE_SOURCE_DIR}/scripts/data/link_ratchet_baseline.txt"
|
||||
--out "${MGL_SERVER_LINK_RSP}"
|
||||
DEPENDS ${MGL_ALL_MODULE_OBJECT_DEPS}
|
||||
"${CMAKE_SOURCE_DIR}/scripts/ci/server_link_check.py"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/link_ratchet.py"
|
||||
"${CMAKE_SOURCE_DIR}/scripts/data/link_ratchet_baseline.txt"
|
||||
COMMENT "Server-only link check: naming the frontend references the baseline exempts"
|
||||
VERBATIM)
|
||||
add_custom_target(mgl_server_link_exemptions DEPENDS "${MGL_SERVER_LINK_RSP}")
|
||||
add_library(MobileGL_server_linkcheck SHARED
|
||||
${MGL_SERVER_MODULE_OBJECTS}
|
||||
tools/server_link_check/Exempt.cpp)
|
||||
target_link_libraries(MobileGL_server_linkcheck PRIVATE mgl_build_iface)
|
||||
target_link_options(MobileGL_server_linkcheck PRIVATE
|
||||
"LINKER:--no-undefined" "@${MGL_SERVER_LINK_RSP}")
|
||||
set_property(TARGET MobileGL_server_linkcheck APPEND PROPERTY LINK_DEPENDS "${MGL_SERVER_LINK_RSP}")
|
||||
add_dependencies(MobileGL_server_linkcheck mgl_server_link_exemptions)
|
||||
else()
|
||||
message(STATUS "MobileGL: no Python3 interpreter - the server-only link check target is not configured")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (ANDROID)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC
|
||||
android
|
||||
@@ -964,7 +1050,7 @@ if (APPLE AND NOT MOBILEGL_IOS)
|
||||
endif()
|
||||
|
||||
if (APPLE AND MOBILEGL_IOS)
|
||||
target_compile_definitions(${CMAKE_PROJECT_NAME} PUBLIC MOBILEGL_IOS=1 _LIBCPP_DISABLE_AVAILABILITY)
|
||||
target_compile_definitions(mgl_build_iface INTERFACE MOBILEGL_IOS=1 _LIBCPP_DISABLE_AVAILABILITY)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC
|
||||
"-framework CoreGraphics"
|
||||
"-framework Foundation"
|
||||
@@ -975,7 +1061,6 @@ if (APPLE AND MOBILEGL_IOS)
|
||||
endif()
|
||||
|
||||
if(TARGET ${CMAKE_PROJECT_NAME}_s)
|
||||
target_compile_definitions(${CMAKE_PROJECT_NAME}_s PUBLIC MOBILEGL_IOS=1 _LIBCPP_DISABLE_AVAILABILITY)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}_s PUBLIC
|
||||
"-framework CoreGraphics"
|
||||
"-framework Foundation"
|
||||
@@ -990,10 +1075,8 @@ endif()
|
||||
if (NOT ANDROID AND NOT MOBILEGL_IOS)
|
||||
find_package(Vulkan)
|
||||
if (Vulkan_FOUND)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC Vulkan::Vulkan Vulkan::Headers)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}_s PUBLIC Vulkan::Vulkan Vulkan::Headers)
|
||||
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC ${Vulkan_INCLUDE_DIR})
|
||||
target_include_directories(${CMAKE_PROJECT_NAME}_s PUBLIC ${Vulkan_INCLUDE_DIR})
|
||||
target_link_libraries(mgl_build_iface INTERFACE Vulkan::Vulkan Vulkan::Headers)
|
||||
target_include_directories(mgl_build_iface INTERFACE ${Vulkan_INCLUDE_DIR})
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env python3
|
||||
"""P13 W7 (D12): the exemption list for the server-only link check target.
|
||||
|
||||
THE TARGET. `MobileGL_server_linkcheck` (CMakeLists.txt) links the SERVER and SHARED module objects
|
||||
(mg_util, mg_pipe, mg_backend, mg_remote_transport, mg_remote_server) WITHOUT mg_frontend and
|
||||
mg_remote_client, with `--no-undefined`: a server image must link from its own half of the tree.
|
||||
The references that still need the frontend are the link ratchet's baseline
|
||||
(scripts/data/link_ratchet_baseline.txt) - each one a named debt, not an accident - and this script
|
||||
turns exactly those into named exemptions: one `--defsym=<mangled>=mgl_server_link_check_exempt`
|
||||
per symbol, written to a compiler-driver response file the target links with. The stub aborts; the target
|
||||
is a link proof, never run.
|
||||
|
||||
WHAT IS REFUSED. A SERVER object's reference that only a FRONTEND object satisfies and that the
|
||||
baseline does not list fails here, before the link, naming the symbol and the referrer - the same
|
||||
verdict the ratchet gives, raised by the build. References from SHARED objects (Init, the global
|
||||
objects, the config loader) into the frontend are exempted and only counted: those files ARE the
|
||||
library's entry glue, and a real server image replaces them rather than sheds them.
|
||||
|
||||
Usage: server_link_check.py --build-dir B --baseline F --out RSP [--nm nm] [--cxxfilt c++filt]
|
||||
"""
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), ".."))
|
||||
import link_ratchet as lr # noqa: E402
|
||||
|
||||
STUB = "mgl_server_link_check_exempt"
|
||||
|
||||
|
||||
def nm_mangled(nm_tool, mode, keys, cwd):
|
||||
"""{key: {mangled: type}} via `nm -o --<mode>-only` (no demangling)."""
|
||||
table = {k: {} for k in keys}
|
||||
back = {lr.OBJECT_PATHS.get(k, k): k for k in keys}
|
||||
for i in range(0, len(keys), 150):
|
||||
batch = [lr.OBJECT_PATHS.get(k, k) for k in keys[i:i + 150]]
|
||||
done = subprocess.run([nm_tool, "-o", "--" + mode + "-only"] + batch, cwd=cwd,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
if done.returncode != 0 and done.stderr.strip():
|
||||
raise SystemExit("server-link-check: nm failed: " + done.stderr.strip())
|
||||
for line in done.stdout.splitlines():
|
||||
head, _, rest = line.partition(":")
|
||||
key = back.get(head)
|
||||
parts = rest.split()
|
||||
if key is None or len(parts) < 2:
|
||||
continue
|
||||
table[key][parts[-1]] = parts[-2]
|
||||
return table
|
||||
|
||||
|
||||
def demangle(names, tool):
|
||||
names = sorted(names)
|
||||
done = subprocess.run([tool], input="\n".join(names) + "\n", stdout=subprocess.PIPE, text=True,
|
||||
check=True)
|
||||
return dict(zip(names, done.stdout.splitlines()))
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--build-dir", required=True)
|
||||
ap.add_argument("--baseline", required=True)
|
||||
ap.add_argument("--out", required=True)
|
||||
ap.add_argument("--nm", default="nm")
|
||||
ap.add_argument("--cxxfilt", default="c++filt")
|
||||
args = ap.parse_args()
|
||||
|
||||
root, objects = lr.find_objects(args.build_dir, "MobileGL")
|
||||
roles = {o: lr.classify(o) for o in objects}
|
||||
unclassified = [o for o, r in roles.items() if r is None]
|
||||
if unclassified:
|
||||
raise SystemExit("server-link-check: object(s) match no PARTITION row: " + ", ".join(unclassified))
|
||||
server = sorted(o for o, r in roles.items() if r == lr.SERVER)
|
||||
shared = sorted(o for o, r in roles.items() if r == lr.SHARED)
|
||||
frontend = sorted(o for o, r in roles.items() if r == lr.FRONTEND)
|
||||
|
||||
undefined = nm_mangled(args.nm, "undefined", server + shared, root)
|
||||
defined = nm_mangled(args.nm, "defined", objects, root)
|
||||
image_defined = set()
|
||||
for obj in server + shared:
|
||||
image_defined.update(defined[obj])
|
||||
frontend_defined = set()
|
||||
for obj in frontend:
|
||||
frontend_defined.update(defined[obj])
|
||||
|
||||
wanted = {} # mangled -> set of referrer keys
|
||||
for obj in server + shared:
|
||||
for name in undefined[obj]:
|
||||
if name in image_defined or name not in frontend_defined:
|
||||
continue
|
||||
wanted.setdefault(name, set()).add(obj)
|
||||
|
||||
readable = demangle(wanted, args.cxxfilt)
|
||||
baseline, _notes = lr.read_baseline(args.baseline)
|
||||
baseline = set(baseline)
|
||||
refused, from_shared = [], 0
|
||||
for name, referrers in sorted(wanted.items()):
|
||||
from_server = [r for r in referrers if roles[r] == lr.SERVER]
|
||||
if not from_server:
|
||||
from_shared += 1
|
||||
continue
|
||||
if readable[name] not in baseline:
|
||||
refused.append((readable[name], sorted(from_server)))
|
||||
if refused:
|
||||
for symbol, referrers in refused:
|
||||
print("server-link-check: NEW frontend reference from the server half: {} <- {}"
|
||||
.format(symbol, ", ".join(referrers)))
|
||||
print("server-link-check: {} reference(s) the baseline does not name - fix the reference or, "
|
||||
"if it is a debt, add it to {} with its reason".format(len(refused), args.baseline))
|
||||
return 1
|
||||
with open(args.out, "w", encoding="utf-8") as out:
|
||||
for name in sorted(wanted):
|
||||
out.write("-Wl,--defsym={}={}\n".format(name, STUB))
|
||||
print("server-link-check: {} named exemption(s) ({} from server objects, all in the baseline; {} "
|
||||
"from the shared entry glue)".format(len(wanted), len(wanted) - from_shared, from_shared))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
+38
-12
@@ -211,21 +211,39 @@ def family_of(obj_path, table=FAMILIES):
|
||||
return best[1]
|
||||
|
||||
|
||||
# Object key (path relative to its target's object directory, e.g. MobileGL/MG_Backend/X.cpp.o)
|
||||
# -> the path nm is run on, relative to <build-dir>/CMakeFiles. Since P13 W7 (D12) the library is
|
||||
# linked from module OBJECT libraries, so its objects live under CMakeFiles/mg_<module>.dir as well
|
||||
# as CMakeFiles/MobileGL.dir (the few sources added to the library target itself); the key keeps the
|
||||
# source-relative spelling every PARTITION row is written against.
|
||||
OBJECT_PATHS = {}
|
||||
|
||||
|
||||
def find_objects(build_dir, target):
|
||||
"""Every .o under <build-dir>/CMakeFiles/<target>.dir, keyed by path relative to that dir."""
|
||||
root = os.path.join(build_dir, "CMakeFiles", target + ".dir")
|
||||
if not os.path.isdir(root):
|
||||
"""Every .o of <target> (and, for the library, of its mg_* module objects), keyed by path
|
||||
relative to its object directory. Returns (<build-dir>/CMakeFiles, sorted keys)."""
|
||||
cmake_files = os.path.join(build_dir, "CMakeFiles")
|
||||
dirs = [target + ".dir"]
|
||||
if target in ("MobileGL", "MobileGL_s") and os.path.isdir(cmake_files):
|
||||
dirs += sorted(d for d in os.listdir(cmake_files) if d.startswith("mg_") and d.endswith(".dir"))
|
||||
if not os.path.isdir(os.path.join(cmake_files, dirs[0])) and len(dirs) == 1:
|
||||
raise SystemExit(PREFIX + "no such object directory: {} (is --build-dir a configured "
|
||||
"CMake build, and is --target right? the disaggregated build "
|
||||
"has MobileGL.dir, MobileGL_s.dir and MobileGLServer.dir)"
|
||||
.format(root))
|
||||
.format(os.path.join(cmake_files, dirs[0])))
|
||||
objects = []
|
||||
for dirpath, _dirnames, filenames in os.walk(root):
|
||||
for name in filenames:
|
||||
if name.endswith(".o"):
|
||||
full = os.path.join(dirpath, name)
|
||||
objects.append(os.path.relpath(full, root).replace(os.sep, "/"))
|
||||
return root, sorted(objects)
|
||||
for sub in dirs:
|
||||
root = os.path.join(cmake_files, sub)
|
||||
if not os.path.isdir(root):
|
||||
continue
|
||||
for dirpath, _dirnames, filenames in os.walk(root):
|
||||
for name in filenames:
|
||||
if name.endswith(".o"):
|
||||
full = os.path.join(dirpath, name)
|
||||
key = os.path.relpath(full, root).replace(os.sep, "/")
|
||||
OBJECT_PATHS[key] = os.path.relpath(full, cmake_files).replace(os.sep, "/")
|
||||
objects.append(key)
|
||||
return cmake_files, sorted(objects)
|
||||
|
||||
|
||||
def check_flags(build_dir):
|
||||
@@ -255,8 +273,9 @@ def check_flags(build_dir):
|
||||
def run_nm(nm_tool, mode, paths, cwd, chunk=150):
|
||||
"""`nm -C -o --<mode>-only` over paths, returned as raw text. Chunked for argv limits."""
|
||||
out = []
|
||||
back = {OBJECT_PATHS.get(p, p): p for p in paths}
|
||||
for i in range(0, len(paths), chunk):
|
||||
batch = paths[i:i + chunk]
|
||||
batch = [OBJECT_PATHS.get(p, p) for p in paths[i:i + chunk]]
|
||||
completed = subprocess.run([nm_tool, "-C", "-o", "--" + mode + "-only"] + batch,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
text=True, cwd=cwd)
|
||||
@@ -265,7 +284,14 @@ def run_nm(nm_tool, mode, paths, cwd, chunk=150):
|
||||
# silently shrunk SERVER set.
|
||||
if completed.returncode != 0 and completed.stderr.strip():
|
||||
raise SystemExit(PREFIX + "nm failed: " + completed.stderr.strip())
|
||||
out.append(completed.stdout)
|
||||
text = completed.stdout
|
||||
if any(k != v for k, v in back.items()):
|
||||
lines = []
|
||||
for line in text.splitlines(True):
|
||||
head, sep, rest = line.partition(":")
|
||||
lines.append(back.get(head, head) + sep + rest)
|
||||
text = "".join(lines)
|
||||
out.append(text)
|
||||
return "".join(out)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// MobileGL - tools/server_link_check/Exempt.cpp
|
||||
// Copyright (c) 2025-2026 MobileGL-Dev
|
||||
// Licensed under the GNU Lesser General Public License v3.0:
|
||||
// https://www.gnu.org/licenses/gpl-3.0.txt
|
||||
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
// End of Source File Header
|
||||
//
|
||||
// P13 W7 (D12): the one definition every named exemption of the server-only link check resolves to
|
||||
// (scripts/ci/server_link_check.py writes `--defsym=<symbol>=mgl_server_link_check_exempt` for each
|
||||
// frontend reference the link ratchet's baseline names). The check target is a link proof and is
|
||||
// never loaded; reaching this would mean a server image called into the frontend half.
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
extern "C" [[noreturn]] void mgl_server_link_check_exempt() {
|
||||
std::fputs("MobileGL server link check: an exempted frontend symbol was called\n", stderr);
|
||||
std::abort();
|
||||
}
|
||||
Reference in New Issue
Block a user