Skip to content

Commit

Permalink
fix(build): fix errors with Xcode 15
Browse files Browse the repository at this point in the history
Xcode 15 introduces Apple's new linker. Fix compatibility with new
linker:

* Work around errors when linking archives with empty object files.
* Fix collect-copyright script to work with the new linker's slightly
  different linker map file format.

Fixes #1130.
  • Loading branch information
strager committed Dec 22, 2023
1 parent 750adc2 commit 0dd4143
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 14 deletions.
6 changes: 1 addition & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,7 @@ find_package(PythonInterp 3) # Force Python 3 (instead of Python 2).
# quick_lint_js_add_library.
include(QuickLintJSTarget)
find_package(Threads REQUIRED)
quick_lint_js_add_library(
quick-lint-js-precompiled-headers
STATIC
website/wasm/empty.cpp
)
quick_lint_js_add_empty_cxx_library(quick-lint-js-precompiled-headers)
target_link_libraries(
quick-lint-js-precompiled-headers
PUBLIC
Expand Down
43 changes: 38 additions & 5 deletions cmake/QuickLintJSTarget.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
set(QUICK_LINT_JS_CXX_COMPILER_OPTIONS "" CACHE STRING "")
mark_as_advanced(QUICK_LINT_JS_CXX_COMPILER_OPTIONS)

set(QUICK_LINT_JS_EMPTY_CPP "${CMAKE_CURRENT_LIST_DIR}/empty.cpp")

function (quick_lint_js_add_executable TARGET)
add_executable(${ARGV})
target_compile_options(
Expand All @@ -26,11 +28,42 @@ function (quick_lint_js_add_library TARGET)
PRIVATE
"${QUICK_LINT_JS_CXX_COMPILER_OPTIONS}"
)
if ("${TARGET}" STREQUAL quick-lint-js-precompiled-headers)
# Don't use PCH when building PCH.
else ()
quick_lint_js_use_default_precompiled_headers("${TARGET}")
endif ()
quick_lint_js_use_default_precompiled_headers("${TARGET}")
endfunction ()

# Like add_library("${TARGET}") but with workarounds for bugs.
#
# * Avoid an INTERFACE library to work around the following error from CMake:
# > Unable to resolve full path of PCH-header '[snip]/cmake_pch_arm64.hxx'
# > assigned to target quick-lint-js-test-lib, although its path is supposed
# > to be known!" errors from CMake.
# * Create a dummy source file because CMake demands one.
# * NOTE[empty-library-symbol]: Ensure there is at least one symbol to avoid the
# following error from macOS's linker (as of Xcode 15.1, dyld version 1022.1):
# > ld: archive member '/' not a mach-o file in
# > '[snip]/libquick-lint-js-precompiled-headers.a'
function (quick_lint_js_add_empty_cxx_library TARGET)
add_library("${TARGET}" STATIC "${QUICK_LINT_JS_EMPTY_CPP}")

# NOTE(strager): Don't enable pre-compiled headers.
# quick_lint_js_add_empty_cxx_library is used to define the main pre-compiled
# headers CMake target and we don't want a dependency cycle.

# NOTE(strager): We need QUICK_LINT_JS_CXX_COMPILER_OPTIONS. Without it, we
# get miscompilations with some GCC flags (I don't know which) which make
# pre-compiled headers incompatible.
target_compile_options(
"${TARGET}"
PRIVATE
"${QUICK_LINT_JS_CXX_COMPILER_OPTIONS}"
)
endfunction ()

# Like add_library("${TARGET}") but with workarounds for bugs.
#
# See quick_lint_js_add_empty_cxx_library for details.
function (quick_lint_js_add_empty_executable TARGET)
add_executable("${TARGET}" "${QUICK_LINT_JS_EMPTY_CPP}")
endfunction ()

function (quick_lint_js_use_default_precompiled_headers TARGET)
Expand Down
8 changes: 6 additions & 2 deletions website/wasm/empty.cpp → cmake/empty.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
// Copyright (C) 2020 Matthew "strager" Glazar
// See end of file for extended copyright information.

// This file is intentionally empty. It is needed to make CMake's add_library
// function happy.
// This file is needed to make CMake's add_library function happy.

// For an explanation for why we need this symbol, see
// NOTE[empty-library-symbol].
extern char this_variable_exists_to_work_around_macos_toolchain_bugs;
char this_variable_exists_to_work_around_macos_toolchain_bugs;

// quick-lint-js finds bugs in JavaScript programs.
// Copyright (C) 2020 Matthew "strager" Glazar
Expand Down
37 changes: 36 additions & 1 deletion tools/collect-copyright
Original file line number Diff line number Diff line change
Expand Up @@ -1219,7 +1219,9 @@ def parse_text_link_map(raw_link_map: str) -> LinkMap:
if match is not None:
linked_archives.add(match.group("file"))
elif state == "MACHO_OBJECT_FILES":
match = re.match(r"^\[[0-9 ]+\] (?P<file>.*)\((?P<object>.*)\)$", line)
match = re.match(
r"^\[[0-9 ]+\] (?P<file>.*?)(?:\[\d+\])?\((?P<object>.*)\)$", line
)
if match is not None:
linked_archives.add(match.group("file"))
elif state == "NONE":
Expand Down Expand Up @@ -1404,6 +1406,39 @@ class TestLD64LinkMap(unittest.TestCase):
)


class TestDyldLinkMap(unittest.TestCase):
"""Test Apple's macOS linker introduced in Xcode 15."""

def test_small_link_map(self) -> None:
raw_link_map = """\
# Path: quick-lint-js
# Arch: arm64
# Object files:
[ 0] linker synthesized
[ 1] tlv-file
[ 2] inits-file
[ 3] /Users/strager/Projects/quick-lint-js-sl/build/src/CMakeFiles/quick-lint-js.dir/quick-lint-js/cli/main.cpp.o
[ 4] src/libquick-lint-js-lib.a[4](emacs-lisp-diag-reporter.cpp.o)
[ 89] vendor/simdjson/libsimdjson.a[2](simdjson.cpp.o)
[ 90] /opt/homebrew/Cellar/llvm/17.0.6/lib/c++/libc++.1.0.dylib
[ 91] /Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk/usr/lib/system/libsystem_c.tbd
# Sections:
# Address Size Segment Section
0x100002C10 0x001FB1E4 __TEXT __text
0x1001FDDF4 0x00005304 __TEXT __stubs
# Symbols:
# Address Size File Name
0x100002C10 0x00000028 [ 3] _main
0x100002C38 0x00000014 [ 3] __ZN13quick_lint_js12_GLOBAL__N_14initEv
0x100002C4C 0x0000005C [ 3] __ZN13quick_lint_js12_GLOBAL__N_13runEiPPc
"""
link_map = parse_text_link_map(raw_link_map)
self.assertEqual(
link_map.linked_archives,
{"src/libquick-lint-js-lib.a", "vendor/simdjson/libsimdjson.a"},
)


class TestMoldLinkMap(unittest.TestCase):
def test_small_link_map(self) -> None:
raw_link_map = """\
Expand Down
2 changes: 1 addition & 1 deletion website/wasm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ set(VSCODE_DIST_DIR dist)

if (EMSCRIPTEN)
# TODO(strager): Rename.
quick_lint_js_add_executable(quick-lint-js-vscode empty.cpp)
quick_lint_js_add_empty_executable(quick-lint-js-vscode)
target_link_libraries(
quick-lint-js-vscode
PRIVATE
Expand Down

0 comments on commit 0dd4143

Please sign in to comment.