| #! /usr/bin/env python3 |
| # Copyright 2024 Google Inc. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """Install script for ANGLE targets |
| |
| 1. Suppose this is your custom prefix: |
| `export CUSTOM_PREFIX=/custom/prefix |
| 2. Configure the install prefix with gn: |
| `gn gen --args="install_prefix=\"$CUSTOM_PREFIX\"" out` |
| 3. Then install ANGLE: |
| `ninja -C out install_angle` |
| |
| This will copy all needed include directories under $CUSTOM_PREFIX/include and the |
| libraries will be copied to $CUSTOM_PREFIX/lib. A package config file is generated for |
| each library under $CUSTOM_PREFIX/lib/pkgconfig, therefore ANGLE libraries can be |
| discovered by package config making sure this path is listed in the PKG_CONFIG_PATH |
| environment variable. |
| ``` |
| export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$CUSTOM_PREFIX/lib/pkgconfig |
| pkg-config --libs EGL |
| pkg-config --cflags EGL |
| ``` |
| """ |
| |
| import argparse |
| import os |
| import shutil |
| import sys |
| |
| |
| def install2(src_list: list, dst_dir: str): |
| """Installs a list of files or directories in `src_list` to `dst_dir`""" |
| os.makedirs(dst_dir, exist_ok=True) |
| for src in src_list: |
| if not os.path.exists(src): |
| raise FileNotFoundError("Failed to find {}".format(src)) |
| basename = os.path.basename(src) |
| dst = os.path.join(dst_dir, basename) |
| print("Installing {} to {}".format(src, dst)) |
| if os.path.isdir(src): |
| shutil.copytree(src, dst, dirs_exist_ok=True) |
| else: |
| shutil.copy2(src, dst) |
| |
| |
| PC_TEMPLATE = """prefix={prefix} |
| libdir=${{prefix}}/lib |
| includedir=${{prefix}}/include |
| |
| Name: {name} |
| Description: {description} |
| Version: {version} |
| Libs: -L${{libdir}} {link_libraries} |
| Cflags: -I${{includedir}} |
| """ |
| |
| |
| def gen_link_libraries(libs: list): |
| """Generates a string that can be used for the `Libs:` entry of a pkgconfig file""" |
| link_libraries = "" |
| for lib in libs: |
| # Absolute paths to file names only -> libEGL.dylib |
| basename = os.path.basename(lib) |
| # lib name only -> libEGL |
| libname: str = os.path.splitext(basename)[0] |
| # name only -> EGL |
| name = libname.strip('lib') |
| link_libraries += '-l{}'.format(name) |
| return link_libraries |
| |
| |
| def gen_pkgconfig(name: str, version: str, prefix: os.path.abspath, libs: list): |
| """Generates a pkgconfig file for the current target""" |
| # Remove lib from name -> EGL |
| no_lib_name = name.strip('lib') |
| description = "ANGLE's {}".format(no_lib_name) |
| name_lowercase = no_lib_name.lower() |
| link_libraries = gen_link_libraries(libs) |
| pc_content = PC_TEMPLATE.format( |
| name=name_lowercase, |
| prefix=prefix, |
| description=description, |
| version=version, |
| link_libraries=link_libraries) |
| |
| lib_pkgconfig_path = os.path.join(prefix, 'lib/pkgconfig') |
| if not os.path.exists(lib_pkgconfig_path): |
| os.makedirs(lib_pkgconfig_path) |
| |
| pc_path = os.path.join(lib_pkgconfig_path, '{}.pc'.format(name_lowercase)) |
| print("Generating {}".format(pc_path)) |
| with open(pc_path, 'w+') as pc_file: |
| pc_file.write(pc_content) |
| |
| |
| def install(name, version, prefix: os.path.abspath, libs: list, includes: list): |
| """Installs under `prefix` |
| - the libraries in the `libs` list |
| - the include directories in the `includes` list |
| - the pkgconfig file for current target if name is set""" |
| install2(libs, os.path.join(prefix, "lib")) |
| |
| for include in includes: |
| assert (os.path.isdir(include)) |
| incs = [inc.path for inc in os.scandir(include)] |
| install2(incs, os.path.join(prefix, "include")) |
| |
| if name: |
| gen_pkgconfig(name, version, prefix, libs) |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser(description='Install script for ANGLE targets') |
| parser.add_argument( |
| '--name', |
| help='Name of the target (e.g., EGL or GLESv2). Set it to generate a pkgconfig file', |
| ) |
| parser.add_argument( |
| '--version', help='SemVer of the target (e.g., 0.1.0 or 2.1)', default='0.0.0') |
| parser.add_argument( |
| '--prefix', |
| help='Install prefix to use (e.g., out/install or /usr/local/)', |
| default='', |
| type=os.path.abspath) |
| parser.add_argument( |
| '--libs', |
| help='List of libraries to install (e.g., libEGL.dylib or libGLESv2.so)', |
| default=[], |
| nargs='+', |
| type=os.path.abspath) |
| parser.add_argument( |
| '-I', |
| '--includes', |
| help='List of include directories to install (e.g., include or ../include)', |
| default=[], |
| nargs='+', |
| type=os.path.abspath) |
| |
| args = parser.parse_args() |
| install(args.name, args.version, args.prefix, args.libs, args.includes) |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |