summaryrefslogtreecommitdiff
path: root/scripts/build-config
blob: db870be754f0ffbb2dbfb4ce60776501ddfacb5e (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
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/env python3
#
# Copyright (C) 2018, VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# 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, see <http://www.gnu.org/licenses/>.
#
# File: build-config
# Purpose:
#  This script serves the same purpose as ./configure in traditional
#   autoconf setups.
#  It takes build configuration options from command line, checks them,
#  builds a config dictionary, augments it with some default and/or
#  computed values and saves it to build/build-config.json
#  for other build scripts to read.

import argparse
import re
import sys
import os
import getpass
import platform
import json

import defaults

# argparse converts hyphens to underscores,
# so for lookups in the original options hash we have to
# convert them back
def field_to_option(s):
    return re.sub(r'_', '-', s)

def get_default_build_by():
    return "{user}@{host}".format(user= getpass.getuser(), host=platform.node())

def get_validator(optdict, name):
    try:
        return optdict[name][2]
    except KeyError:
        return None


# Options dict format:
# '$option_name_without_leading_dashes': { ('$help_string', $default_value_generator_thunk, $value_checker_thunk) }
options = {
   'architecture': ('Image target architecture (amd64 or i386 or armhf)', lambda: 'amd64', lambda x: x in ['amd64', 'i386', 'armhf']),
   'build-by': ('Builder identifier (e.g. jrandomhacker@example.net)', get_default_build_by, None),
   'debian-mirror': ('Debian repository mirror for ISO build', lambda: defaults.DEBIAN_MIRROR, None),
   'debian-security-mirror': ('Debian security updated mirror', lambda: defaults.DEBIAN_SECURITY_MIRROR, None),
   'pbuilder-debian-mirror': ('Debian repository mirror for pbuilder env bootstrap', lambda: defaults.DEBIAN_MIRROR, None),
   'salt-mirror': ('Salt package mirror', lambda: defaults.SALT_MIRROR, None),
   'vyos-mirror': ('VyOS package mirror', lambda: defaults.VYOS_MIRROR, None),
   'build-type': ('Build type, release or development', lambda: 'development', lambda x: x in ['release', 'development']),
   'custom-packages': ('Custom packages to install from repositories', lambda: '', None),
   'version': ('Version number (release builds only)', None, None)
}

# Create the option parser
parser = argparse.ArgumentParser()
for k, v in options.items():
    help_string, default_value_thunk = v[0], v[1]
    if default_value_thunk is None:
        parser.add_argument('--' + k, type=str, help=help_string)
    else:
        parser.add_argument('--' + k, type=str, help=help_string, default=default_value_thunk())

# The debug option is a bit special since it's different type
parser.add_argument('--debug', help="Enable debug output", action='store_true')

# Custom APT entry and APT key options can be used multiple times
parser.add_argument('--custom-apt-entry', help="Custom APT entry", action='append')
parser.add_argument('--custom-apt-key', help="Custom APT key file", action='append')

args = vars(parser.parse_args())

# Validate options
for k, v in args.items():
    key = field_to_option(k)
    func = get_validator(options, k)
    if func is not None:
        if not func(v):
            print("{v} is not a valid value for --{o} option".format(o=key, v=v))
            sys.exit(1)

# Some fixup for mirror settings.
# The idea is: if --debian-mirror is specified but --pbuilder-debian-mirror is not,
# use the --debian-mirror value for both lb and pbuilder bootstrap
if (args['debian_mirror'] != defaults.DEBIAN_MIRROR) and \
   (args['pbuilder_debian_mirror'] == defaults.DEBIAN_MIRROR):
    args['pbuilder_debian_mirror'] = args['debian_mirror']

# Version can only be set for release builds,
# for dev builds it hardly makes any sense
if args['build_type'] == 'development':
    if args['version'] is not None:
        print("Version can only be set for release builds")
        print("Use --build-type=release option if you want to set version number")
        sys.exit(1)

# Populate some defaults that are not configurable,
# but that are handy to have in the options hash
args['distribution'] = defaults.DEBIAN_DISTRIBUTION
args['build_dir'] = os.path.join(os.getcwd(), defaults.BUILD_DIR)
args['pbuilder_config'] = defaults.PBUILDER_CONFIG
args['vyos_branch'] = defaults.VYOS_BRANCH

# Convert a whitespace-separated string of custom packages to a list
if args['custom_packages']:
    args['custom_packages'] = re.split(r'\s+', args['custom_packages'])
else:
    args['custom_packages'] = []


# Check the build environment and dependencies
env_check_retval = os.system("scripts/check-build-env")
if env_check_retval > 0:
    print("Build environment check failed, fix the issues and retry")

# Get the kernel version from data/kernel_version
with open("data/kernel_version") as f:
    kernel_version = f.read().strip()
    args['kernel_version'] = kernel_version


# Save to file
os.makedirs(defaults.BUILD_DIR, exist_ok=True)
print("Saving the build config to {0}".format(defaults.BUILD_CONFIG))
with open(defaults.BUILD_CONFIG, 'w') as f:
    json.dump(args, f, indent=4, sort_keys=True)
    print("\n", file=f)