[K/N] Option to build smaller LLVM distribution.
Also add a few adjustments to `package.py`: * Enable threading in LLVM * Replace `--archive-path` with `--pack` to avoid naming divergence.
This commit is contained in:
@@ -18,24 +18,42 @@ python3 package.py
|
|||||||
```
|
```
|
||||||
It will create a `llvm-distribution` folder which contains LLVM distribution.
|
It will create a `llvm-distribution` folder which contains LLVM distribution.
|
||||||
Note that build will take a lot of time and all your machine cores. 😈
|
Note that build will take a lot of time and all your machine cores. 😈
|
||||||
See [HACKING.md](../../HACKING.md#using-different-llvm-distributions-as-part-of-kotlinnative-compilation-pipeline) on how to use freshly built distribution.
|
See [HACKING.md](../../HACKING.md#using-different-llvm-distributions-as-part-of-kotlinnative-compilation-pipeline)
|
||||||
|
on how to use freshly built distribution.
|
||||||
|
|
||||||
|
### Building distribution for end-users
|
||||||
|
By default, `package.py` installs a lot of LLVM components that is not really required to use Kotlin/Native compiler.
|
||||||
|
To build only essential parts, run the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
python3 package.py --build-targets install-distribution --distribution-components $DISTRIBUTION_COMPONENTS
|
||||||
|
```
|
||||||
|
Set of required `$DISTRIBUTION_COMPONENTS` is depends on OS:
|
||||||
|
|
||||||
|
| OS | Distribution components |
|
||||||
|
| --- | --- |
|
||||||
|
|Windows | `clang libclang lld llvm-cov llvm-profdata llvm-ar clang-resource-headers` |
|
||||||
|
|macOS | `clang libclang lld llvm-cov llvm-profdata llvm-ar clang-resource-headers` |
|
||||||
|
|Linux | `clang libclang lld llvm-cov llvm-profdata llvm-ar clang-resource-headers compiler_rt` |
|
||||||
|
|
||||||
### Tuning
|
### Tuning
|
||||||
Run `python3 package.py -h` to check how one can tune script's behavior.
|
Run `python3 package.py -h` to check how one can tune script's behavior.
|
||||||
Some examples:
|
Some examples:
|
||||||
* `--archive-path` creates an archive (`zip` on Windows, `tar.gz` on macOS and Linux) with distribution
|
* `--pack` creates an archive (`zip` on Windows, `tar.gz` on macOS and Linux) with distribution
|
||||||
alongside with its SHA256.
|
alongside with its SHA256.
|
||||||
* `--install-path` allows overriding distribution's output directory.
|
* `--install-path` allows overriding distribution's output directory.
|
||||||
* `--num-stages` specifies number of steps in build. Passing 2 or more makes bootstrap build which
|
* `--num-stages` specifies number of steps in build. Passing 2 or more makes bootstrap build which
|
||||||
means that LLVM will build itself by using distribution from the previous step.
|
means that LLVM will build itself by using distribution from the previous step.
|
||||||
* `--stage0` allows using existing LLVM toolchain for bootstrapping.
|
* `--stage0` allows using existing LLVM toolchain for bootstrapping.
|
||||||
|
* `--build-targets` specifies what targets will be passed to Ninja.
|
||||||
|
* `--distribution-components` is a list of components that will be installed with `install-distribution` build target.
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
|
||||||
You can use Docker to build LLVM for Linux:
|
You can use Docker to build LLVM for Linux:
|
||||||
```shell
|
```shell
|
||||||
docker build -t kotlin-llvm-builder .
|
docker build -t kotlin-llvm-builder .
|
||||||
docker run --rm -it -v <HOST_PATH>:/output kotlin-llvm-builder --archive-path /output/llvm-11.1.0-linux-x64
|
docker run --rm -it -v <HOST_PATH>:/output kotlin-llvm-builder --install-path /output/llvm-11.1.0-linux-x64 --pack
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -43,5 +61,3 @@ docker run --rm -it -v <HOST_PATH>:/output kotlin-llvm-builder --archive-path /o
|
|||||||
1. Bootstrap build is not working on macOS for default git branch.
|
1. Bootstrap build is not working on macOS for default git branch.
|
||||||
2. `libcxx` and `compiler-rt` are built as projects, not runtimes.
|
2. `libcxx` and `compiler-rt` are built as projects, not runtimes.
|
||||||
3. No way to run LLVM tests out of the box.
|
3. No way to run LLVM tests out of the box.
|
||||||
4. No way to override default `install` task out of the box.
|
|
||||||
|
|
||||||
|
|||||||
@@ -92,13 +92,31 @@ def construct_cmake_flags(
|
|||||||
install_path: str = None,
|
install_path: str = None,
|
||||||
projects: List[str] = None,
|
projects: List[str] = None,
|
||||||
runtimes: List[str] = None,
|
runtimes: List[str] = None,
|
||||||
targets: List[str] = None
|
targets: List[str] = None,
|
||||||
|
distribution_components: List[str] = None
|
||||||
) -> List[str]:
|
) -> List[str]:
|
||||||
building_bootstrap = bootstrap_llvm_path is None
|
building_bootstrap = bootstrap_llvm_path is None
|
||||||
|
|
||||||
c_compiler, cxx_compiler, linker, ar = None, None, None, None
|
c_compiler, cxx_compiler, linker, ar = None, None, None, None
|
||||||
c_flags, cxx_flags, linker_flags = None, None, None
|
c_flags, cxx_flags, linker_flags = None, None, None
|
||||||
|
|
||||||
|
cmake_args = [
|
||||||
|
'-DCMAKE_BUILD_TYPE=Release',
|
||||||
|
'-DLLVM_ENABLE_ASSERTIONS=OFF',
|
||||||
|
'-DLLVM_ENABLE_TERMINFO=OFF',
|
||||||
|
'-DLLVM_INCLUDE_GO_TESTS=OFF',
|
||||||
|
'-DLLVM_ENABLE_Z3_SOLVER=OFF',
|
||||||
|
'-DCOMPILER_RT_BUILD_BUILTINS=ON',
|
||||||
|
'-DLLVM_ENABLE_THREADS=ON',
|
||||||
|
'-DLLVM_OPTIMIZED_TABLEGEN=ON'
|
||||||
|
]
|
||||||
if not building_bootstrap:
|
if not building_bootstrap:
|
||||||
|
if distribution_components:
|
||||||
|
cmake_args.append('-DLLVM_DISTRIBUTION_COMPONENTS=' + ';'.join(distribution_components))
|
||||||
|
# These links are actually copies on windows, so they're wasting precious disk space.
|
||||||
|
cmake_args.append("-DCLANG_LINKS_TO_CREATE=clang++")
|
||||||
|
cmake_args.append("-DLLD_SYMLINKS_TO_CREATE=ld.lld;wasm-ld")
|
||||||
|
|
||||||
if host_is_windows():
|
if host_is_windows():
|
||||||
# CMake is not tolerant to backslashes
|
# CMake is not tolerant to backslashes
|
||||||
c_compiler = f'{bootstrap_llvm_path}/bin/clang-cl.exe'.replace('\\', '/')
|
c_compiler = f'{bootstrap_llvm_path}/bin/clang-cl.exe'.replace('\\', '/')
|
||||||
@@ -120,14 +138,6 @@ def construct_cmake_flags(
|
|||||||
cxx_flags = ['-isysroot', isysroot, '-stdlib=libc++']
|
cxx_flags = ['-isysroot', isysroot, '-stdlib=libc++']
|
||||||
linker_flags = ['-stdlib=libc++']
|
linker_flags = ['-stdlib=libc++']
|
||||||
|
|
||||||
cmake_args = [
|
|
||||||
'-DCMAKE_BUILD_TYPE=Release',
|
|
||||||
'-DLLVM_ENABLE_ASSERTIONS=OFF',
|
|
||||||
'-DLLVM_ENABLE_TERMINFO=OFF',
|
|
||||||
'-DLLVM_INCLUDE_GO_TESTS=OFF',
|
|
||||||
'-DLLVM_ENABLE_Z3_SOLVER=OFF',
|
|
||||||
'-DCOMPILER_RT_BUILD_BUILTINS=ON'
|
|
||||||
]
|
|
||||||
|
|
||||||
if host_is_darwin():
|
if host_is_darwin():
|
||||||
cmake_args.append('-DLLVM_ENABLE_LIBCXX=ON')
|
cmake_args.append('-DLLVM_ENABLE_LIBCXX=ON')
|
||||||
@@ -186,7 +196,7 @@ def construct_cmake_flags(
|
|||||||
# Also not working for Linux and macOS because of signal chaining.
|
# Also not working for Linux and macOS because of signal chaining.
|
||||||
# TODO: Enable after LLVM distribution patching.
|
# TODO: Enable after LLVM distribution patching.
|
||||||
if not host_is_windows():
|
if not host_is_windows():
|
||||||
cmake_args.append("-LLVM_BUILD_LLVM_DYLIB=OFF")
|
cmake_args.append("-DLLVM_BUILD_LLVM_DYLIB=OFF")
|
||||||
cmake_args.append("-DLLVM_LINK_LLVM_DYLIB=OFF")
|
cmake_args.append("-DLLVM_LINK_LLVM_DYLIB=OFF")
|
||||||
|
|
||||||
return cmake_args
|
return cmake_args
|
||||||
@@ -221,11 +231,11 @@ def force_create_directory(parent, name) -> Path:
|
|||||||
|
|
||||||
|
|
||||||
def llvm_build_commands(
|
def llvm_build_commands(
|
||||||
install_path, bootstrap_path, llvm_src, targets, ninja_target, projects, runtimes
|
install_path, bootstrap_path, llvm_src, targets, build_targets, projects, runtimes, distribution_components
|
||||||
) -> List[List[str]]:
|
) -> List[List[str]]:
|
||||||
cmake_flags = construct_cmake_flags(bootstrap_path, install_path, projects, runtimes, targets)
|
cmake_flags = construct_cmake_flags(bootstrap_path, install_path, projects, runtimes, targets, distribution_components)
|
||||||
cmake_command = [cmake, "-G", "Ninja"] + cmake_flags + [os.path.join(llvm_src, "llvm")]
|
cmake_command = [cmake, "-G", "Ninja"] + cmake_flags + [os.path.join(llvm_src, "llvm")]
|
||||||
ninja_command = [ninja, ninja_target]
|
ninja_command = [ninja] + build_targets
|
||||||
return [cmake_command, ninja_command]
|
return [cmake_command, ninja_command]
|
||||||
|
|
||||||
|
|
||||||
@@ -250,12 +260,18 @@ def default_num_stages():
|
|||||||
|
|
||||||
|
|
||||||
def build_parser() -> argparse.ArgumentParser:
|
def build_parser() -> argparse.ArgumentParser:
|
||||||
parser = argparse.ArgumentParser(description="Build LLVM toochain for Kotlin/Native")
|
parser = argparse.ArgumentParser(description="Build LLVM toolchain for Kotlin/Native")
|
||||||
# Output configuration.
|
# Output configuration.
|
||||||
parser.add_argument("--install-path", type=str, default="llvm-distribution", required=False,
|
parser.add_argument("--install-path", type=str, default="llvm-distribution", required=False,
|
||||||
help="Where final LLVM distribution will be installed")
|
help="Where final LLVM distribution will be enabled")
|
||||||
parser.add_argument("--archive-path", default=None,
|
parser.add_argument("--pack", action='store_true',
|
||||||
help="Create an archive and its sha256 for final distribution at given path")
|
help="Create an archive and its sha256 for final distribution at `--install-path`")
|
||||||
|
parser.add_argument("--build-targets", default=["install"],
|
||||||
|
nargs="+",
|
||||||
|
help="What components should be installed")
|
||||||
|
parser.add_argument("--distribution-components", default=None,
|
||||||
|
nargs="+",
|
||||||
|
help="What components should be installed with `install-distribution` target")
|
||||||
# Build configuration
|
# Build configuration
|
||||||
parser.add_argument("--stage0", type=str, default=None,
|
parser.add_argument("--stage0", type=str, default=None,
|
||||||
help="Path to existing LLVM toolchain")
|
help="Path to existing LLVM toolchain")
|
||||||
@@ -280,7 +296,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
parser.add_argument("--isysroot", type=str, default=None,
|
parser.add_argument("--isysroot", type=str, default=None,
|
||||||
help="(macOS only) Override path to macOS SDK")
|
help="(macOS only) Override path to macOS SDK")
|
||||||
# Misc.
|
# Misc.
|
||||||
parser.add_argument("--save-temporary-files", type=bool, default=False,
|
parser.add_argument("--save-temporary-files", action='store_true',
|
||||||
help="Should intermediate build results be saved?")
|
help="Should intermediate build results be saved?")
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
@@ -312,16 +328,16 @@ def build_distribution(args):
|
|||||||
else:
|
else:
|
||||||
# None targets means all available targets.
|
# None targets means all available targets.
|
||||||
targets = None
|
targets = None
|
||||||
|
|
||||||
if building_final:
|
if building_final:
|
||||||
install_path = args.install_path
|
install_path = args.install_path
|
||||||
|
build_targets = args.build_targets
|
||||||
else:
|
else:
|
||||||
install_path = force_create_directory(current_dir, f"llvm-stage-{stage}")
|
install_path = force_create_directory(current_dir, f"llvm-stage-{stage}")
|
||||||
intermediate_build_results.append(install_path)
|
intermediate_build_results.append(install_path)
|
||||||
|
build_targets = ["install"]
|
||||||
|
|
||||||
projects = ["clang", "lld", "libcxx", "libcxxabi", "compiler-rt"]
|
projects = ["clang", "lld", "libcxx", "libcxxabi", "compiler-rt"]
|
||||||
runtimes = None
|
runtimes = None
|
||||||
ninja_target = "install"
|
|
||||||
|
|
||||||
build_dir = force_create_directory(current_dir, f"llvm-stage-{stage}-build")
|
build_dir = force_create_directory(current_dir, f"llvm-stage-{stage}-build")
|
||||||
intermediate_build_results.append(build_dir)
|
intermediate_build_results.append(build_dir)
|
||||||
@@ -330,9 +346,10 @@ def build_distribution(args):
|
|||||||
bootstrap_path=absolute_path(bootstrap_path),
|
bootstrap_path=absolute_path(bootstrap_path),
|
||||||
llvm_src=absolute_path(args.llvm_src),
|
llvm_src=absolute_path(args.llvm_src),
|
||||||
targets=targets,
|
targets=targets,
|
||||||
ninja_target=ninja_target,
|
build_targets=build_targets,
|
||||||
projects=projects,
|
projects=projects,
|
||||||
runtimes=runtimes
|
runtimes=runtimes,
|
||||||
|
distribution_components=args.distribution_components
|
||||||
)
|
)
|
||||||
|
|
||||||
os.chdir(build_dir)
|
os.chdir(build_dir)
|
||||||
@@ -404,8 +421,8 @@ def main():
|
|||||||
temporary_llvm_repo = clone_llvm_repository(args.repo, args.branch, args.llvm_repo_destination)
|
temporary_llvm_repo = clone_llvm_repository(args.repo, args.branch, args.llvm_repo_destination)
|
||||||
args.llvm_src = temporary_llvm_repo
|
args.llvm_src = temporary_llvm_repo
|
||||||
final_dist = build_distribution(args)
|
final_dist = build_distribution(args)
|
||||||
if args.archive_path is not None:
|
if args.pack:
|
||||||
archive = create_archive(final_dist, args.archive_path)
|
archive = create_archive(final_dist, args.install_path)
|
||||||
create_checksum_file(archive, f"{archive}.sha256")
|
create_checksum_file(archive, f"{archive}.sha256")
|
||||||
if not args.save_temporary_files and temporary_llvm_repo is not None:
|
if not args.save_temporary_files and temporary_llvm_repo is not None:
|
||||||
print(f"Removing temporary directory: {temporary_llvm_repo}")
|
print(f"Removing temporary directory: {temporary_llvm_repo}")
|
||||||
|
|||||||
Reference in New Issue
Block a user