Skip to content

Commit a31e35b

Browse files
author
Alex Denisov
committedDec 8, 2022
Swift: enable bootstrapping
1 parent 96a5813 commit a31e35b

File tree

4 files changed

+90
-152
lines changed

4 files changed

+90
-152
lines changed
 

‎CMakeLists.txt

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
cmake_minimum_required(VERSION 3.12.4)
2+
project(codeql-swift-artifacts C CXX)
3+
4+
find_package(LLVM REQUIRED CONFIG)
5+
find_package(Clang REQUIRED CONFIG)
6+
find_package(Swift REQUIRED CONFIG)
7+
8+
message("Using LLVM_CONFIG: ${Swift_CONFIG}")
9+
message("Using Clang_CONFIG: ${LLVM_CONFIG}")
10+
message("Using Swift_CONFIG: ${Clang_CONFIG}")
11+
12+
add_executable(codeql-swift-artifacts empty.cpp)
13+
target_link_libraries(codeql-swift-artifacts PRIVATE LLVMSupport swiftFrontendTool swiftCompilerModules)
14+
15+
if(APPLE)
16+
execute_process(
17+
COMMAND xcrun -find swiftc
18+
OUTPUT_VARIABLE CODEQL_SWIFT_COMPILER
19+
OUTPUT_STRIP_TRAILING_WHITESPACE
20+
)
21+
execute_process(
22+
COMMAND xcrun -show-sdk-path
23+
OUTPUT_VARIABLE CODEQL_MACOS_SDK_PATH
24+
OUTPUT_STRIP_TRAILING_WHITESPACE
25+
)
26+
27+
# Add in the toolchain directory so we can grab compatibility libraries
28+
# Inspired by the Swift's CMakeLists
29+
get_filename_component(TOOLCHAIN_BIN_DIR ${CODEQL_SWIFT_COMPILER} DIRECTORY)
30+
get_filename_component(TOOLCHAIN_LIB_DIR "${TOOLCHAIN_BIN_DIR}/../lib/swift/macosx" ABSOLUTE)
31+
target_link_directories(codeql-swift-artifacts PUBLIC ${TOOLCHAIN_LIB_DIR})
32+
target_link_directories(codeql-swift-artifacts PUBLIC ${CODEQL_MACOS_SDK_PATH}/usr/lib/swift)
33+
endif()
34+

‎empty.cpp

Whitespace-only changes.

‎pkg_swift_llvm.py

+55-151
Original file line numberDiff line numberDiff line change
@@ -11,98 +11,33 @@
1111
import zlib
1212
from collections import namedtuple
1313

14-
DEPS = {"llvm": ["LLVMSupport"],
15-
"swift": ["swiftFrontendTool"]}
16-
1714

1815
def getoptions():
1916
parser = argparse.ArgumentParser(description="package swift for codeql compilation")
20-
for p in DEPS:
21-
parser.add_argument(f"--{p}", required=True, type=resolve,
22-
metavar="DIR", help=f"path to {p} build root")
17+
parser.add_argument(f"--llvm-build-tree", required=True, type=resolve,
18+
metavar="DIR", help=f"path to LLVM build tree")
19+
parser.add_argument(f"--swift-build-tree", required=True, type=resolve,
20+
metavar="DIR", help=f"path to Swift build tree")
21+
parser.add_argument(f"--swift-source-tree", required=True, type=resolve,
22+
metavar="DIR", help=f"path to Swift source tree")
23+
2324
default_output = f"swift-prebuilt-{get_platform()}"
24-
parser.add_argument("--keep-tmp-dir", "-K", action="store_true",
25-
help="do not clean up the temporary directory")
2625
parser.add_argument("--output", "-o", type=pathlib.Path, metavar="DIR_OR_ZIP",
2726
help="output zip file or directory "
2827
f"(by default the filename is {default_output})")
29-
update_help_fmt = "Only update the {} library in DIR, triggering rebuilds of required files"
30-
parser.add_argument("--update-shared", "-u", metavar="DIR", type=pathlib.Path,
31-
help=update_help_fmt.format("shared"))
32-
parser.add_argument("--update-static", "-U", metavar="DIR", type=pathlib.Path,
33-
help=update_help_fmt.format("static"))
28+
3429
opts = parser.parse_args()
35-
if opts.output and (opts.update_shared or opts.update_static):
36-
parser.error("provide --output or one of --update-*, not both")
3730
if opts.output is None:
3831
opts.output = pathlib.Path()
3932
opts.output = get_tgt(opts.output, default_output)
40-
return opts
41-
4233

43-
Libs = namedtuple("Libs", ("archive", "static", "shared"))
44-
45-
DEPLIST = [x for d in DEPS.values() for x in d]
46-
47-
CMAKELISTS_DUMMY = f"""
48-
cmake_minimum_required(VERSION 3.12.4)
49-
50-
project(dummy C CXX)
34+
return opts
5135

52-
find_package(LLVM REQUIRED CONFIG PATHS ${{LLVM_ROOT}}/lib/cmake/llvm NO_DEFAULT_PATH)
53-
find_package(Clang REQUIRED CONFIG PATHS ${{LLVM_ROOT}}/lib/cmake/clang NO_DEFAULT_PATH)
54-
find_package(Swift REQUIRED CONFIG PATHS ${{SWIFT_ROOT}}/lib/cmake/swift NO_DEFAULT_PATH)
5536

56-
add_executable(dummy empty.cpp)
57-
target_link_libraries(dummy PRIVATE {" ".join(DEPLIST)})
58-
"""
37+
Libs = namedtuple("Libs", ("archive", "static", "shared", "linker_flags"))
5938

6039
EXPORTED_LIB = "CodeQLSwiftFrontendTool"
6140

62-
CMAKELISTS_EXPORTED_FMT = """
63-
add_library({exported} INTERFACE)
64-
65-
if (BUILD_SHARED_LIBS)
66-
if (APPLE)
67-
set(EXT "dylib")
68-
else()
69-
set(EXT "so")
70-
endif()
71-
else()
72-
set(EXT "a")
73-
endif()
74-
75-
set (SwiftLLVMWrapperLib libCodeQLSwiftFrontendTool.${{EXT}})
76-
set (input ${{CMAKE_CURRENT_LIST_DIR}}/${{SwiftLLVMWrapperLib}})
77-
set (output ${{CMAKE_BINARY_DIR}}/${{SwiftLLVMWrapperLib}})
78-
79-
add_custom_command(OUTPUT ${{output}}
80-
COMMAND ${{CMAKE_COMMAND}} -E copy_if_different ${{input}} ${{output}}
81-
DEPENDS ${{input}})
82-
add_custom_target(copy-llvm-swift-wrapper DEPENDS ${{output}})
83-
84-
target_include_directories({exported} INTERFACE ${{CMAKE_CURRENT_LIST_DIR}}/include)
85-
target_link_libraries({exported} INTERFACE
86-
${{output}}
87-
{libs}
88-
)
89-
add_dependencies(swiftAndLlvmSupport copy-llvm-swift-wrapper)
90-
"""
91-
92-
93-
class TempDir:
94-
def __init__(self, cleanup=True):
95-
self.path = None
96-
self.cleanup = cleanup
97-
98-
def __enter__(self):
99-
self.path = pathlib.Path(tempfile.mkdtemp())
100-
return self.path
101-
102-
def __exit__(self, *args):
103-
if self.cleanup:
104-
shutil.rmtree(self.path)
105-
10641

10742
def resolve(p):
10843
return pathlib.Path(p).resolve()
@@ -118,53 +53,27 @@ def run(prog, *, cwd, env=None, input=None):
11853
subprocess.run(prog, cwd=cwd, env=runenv, input=input, text=True)
11954

12055

121-
def build(dir, targets):
122-
print(f"building {' '.join(targets)} in {dir}")
123-
cmd = ["cmake", "--build", ".", "--"]
124-
cmd.extend(targets)
125-
run(cmd, cwd=dir)
126-
127-
12856
def get_platform():
12957
return "linux" if platform.system() == "Linux" else "macos"
13058

13159

132-
def create_empty_cpp(path):
133-
with open(path / "empty.cpp", "w"):
134-
pass
135-
136-
137-
def install(tmp, opts):
138-
print("installing dependencies")
139-
tgt = tmp / "install"
140-
for p in DEPS:
141-
builddir = getattr(opts, p)
142-
run(["cmake", "--build", ".", "--", "install"], cwd=builddir, env={"DESTDIR": tgt})
143-
if sys.platform != 'linux':
144-
return tgt / "Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain"
145-
return tgt
146-
147-
148-
def configure_dummy_project(tmp, *, llvm=None, swift=None, installed=None):
60+
def configure_dummy_project(tmp, *, llvm=None, swift=None):
14961
print("configuring dummy cmake project")
150-
if installed is not None:
151-
swift = llvm = installed / "usr"
152-
with open(tmp / "CMakeLists.txt", "w") as out:
153-
out.write(CMAKELISTS_DUMMY)
154-
create_empty_cpp(tmp)
62+
shutil.copy("CMakeLists.txt", tmp / "CMakeLists.txt")
63+
shutil.copy("empty.cpp", tmp / "empty.cpp")
15564
tgt = tmp / "build"
15665
tgt.mkdir()
157-
run(["cmake", f"-DLLVM_ROOT={llvm}", f"-DSWIFT_ROOT={swift}", "-DBUILD_SHARED_LIBS=OFF", ".."],
66+
run(["cmake", f"-DCMAKE_PREFIX_PATH={llvm};{swift}", "-DBUILD_SHARED_LIBS=OFF", ".."],
15867
cwd=tgt)
15968
return tgt
16069

16170

16271
def get_libs(configured):
16372
print("extracting linking information from dummy project")
164-
with open(configured / "CMakeFiles" / "dummy.dir" / "link.txt") as link:
73+
with open(configured / "CMakeFiles" / "codeql-swift-artifacts.dir" / "link.txt") as link:
16574
libs = link.read().split()
166-
libs = libs[libs.index('dummy')+1:] # skip up to -o dummy
167-
ret = Libs([], [], [])
75+
libs = libs[libs.index('codeql-swift-artifacts')+1:] # skip up to -o dummy
76+
ret = Libs([], [], [], [])
16877
for l in libs:
16978
if l.endswith(".a"):
17079
ret.static.append(str((configured / l).resolve()))
@@ -173,11 +82,10 @@ def get_libs(configured):
17382
ret.shared.append(f"-l{l[3:]}") # drop 'lib' prefix and '.so' suffix
17483
elif l.startswith("-l"):
17584
ret.shared.append(l)
85+
elif l.startswith("-L") or l.startswith("-Wl"):
86+
ret.linker_flags.append(l)
17687
else:
17788
raise ValueError(f"cannot understand link.txt: " + l)
178-
# move direct dependencies into archive
179-
ret.archive[:] = ret.static[:len(DEPLIST)]
180-
ret.static[:len(DEPLIST)] = []
18189
return ret
18290

18391

@@ -195,7 +103,6 @@ def create_static_lib(tgt, libs):
195103
mriscript = f"create {tgt}\n{includedlibs}\nsave\nend"
196104
run(["ar", "-M"], cwd=tgt.parent, input=mriscript)
197105
else:
198-
includedlibs = " ".join(f"{l}" for l in libs.archive + libs.static)
199106
libtool_args = ["libtool", "-static"]
200107
libtool_args.extend(libs.archive)
201108
libtool_args.extend(libs.static)
@@ -214,6 +121,7 @@ def create_shared_lib(tgt, libs):
214121
print(f"packaging {libname}")
215122
compiler = os.environ.get("CC", "clang")
216123
cmd = [compiler, "-shared"]
124+
cmd.extend(libs.linker_flags)
217125

218126
if sys.platform == 'linux':
219127
cmd.append("-Wl,--whole-archive")
@@ -239,17 +147,17 @@ def create_shared_lib(tgt, libs):
239147
def copy_includes(src, tgt):
240148
print("copying includes")
241149
for dir, exts in (("include", ("h", "def", "inc")), ("stdlib", ("h",))):
242-
srcdir = src / "usr" / dir
150+
srcdir = src / dir
243151
for ext in exts:
244152
for srcfile in srcdir.rglob(f"*.{ext}"):
245153
tgtfile = tgt / dir / srcfile.relative_to(srcdir)
246154
tgtfile.parent.mkdir(parents=True, exist_ok=True)
247155
shutil.copy(srcfile, tgtfile)
248156

249157

250-
def create_sdk(installed, tgt):
158+
def export_sdk(tgt, swift_source_tree, swift_build_tree):
251159
print("assembling sdk")
252-
srcdir = installed / "usr" / "lib" / "swift"
160+
srcdir = swift_build_tree/ "lib" / "swift"
253161
tgtdir = tgt / "usr" / "lib" / "swift"
254162
if get_platform() == "linux":
255163
srcdir /= "linux"
@@ -258,24 +166,30 @@ def create_sdk(installed, tgt):
258166
srcdir /= "macosx"
259167
for mod in srcdir.glob("*.swiftmodule"):
260168
shutil.copytree(mod, tgtdir / mod.name)
261-
shutil.copytree(installed / "usr" / "stdlib" / "public" / "SwiftShims",
262-
tgt / "usr" / "include" / "SwiftShims")
169+
shutil.copytree(swift_source_tree / "stdlib" / "public" / "SwiftShims",
170+
tgt / "usr" / "include" / "SwiftShims",
171+
ignore=shutil.ignore_patterns('CMakeLists.txt'))
263172

264173

265-
def create_export_dir(tmp, installed, libs):
266-
print("assembling prebuilt directory")
267-
exportedlibs = [create_static_lib(tmp, libs), create_shared_lib(tmp, libs)]
268-
tgt = tmp / "exported"
269-
tgt.mkdir()
174+
def export_libs(exported_dir, libs):
175+
print("exporting libraries")
176+
exportedlibs = [
177+
create_static_lib(exported_dir, libs),
178+
create_shared_lib(exported_dir, libs)
179+
]
270180
for l in exportedlibs:
271-
l.rename(tgt / l.name)
272-
with open(tgt / "swift_llvm_prebuilt.cmake", "w") as out:
273-
# drop -l prefix here
274-
sharedlibs = " ".join(l[2:] for l in libs.shared)
275-
out.write(CMAKELISTS_EXPORTED_FMT.format(exported=EXPORTED_LIB, libs=sharedlibs))
276-
copy_includes(installed, tgt)
277-
create_sdk(installed, tgt / "sdk")
278-
return tgt
181+
l.rename(exported_dir / l.name)
182+
183+
184+
def export_headers(exported_dir, swift_source_tree, llvm_build_tree, swift_build_tree):
185+
print("exporting headers")
186+
# Assuming default checkout where LLVM sources are placed next to Swift sources
187+
llvm_source_tree = swift_source_tree.parent / 'llvm-project/llvm'
188+
clang_source_tree = swift_source_tree.parent / 'llvm-project/clang'
189+
clang_tools_build_tree = llvm_build_tree / 'tools/clang'
190+
header_dirs = [ llvm_source_tree, clang_source_tree, swift_source_tree, llvm_build_tree, swift_build_tree, clang_tools_build_tree ]
191+
for h in header_dirs:
192+
copy_includes(h, exported_dir)
279193

280194

281195
def zip_dir(src, tgt):
@@ -296,27 +210,17 @@ def main(opts):
296210
if os.path.exists(tmp):
297211
shutil.rmtree(tmp)
298212
os.mkdir(tmp)
299-
if opts.update_shared or opts.update_static:
300-
for project, deps in DEPS.items():
301-
build(getattr(opts, project), deps)
302-
configured = configure_dummy_project(tmp, llvm=opts.llvm, swift=opts.swift)
303-
libs = get_libs(configured)
304-
if opts.update_shared:
305-
create_shared_lib(opts.update_shared, libs)
306-
if opts.update_static:
307-
create_static_lib(opts.update_static, libs)
308-
else:
309-
installed = install(tmp, opts)
310-
swift_syntax_build = opts.swift / "include/swift/Syntax/"
311-
swift_syntax_install = installed / "usr/include/swift/Syntax/"
312-
for header in os.listdir(swift_syntax_build):
313-
if header.endswith('.h') or header.endswith('.def'):
314-
shutil.copy(swift_syntax_build / header, swift_syntax_install / header)
315-
configured = configure_dummy_project(tmp, installed=installed)
316-
libs = get_libs(configured)
317-
exported = create_export_dir(tmp, installed, libs)
318-
zip_dir(exported, opts.output)
319-
tar_dir(exported, opts.output)
213+
configured = configure_dummy_project(tmp, llvm=opts.llvm_build_tree, swift=opts.swift_build_tree)
214+
libs = get_libs(configured)
215+
216+
exported = tmp / "exported"
217+
exported.mkdir()
218+
export_libs(exported, libs)
219+
export_headers(exported, opts.swift_source_tree, opts.llvm_build_tree, opts.swift_build_tree)
220+
export_sdk(exported / "sdk", opts.swift_source_tree, opts.swift_build_tree)
221+
222+
zip_dir(exported, opts.output)
223+
tar_dir(exported, opts.output)
320224

321225

322226
if __name__ == "__main__":

‎swift-build-presets

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[preset: codeql-baseline]
2-
bootstrapping=off
2+
bootstrapping=hosttools
33

44
llvm-cmake-options=-DLLVM_ENABLE_TERMINFO=OFF -DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64
55

0 commit comments

Comments
 (0)