aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/project/ci/appveyor/cmake.py
blob: 66e89f097398e1ac3811904e58cc3930c51e82b5 (plain) (blame)
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# Copyright (c) 2019 Egor Tensin <Egor.Tensin@gmail.com>
# This file is part of the "cmake-common" project.
# For details, see https://github.com/egor-tensin/cmake-common.
# Distributed under the MIT License.

R'''Build a CMake project on AppVeyor.

This is similar to build.py, but auto-fills some parameters for build.py from
the AppVeyor-defined environment variables.

The project is built in C:\Projects\build.
'''

import argparse
from enum import Enum
import logging
import os
import sys

from project.cmake.build import build
import project.utils


class Image(Enum):
    VS_2013 = 'Visual Studio 2013'
    VS_2015 = 'Visual Studio 2015'
    VS_2017 = 'Visual Studio 2017'
    VS_2019 = 'Visual Studio 2019'

    def __str__(self):
        return self.value


def _parse_image(s):
    try:
        return Image(s)
    except ValueError as e:
        raise ValueError(f'unsupported AppVeyor image: {s}') from e


class Generator(Enum):
    VS_2013 = 'Visual Studio 12 2013'
    VS_2015 = 'Visual Studio 14 2015'
    VS_2017 = 'Visual Studio 15 2017'
    VS_2019 = 'Visual Studio 16 2019'

    def __str__(self):
        return self.value

    @staticmethod
    def from_image(image):
        if image is Image.VS_2013:
            return Generator.VS_2013
        if image is Image.VS_2015:
            return Generator.VS_2015
        if image is Image.VS_2017:
            return Generator.VS_2017
        if image is Image.VS_2019:
            return Generator.VS_2019
        raise RuntimeError(f"don't know which generator to use for image: {image}")


class Platform(Enum):
    x86 = 'Win32'
    X64 = 'x64'

    def __str__(self):
        return self.value


def _parse_platform(s):
    try:
        return Platform(s)
    except ValueError as e:
        raise ValueError(f'unsupported AppVeyor platform: {s}') from e


def _env(name):
    if name not in os.environ:
        raise RuntimeError(f'undefined environment variable: {name}')
    return os.environ[name]


def _check_appveyor():
    if 'APPVEYOR' not in os.environ:
        raise RuntimeError('not running on AppVeyor')


def _get_src_dir():
    return _env('APPVEYOR_BUILD_FOLDER')


def _get_build_dir():
    return R'C:\Projects\build'


def _get_generator():
    image = _parse_image(_env('APPVEYOR_BUILD_WORKER_IMAGE'))
    return str(Generator.from_image(image))


def _get_platform():
    return str(_parse_platform(_env('PLATFORM')))


def _get_configuration():
    return _env('CONFIGURATION')


def _parse_args(argv=None):
    if argv is None:
        argv = sys.argv[1:]
    logging.info('Command line arguments: %s', argv)

    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)

    parser.add_argument('--install', metavar='DIR', dest='install_dir',
                        help='install directory')
    parser.add_argument('cmake_args', nargs='*', metavar='CMAKE_ARG', default=[],
                        help='additional CMake arguments, to be passed verbatim')
    return parser.parse_args(argv)


def build_appveyor(argv=None):
    args = _parse_args(argv)
    _check_appveyor()

    appveyor_argv = [
        '--build', _get_build_dir(),
        '--configuration', _get_configuration(),
    ]
    if args.install_dir is not None:
        appveyor_argv += [
            '--install', args.install_dir,
        ]
    appveyor_argv += [
        '--',
        _get_src_dir(),
        '-G', _get_generator(),
        '-A', _get_platform(),
    ]
    build(appveyor_argv + args.cmake_args)


def main(argv=None):
    with project.utils.setup_logging():
        build_appveyor(argv)


if __name__ == '__main__':
    main()