Skip to content

Commit fe2c47c

Browse files
authored
Merge pull request #4 from dsp-testing/alexdenisov/enable-bootstrapping
Swift: enable bootstrapping
2 parents 96a5813 + a887c9a commit fe2c47c

File tree

5 files changed

+92
-224
lines changed

5 files changed

+92
-224
lines changed

CMakeLists.txt

Lines changed: 34 additions & 0 deletions
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

Lines changed: 57 additions & 151 deletions
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,29 @@ 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+
script_dir = pathlib.Path(os.path.realpath(__file__)).parent
63+
print(script_dir)
64+
shutil.copy(script_dir / "CMakeLists.txt", tmp / "CMakeLists.txt")
65+
shutil.copy(script_dir / "empty.cpp", tmp / "empty.cpp")
15566
tgt = tmp / "build"
15667
tgt.mkdir()
157-
run(["cmake", f"-DLLVM_ROOT={llvm}", f"-DSWIFT_ROOT={swift}", "-DBUILD_SHARED_LIBS=OFF", ".."],
68+
run(["cmake", f"-DCMAKE_PREFIX_PATH={llvm};{swift}", "-DBUILD_SHARED_LIBS=OFF", ".."],
15869
cwd=tgt)
15970
return tgt
16071

16172

16273
def get_libs(configured):
16374
print("extracting linking information from dummy project")
164-
with open(configured / "CMakeFiles" / "dummy.dir" / "link.txt") as link:
75+
with open(configured / "CMakeFiles" / "codeql-swift-artifacts.dir" / "link.txt") as link:
16576
libs = link.read().split()
166-
libs = libs[libs.index('dummy')+1:] # skip up to -o dummy
167-
ret = Libs([], [], [])
77+
libs = libs[libs.index('codeql-swift-artifacts')+1:] # skip up to -o dummy
78+
ret = Libs([], [], [], [])
16879
for l in libs:
16980
if l.endswith(".a"):
17081
ret.static.append(str((configured / l).resolve()))
@@ -173,11 +84,10 @@ def get_libs(configured):
17384
ret.shared.append(f"-l{l[3:]}") # drop 'lib' prefix and '.so' suffix
17485
elif l.startswith("-l"):
17586
ret.shared.append(l)
87+
elif l.startswith("-L") or l.startswith("-Wl"):
88+
ret.linker_flags.append(l)
17689
else:
17790
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)] = []
18191
return ret
18292

18393

@@ -195,7 +105,6 @@ def create_static_lib(tgt, libs):
195105
mriscript = f"create {tgt}\n{includedlibs}\nsave\nend"
196106
run(["ar", "-M"], cwd=tgt.parent, input=mriscript)
197107
else:
198-
includedlibs = " ".join(f"{l}" for l in libs.archive + libs.static)
199108
libtool_args = ["libtool", "-static"]
200109
libtool_args.extend(libs.archive)
201110
libtool_args.extend(libs.static)
@@ -214,6 +123,7 @@ def create_shared_lib(tgt, libs):
214123
print(f"packaging {libname}")
215124
compiler = os.environ.get("CC", "clang")
216125
cmd = [compiler, "-shared"]
126+
cmd.extend(libs.linker_flags)
217127

218128
if sys.platform == 'linux':
219129
cmd.append("-Wl,--whole-archive")
@@ -239,17 +149,17 @@ def create_shared_lib(tgt, libs):
239149
def copy_includes(src, tgt):
240150
print("copying includes")
241151
for dir, exts in (("include", ("h", "def", "inc")), ("stdlib", ("h",))):
242-
srcdir = src / "usr" / dir
152+
srcdir = src / dir
243153
for ext in exts:
244154
for srcfile in srcdir.rglob(f"*.{ext}"):
245155
tgtfile = tgt / dir / srcfile.relative_to(srcdir)
246156
tgtfile.parent.mkdir(parents=True, exist_ok=True)
247157
shutil.copy(srcfile, tgtfile)
248158

249159

250-
def create_sdk(installed, tgt):
160+
def export_sdk(tgt, swift_source_tree, swift_build_tree):
251161
print("assembling sdk")
252-
srcdir = installed / "usr" / "lib" / "swift"
162+
srcdir = swift_build_tree/ "lib" / "swift"
253163
tgtdir = tgt / "usr" / "lib" / "swift"
254164
if get_platform() == "linux":
255165
srcdir /= "linux"
@@ -258,24 +168,30 @@ def create_sdk(installed, tgt):
258168
srcdir /= "macosx"
259169
for mod in srcdir.glob("*.swiftmodule"):
260170
shutil.copytree(mod, tgtdir / mod.name)
261-
shutil.copytree(installed / "usr" / "stdlib" / "public" / "SwiftShims",
262-
tgt / "usr" / "include" / "SwiftShims")
171+
shutil.copytree(swift_source_tree / "stdlib" / "public" / "SwiftShims",
172+
tgt / "usr" / "include" / "SwiftShims",
173+
ignore=shutil.ignore_patterns('CMakeLists.txt'))
263174

264175

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()
176+
def export_libs(exported_dir, libs):
177+
print("exporting libraries")
178+
exportedlibs = [
179+
create_static_lib(exported_dir, libs),
180+
create_shared_lib(exported_dir, libs)
181+
]
270182
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
183+
l.rename(exported_dir / l.name)
184+
185+
186+
def export_headers(exported_dir, swift_source_tree, llvm_build_tree, swift_build_tree):
187+
print("exporting headers")
188+
# Assuming default checkout where LLVM sources are placed next to Swift sources
189+
llvm_source_tree = swift_source_tree.parent / 'llvm-project/llvm'
190+
clang_source_tree = swift_source_tree.parent / 'llvm-project/clang'
191+
clang_tools_build_tree = llvm_build_tree / 'tools/clang'
192+
header_dirs = [ llvm_source_tree, clang_source_tree, swift_source_tree, llvm_build_tree, swift_build_tree, clang_tools_build_tree ]
193+
for h in header_dirs:
194+
copy_includes(h, exported_dir)
279195

280196

281197
def zip_dir(src, tgt):
@@ -296,27 +212,17 @@ def main(opts):
296212
if os.path.exists(tmp):
297213
shutil.rmtree(tmp)
298214
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)
215+
configured = configure_dummy_project(tmp, llvm=opts.llvm_build_tree, swift=opts.swift_build_tree)
216+
libs = get_libs(configured)
217+
218+
exported = tmp / "exported"
219+
exported.mkdir()
220+
export_libs(exported, libs)
221+
export_headers(exported, opts.swift_source_tree, opts.llvm_build_tree, opts.swift_build_tree)
222+
export_sdk(exported / "sdk", opts.swift_source_tree, opts.swift_build_tree)
223+
224+
zip_dir(exported, opts.output)
225+
tar_dir(exported, opts.output)
320226

321227

322228
if __name__ == "__main__":

swift-build-presets

Lines changed: 1 addition & 1 deletion
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)