File: cmake.py

package info (click to toggle)
mpd 0.24.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 10,740 kB
  • sloc: cpp: 74,967; python: 1,371; xml: 628; perl: 469; java: 289; sh: 286; ansic: 235; makefile: 105
file content (130 lines) | stat: -rw-r--r-- 4,883 bytes parent folder | download | duplicates (2)
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
import os
import re
import subprocess
from typing import cast, Optional, Sequence, TextIO, Union
from collections.abc import Mapping

from build.project import Project
from .toolchain import AnyToolchain

def __write_cmake_compiler(f: TextIO, language: str, compiler: str) -> None:
    s = compiler.split(' ', 1)
    if len(s) == 2:
        print(f'set(CMAKE_{language}_COMPILER_LAUNCHER {s[0]})', file=f)
        compiler = s[1]
    print(f'set(CMAKE_{language}_COMPILER {compiler})', file=f)

def __write_cmake_toolchain_file(f: TextIO, toolchain: AnyToolchain) -> None:
    if toolchain.is_darwin:
        cmake_system_name = 'Darwin'
    elif toolchain.is_windows:
        cmake_system_name = 'Windows'
    else:
        cmake_system_name = 'Linux'

    f.write(f"""
set(CMAKE_SYSTEM_NAME {cmake_system_name})
set(CMAKE_SYSTEM_PROCESSOR {toolchain.host_triplet.split('-', 1)[0]})

set(CMAKE_C_COMPILER_TARGET {toolchain.host_triplet})
set(CMAKE_CXX_COMPILER_TARGET {toolchain.host_triplet})

set(CMAKE_C_FLAGS_INIT "{toolchain.cflags} {toolchain.cppflags}")
set(CMAKE_CXX_FLAGS_INIT "{toolchain.cxxflags} {toolchain.cppflags}")
""")
    __write_cmake_compiler(f, 'C', toolchain.cc)
    __write_cmake_compiler(f, 'CXX', toolchain.cxx)

    if cmake_system_name == 'Darwin':
        # On macOS, cmake forcibly adds an "-isysroot" flag even if
        # one is already present in the flags variable; this breaks
        # cross-compiling for iOS, and can be worked around by setting
        # the CMAKE_OSX_SYSROOT variable
        # (https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_SYSROOT.html).
        m = re.search(r'-isysroot +(\S+)', toolchain.cflags)
        if m:
            sysroot = m.group(1)

            print(f'set(CMAKE_OSX_SYSROOT {sysroot})', file=f)

            # search libraries and headers only in the sysroot, not on
            # the build host
            f.write(f"""
set(CMAKE_FIND_ROOT_PATH "{toolchain.install_prefix};{sysroot}")
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
""")
    elif cmake_system_name == 'Windows':
            # search libraries and headers only in the sysroot, not on
            # the build host
            f.write(f"""
set(CMAKE_FIND_ROOT_PATH "{toolchain.install_prefix}")
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
""")

def configure(toolchain: AnyToolchain, src: str, build: str, args: list[str]=[], env: Optional[Mapping[str, str]]=None) -> None:
    cross_args: list[str] = []

    if toolchain.is_windows:
        cross_args.append('-DCMAKE_RC_COMPILER=' + cast(str, toolchain.windres))

    configure = [
        'cmake',
        src,

        '-DCMAKE_INSTALL_PREFIX=' + toolchain.install_prefix,
        '-DCMAKE_BUILD_TYPE=release',

        '-GNinja',
    ] + cross_args + args

    if toolchain.host_triplet is not None:
        # cross-compiling: write a toolchain file
        os.makedirs(build, exist_ok=True)

        # Several targets need a sysroot to prevent pkg-config from
        # looking for libraries on the build host (TODO: fix this
        # properly); but we must not do that on Android because the NDK
        # has a sysroot already
        if not toolchain.is_android and not toolchain.is_darwin:
            cross_args.append('-DCMAKE_SYSROOT=' + toolchain.install_prefix)

        cmake_toolchain_file = os.path.join(build, 'cmake_toolchain_file')
        with open(cmake_toolchain_file, 'w') as f:
            __write_cmake_toolchain_file(f, toolchain)

        configure.append('-DCMAKE_TOOLCHAIN_FILE=' + cmake_toolchain_file)

    if env is None:
        env = toolchain.env
    else:
        env = {**toolchain.env, **env}

    print(configure)
    subprocess.check_call(configure, env=env, cwd=build)

class CmakeProject(Project):
    def __init__(self, url: Union[str, Sequence[str]], md5: str, installed: str,
                 configure_args: list[str]=[],
                 windows_configure_args: list[str]=[],
                 env: Optional[Mapping[str, str]]=None,
                 **kwargs):
        Project.__init__(self, url, md5, installed, **kwargs)
        self.configure_args = configure_args
        self.windows_configure_args = windows_configure_args
        self.env = env

    def configure(self, toolchain: AnyToolchain) -> str:
        src = self.unpack(toolchain)
        build = self.make_build_path(toolchain)
        configure_args = self.configure_args
        if toolchain.is_windows:
            configure_args = configure_args + self.windows_configure_args
        configure(toolchain, src, build, configure_args, self.env)
        return build

    def _build(self, toolchain: AnyToolchain) -> None:
        build = self.configure(toolchain)
        subprocess.check_call(['ninja', '-v', 'install'],
                              cwd=build, env=toolchain.env)