prepare.py 10.7 KB
Newer Older
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
1 2 3 4
#!/usr/bin/env python

############################################################################
# prepare.py
5
# Copyright (C) 2015-2018  Belledonne Communications, Grenoble France
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
#
############################################################################
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
21
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
22 23 24 25
#
############################################################################

import os
Ghislain MARY's avatar
Ghislain MARY committed
26
import platform
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
27
import sys
28
from logging import error, warning, info
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
29 30
from subprocess import Popen
sys.dont_write_bytecode = True
Ghislain MARY's avatar
Ghislain MARY committed
31
sys.path.insert(0, 'linphone-sdk/cmake-builder')
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
32 33
try:
    import prepare
34 35
except Exception as e:
    error(
Ghislain MARY's avatar
Ghislain MARY committed
36
        "Could not find prepare module: {}, probably missing linphone-sdk/cmake-builder? Try running:\n"
37
        "git submodule sync && git submodule update --init --recursive".format(e))
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
38 39 40
    exit(1)


41

Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
42 43
class DesktopTarget(prepare.Target):

44
    def __init__(self, group_builders=False):
45
        prepare.Target.__init__(self, 'desktop')
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
46 47
        current_path = os.path.dirname(os.path.realpath(__file__))
        self.config_file = 'configs/config-desktop.cmake'
48
        self.output = 'OUTPUT/' + self.name
Ghislain MARY's avatar
Ghislain MARY committed
49
        self.external_source_path = os.path.join(current_path, 'linphone-sdk')
Ghislain MARY's avatar
Ghislain MARY committed
50
        self.alternate_external_source_path = os.path.join(current_path, 'submodules')
51 52 53
        self.packaging_args = [
            "-DENABLE_RELATIVE_PREFIX=YES"
        ]
54 55 56 57 58
        external_builders_path = os.path.join(current_path, 'cmake_builder')
        self.additional_args = [
            "-DLINPHONE_BUILDER_EXTERNAL_BUILDERS_PATH=" + external_builders_path,
            "-DLINPHONE_BUILDER_TARGET=linphoneqt"
        ]
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
59

60

61 62 63 64 65 66 67 68 69
class DesktopRaspberryTarget(prepare.Target):

    def __init__(self, group_builders=False):
        prepare.Target.__init__(self, 'desktop-raspberry')
        current_path = os.path.dirname(os.path.realpath(__file__))
        self.required_build_platforms = ['Linux']
        self.config_file = 'configs/config-desktop-raspberry.cmake'
        self.toolchain_file = 'toolchains/toolchain-raspberry.cmake'
        self.output = 'OUTPUT/' + self.name
Ghislain MARY's avatar
Ghislain MARY committed
70
        self.external_source_path = os.path.join(current_path, 'linphone-sdk')
Ghislain MARY's avatar
Ghislain MARY committed
71
        self.alternate_external_source_path = os.path.join(current_path, 'submodules')
72 73 74 75
        self.packaging_args = [
            "-DCMAKE_INSTALL_RPATH=$ORIGIN/../lib",
            "-DENABLE_RELATIVE_PREFIX=YES"
        ]
76 77


78 79 80 81 82 83 84
class DesktopRpmTarget(prepare.Target):

    def __init__(self, group_builders=False):
        prepare.Target.__init__(self, 'desktop-rpm')
        current_path = os.path.dirname(os.path.realpath(__file__))
        self.config_file = 'configs/config-desktop-rpm.cmake'
        self.output = 'OUTPUT/' + self.name
Ghislain MARY's avatar
Ghislain MARY committed
85
        self.external_source_path = os.path.join(current_path, 'linphone-sdk')
Ghislain MARY's avatar
Ghislain MARY committed
86
        self.alternate_external_source_path = os.path.join(current_path, 'submodules')
87 88 89 90 91 92 93
        external_builders_path = os.path.join(current_path, 'cmake_builder')
        self.additional_args = [
            "-DLINPHONE_BUILDER_EXTERNAL_BUILDERS_PATH=" + external_builders_path,
            "-DLINPHONE_BUILDER_TARGET=linphoneqt"
        ]


94 95 96 97 98 99
class NoUITarget(prepare.Target):

    def __init__(self, group_builders=False):
        prepare.Target.__init__(self, 'no-ui')
        current_path = os.path.dirname(os.path.realpath(__file__))
        self.config_file = 'configs/config-desktop.cmake'
Erwan Croze's avatar
Erwan Croze committed
100
        self.output = 'OUTPUT/' + self.name
Ghislain MARY's avatar
Ghislain MARY committed
101
        self.external_source_path = os.path.join(current_path, 'linphone-sdk')
Ghislain MARY's avatar
Ghislain MARY committed
102
        self.alternate_external_source_path = os.path.join(current_path, 'submodules')
103 104
        self.packaging_args = [
            "-DCMAKE_INSTALL_RPATH=$ORIGIN/../lib",
105 106
            "-DENABLE_RELATIVE_PREFIX=YES",
            "-DENABLE_CXX_WRAPPER=OFF"
107 108 109 110 111
        ]




112 113 114
class PythonTarget(prepare.Target):

    def __init__(self):
115
        prepare.Target.__init__(self, 'python')
116 117
        current_path = os.path.dirname(os.path.realpath(__file__))
        self.config_file = 'configs/config-python.cmake'
118
        self.output = 'OUTPUT/' + self.name
Ghislain MARY's avatar
Ghislain MARY committed
119
        self.external_source_path = os.path.join(current_path, 'linphone-sdk')
Ghislain MARY's avatar
Ghislain MARY committed
120
        self.alternate_external_source_path = os.path.join(current_path, 'submodules')
Ghislain MARY's avatar
Ghislain MARY committed
121 122 123 124 125
        external_builders_path = os.path.join(current_path, 'cmake_builder')
        self.additional_args += [
            "-DLINPHONE_BUILDER_EXTERNAL_BUILDERS_PATH=" + external_builders_path,
            "-DLINPHONE_BUILDER_PYTHON_VERSION={}.{}".format(sys.version_info.major, sys.version_info.minor)
        ]
126

127

128 129 130
class PythonRaspberryTarget(prepare.Target):

    def __init__(self):
131
        prepare.Target.__init__(self, 'python-raspberry')
Ghislain MARY's avatar
Ghislain MARY committed
132
        current_path = os.path.dirname(os.path.realpath(__file__))
133 134 135
        self.required_build_platforms = ['Linux']
        self.config_file = 'configs/config-python-raspberry.cmake'
        self.toolchain_file = 'toolchains/toolchain-raspberry.cmake'
136
        self.output = 'OUTPUT/' + self.name
Ghislain MARY's avatar
Ghislain MARY committed
137
        self.external_source_path = os.path.join(current_path, 'linphone-sdk')
Ghislain MARY's avatar
Ghislain MARY committed
138
        self.alternate_external_source_path = os.path.join(current_path, 'submodules')
139 140 141 142 143



desktop_targets = {
    'desktop': DesktopTarget(),
144
    'desktop-raspberry': DesktopRaspberryTarget(),
145 146 147 148
    'desktop-rpm': DesktopRpmTarget(),
    'no-ui' : NoUITarget(),
    'python': PythonTarget(),
    'python-raspberry': PythonRaspberryTarget()
149 150 151 152 153
}

class DesktopPreparator(prepare.Preparator):

    def __init__(self, targets=desktop_targets, default_targets=['desktop']):
154
        prepare.Preparator.__init__(self, targets, default_targets)
155 156 157 158
        self.veryclean = True
        self.argparser.add_argument('-ac', '--all-codecs', help="Enable all codecs, including the non-free ones", action='store_true')
        self.argparser.add_argument('-sys', '--use-system-dependencies', help="Find dependencies on the system.", action='store_true')
        self.argparser.add_argument('-p', '--package', help="Build an installation package (only on Mac OSX and Windows).", action='store_true')
159
        self.argparser.add_argument('-ps', '--package-source', help="Build source packages for the dependencies.", action='store_true')
160 161

    def parse_args(self):
162
        prepare.Preparator.parse_args(self)
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185

        if self.args.use_system_dependencies:
            self.additional_args += ["-DLINPHONE_BUILDER_USE_SYSTEM_DEPENDENCIES=YES"]

        if self.args.all_codecs:
            self.additional_args += ["-DENABLE_GPL_THIRD_PARTIES=YES"]
            self.additional_args += ["-DENABLE_NON_FREE_CODECS=YES"]
            self.additional_args += ["-DENABLE_AMRNB=YES"]
            self.additional_args += ["-DENABLE_AMRWB=YES"]
            self.additional_args += ["-DENABLE_G729=YES"]
            self.additional_args += ["-DENABLE_GSM=YES"]
            self.additional_args += ["-DENABLE_ILBC=YES"]
            self.additional_args += ["-DENABLE_ISAC=YES"]
            self.additional_args += ["-DENABLE_OPUS=YES"]
            self.additional_args += ["-DENABLE_SILK=YES"]
            self.additional_args += ["-DENABLE_SPEEX=YES"]
            self.additional_args += ["-DENABLE_FFMPEG=YES"]
            self.additional_args += ["-DENABLE_H263=YES"]
            self.additional_args += ["-DENABLE_H263P=YES"]
            self.additional_args += ["-DENABLE_MPEG4=YES"]
            self.additional_args += ["-DENABLE_OPENH264=YES"]
            self.additional_args += ["-DENABLE_VPX=YES"]

Ghislain MARY's avatar
Ghislain MARY committed
186 187
    def check_environment(self):
        ret = prepare.Preparator.check_environment(self)
188

189
        if "no-ui" in self.targets:
190
            return ret
191 192
        if platform.system() == 'Windows':
            ret |= not self.check_is_installed('mingw-get', 'MinGW (https://sourceforge.net/projects/mingw/files/Installer/)')
193 194
        if platform.system() == 'Windows':
            doxygen_prog = 'doxygen (http://www.stack.nl/~dimitri/doxygen/download.html)'
erwan's avatar
erwan committed
195
            graphviz_prog = 'graphviz (http://www.graphviz.org/download/)'
196 197 198 199 200 201
        else:
            doxygen_prog = 'doxygen'
            graphviz_prog = 'graphviz'
        ret |= not self.check_is_installed('doxygen', doxygen_prog)
        ret |= not self.check_is_installed('dot', graphviz_prog)
        ret |= not self.check_python_module_is_present('pystache')
202
        ret |= not self.check_python_module_is_present('six')
203
        if "python" in self.args.target or "python-raspberry" in self.args.target:
204
            ret |= not self.check_python_module_is_present('wheel')
205

206 207 208 209 210 211 212 213
        return ret

    def show_missing_dependencies(self):
        if self.missing_dependencies:
            error("The following binaries are missing: {}. Please install these packages:\n\t{}".format(
                " ".join(self.missing_dependencies.keys()),
                " ".join(self.missing_dependencies.values())))

214
    def clean(self):
215
        prepare.Preparator.clean(self)
216 217 218 219 220 221
        if os.path.isfile('Makefile'):
            os.remove('Makefile')
        if os.path.isdir('WORK') and not os.listdir('WORK'):
            os.rmdir('WORK')
        if os.path.isdir('OUTPUT') and not os.listdir('OUTPUT'):
            os.rmdir('OUTPUT')
222

223
    def generate_makefile(self, generator, project_file=''):
224 225 226 227 228 229 230
        targets = self.args.target
        targets_str = ""
        for target in targets:
            targets_str += """
{target}: {target}-build

{target}-build:
231
\t{generator} WORK/{target}/cmake/{project_file}
232
\t@echo "Done"
233
""".format(target=target, generator=generator, project_file=project_file)
234 235
        makefile = """
targets={targets}
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
236

237
.PHONY: all
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
238

239
all: build
240

241
build: $(addsuffix -build, $(targets))
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
242

243
{targets_str}
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
244 245 246

help-prepare-options:
\t@echo "prepare.py was previously executed with the following options:"
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
247
\t@echo "   ./prepare.py {options}"
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
248 249 250 251 252

help: help-prepare-options
\t@echo ""
\t@echo "(please read the README.md file first)"
\t@echo ""
253
\t@echo "Available targets: {targets}"
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
254
\t@echo ""
255
""".format(targets=' '.join(targets), targets_str=targets_str, options=' '.join(self.argv), generator=generator)
256 257 258
        f = open('Makefile', 'w')
        f.write(makefile)
        f.close()
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
259

260

Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
261

262 263 264
def main():
    preparator = DesktopPreparator()
    preparator.parse_args()
Ghislain MARY's avatar
Ghislain MARY committed
265 266
    if preparator.check_environment() != 0:
        preparator.show_environment_errors()
267 268
        return 1
    return preparator.run()
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
269 270 271

if __name__ == "__main__":
    sys.exit(main())