aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/mupgrade.py
blob: 7a97497397f43112060bc3ba39b6add15106f9e9 (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
# Copyright 2018 The Meson development team

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import sys, os
import json
import subprocess
import shlex
from .mesonlib import meson_command
from .compilers.compilers import compiler_envvars

dump_format_version = 1

def upgrade(state_file):
    d = json.load(open(state_file, 'r'))
    version = d.get('dump_format_version', 'missing')
    if version != dump_format_version:
        sys.exit('Can not upgrade because state dump file format is not compatible: %d != %d.' % (version, dump_format_version))
    state = d['state']
    env = os.environ.copy()
    for c in state['compilers']:
        ename = compiler_envvars[c[0]]
        eval = ' '.join([shlex.quote(x) for x in c[1]])
        env[ename] = eval
    cmd_args = [state['source_root'],
                state['build_root']]
    if 'cross_file' in state:
        cmd_args += ['--cross-file', state['cross_file']]
    for o in state['options']:
        cmd_args.append('-D%s=%s' % (o[0], o[1]))
    pc = subprocess.run(meson_command + cmd_args)
    if pc.returncode != 0:
        sys.exit(1) # The output from above should be enough to debug any issues.

def do_upgrade(potential_builddirs):
    for bd in potential_builddirs:
        state_file = os.path.join(bd, 'meson-private', 'upgrade-state.json')
        corefile = os.path.join(bd, 'meson-private', 'coredata.dat')
        corefile_bak = corefile + '~'
        if os.path.exists(state_file):
            was_success = False
            try:
                os.replace(corefile, corefile_bak)
                upgrade(state_file)
                was_success = True
            finally:
                if not was_success:
                    try:
                        os.replace(corefile_bak, corefile)
                    except Exception as e:
                        print('Could not restore original state: %s\nYou probably need to wipe the builddir' % str(e))
            return
    sys.exit('Could not find upgrade state file. Can not upgrade')

def build_opt_array(environment):
    options = []
    for optclass in environment.coredata.get_all_option_classes():
        for k, v in optclass.items():
            options.append((k, str(v.value)))
    return options

def build_compiler_array(build):
    result = []
    # Only native ones, cross compilers come from the cross file.
    for k, v in build.compilers.items():
        result.append((k, v.exelist))
    return result

def build_state_dict(environment, build):
    result = {}
    result['source_root'] = environment.get_source_dir()
    result['build_root'] = environment.get_build_dir()
    if environment.coredata.cross_file:
        result['cross_file'] = environment.coredata.cross_file
    result['options'] = build_opt_array(environment)
    result['compilers'] = build_compiler_array(build)
    return result

def create_dump_dict(environment, build):
    s = {}
    s['dump_format_version'] = dump_format_version
    s['state'] = build_state_dict(environment, build)
    return s