summaryrefslogtreecommitdiff
path: root/recipes/x265.recipe
blob: 4fa7499e35c904ee03decf84d815117e15874bd7 (plain)
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
 # -*- Mode: Python -*- vi:si:et:sw=4:sts=4:ts=4:syntax=python

from pathlib import Path
import shutil
import tempfile
from cerbero.utils import shell
from cerbero.tools.libtool import LibtoolLibrary


class Recipe(recipe.Recipe):
    name = 'x265'
    version = '3.6'
    licenses = [License.GPLv2Plus]
    stype = SourceType.CUSTOM
    btype = BuildType.CMAKE
    library_type = LibraryType.BOTH
    cmake_generator = 'ninja'
    can_msvc = True
    configure_options = ' -DENABLE_CLI=OFF -DLINKED_10BIT=ON -DLINKED_12BIT=ON '
    deps = ['x265-10bit', 'x265-12bit']

    files_libs = ['libx265']
    files_devel = ['%(libdir)s/pkgconfig/x265.pc', 'include/x265.h', 'include/x265_config.h']

    def prepare(self):
        if self.config.target_platform == Platform.LINUX:
            # Doesn't use GNUInstallDirs so prefix must be manually fixed
            self.configure_options += f' -DLIB_INSTALL_DIR={self.config.libdir} '
        if self.config.target_platform == Platform.ANDROID:
            self.append_env('CXXFLAGS', '-frtti', '-fexceptions')
            if self.config.target_arch != Architecture.X86_64:
                # Arm64 assembly is completely incompatible
                self.configure_options += ' -DENABLE_ASSEMBLY=OFF '
        # x265 ignores CCASFLAGS
        elif self.config.target_platform == Platform.IOS:
            self.configure_options += ' -DENABLE_ASSEMBLY=OFF '
        elif self.config.target_arch == Architecture.X86:
            # on x86 it tries to use the high bank of AVX
            self.configure_options += ' -DENABLE_ASSEMBLY=OFF '
        self.config_src_dir = os.path.join(self.config.sources, f'x265-src-{self.version}', 'source')
        self.build_dir = os.path.join(self.config_src_dir, 'b')
        self.make_dir = self.config_src_dir
        Path(self.build_dir).mkdir(parents=True, exist_ok=True)

        prefix = '' if self.using_msvc() else 'lib'
        self.hdr10lib = Path(self.config_src_dir) / 'b-10bit' / f'{prefix}x265-10bit.a'
        self.hdr12lib = Path(self.config_src_dir) / 'b-12bit' / f'{prefix}x265-12bit.a'

    async def configure(self):
        if self.config.target_platform == Platform.WINDOWS:
            system_name = 'Windows'
        elif self.config.target_platform == Platform.LINUX:
            system_name = 'Linux'
        elif self.config.target_platform == Platform.DARWIN:
            system_name = 'Darwin'
        elif self.config.target_platform == Platform.IOS:
            system_name = 'iOS'

        # We always need a toolchain file because CMakeLists.txt requires these values to be set.
        # The Android NDK provides one, so we use that as-is.
        # This recipe uses these to decide which optimizations to use:
        # https://github.com/pnggroup/libpng/blob/libpng16/CMakeLists.txt#L130
        if self.config.target_platform == Platform.ANDROID:
            arch = self.config.target_arch
            if self.config.target_arch == Architecture.ARMv7:
                arch = 'armeabi-v7a'
            elif self.config.target_arch == Architecture.ARM64:
                arch = 'arm64-v8a'
            self.configure_options += f" -DCMAKE_TOOLCHAIN_FILE={self.config.env['ANDROID_NDK_HOME']}/build/cmake/android.toolchain.cmake -DANDROID_ABI={arch}"
        else:
            Path(self.build_dir).mkdir(exist_ok=True)
            with open(f'{self.build_dir}/toolchain.cmake', 'w') as f:
                f.write(f'set(CMAKE_SYSTEM_NAME {system_name})\n')
                f.write(f'set(CMAKE_SYSTEM_PROCESSOR {self.config.target_arch})\n')
            self.configure_options += f' -DCMAKE_TOOLCHAIN_FILE={self.build_dir}/toolchain.cmake'

        self.configure_options += f' -DEXTRA_LIB={self.hdr10lib.as_posix()};{self.hdr12lib.as_posix()} '
        await super().configure()

    def post_install(self):
        # Craft a wholearchive of 8-, 10- and 12-bit x265
        if self.using_msvc():
            lib_exe = shutil.which('lib', path=self.config.msvc_env_for_toolchain['PATH'].get())
            shell.check_output(
                [
                    lib_exe,
                    "/OUT:x265.a",
                    str(self.hdr10lib.absolute()),
                    str(self.hdr12lib.absolute()),
                ],
                cmd_dir=self.config.libdir,
                logfile=self.logfile,
            )
        elif self.config.target_platform in (Platform.DARWIN, Platform.IOS):
            libtool = shutil.which('libtool')
            shell.check_output(
                [
                    libtool,
                    "-static",
                    "-o",
                    "libx265.a",
                    str(self.hdr10lib.absolute()),
                    str(self.hdr12lib.absolute()),
                ],
                cmd_dir=self.config.libdir,
                logfile=self.logfile,
            )
        else:
            ar = shutil.which('ar')
            with tempfile.TemporaryDirectory() as tmpdir:
                whole_lib = os.path.join(self.config.libdir, 'libx265.a')
                shutil.copy(whole_lib, os.path.join(tmpdir, 'libx265-8bit.a'))
                shutil.copy(self.hdr10lib, tmpdir)
                shutil.copy(self.hdr12lib, tmpdir)
                mri = b'CREATE libx265.a\nADDLIB libx265-8bit.a\nADDLIB libx265-10bit.a\nADDLIB libx265-12bit.a\nSAVE\nEND\n'
                shell.new_call(
                    ' '.join([
                        ar,
                        "-M"
                    ]),
                    input=mri,
                    cmd_dir=tmpdir,
                    logfile=self.logfile,
                )
                shutil.copy(os.path.join(tmpdir, 'libx265.a'), whole_lib)
        libtool_la = LibtoolLibrary(self.name, None, None, None, self.config.libdir,
                self.config.target_platform)
        libtool_la.save()
        super().post_install()