Hash :
e3cba40e
Author :
Date :
2024-04-30T17:47:36
gn: Add install target Define an install_target GN template which installs include directories and a predefined list of libraries to a given prefix. The template is taking advantage of an install_target.py script which generates package config files for every named target. Bug: angleproject:8110 Change-Id: I6deb40fe9c54f11da7caf4fb5df59d3ce522df29 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5553797 Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Cody Northrop <cnorthrop@google.com> Reviewed-by: Cody Northrop <cnorthrop@google.com> Auto-Submit: Antonio Caggiano <quic_acaggian@quicinc.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
#! /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())