• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2018 The Chromium Authors. All rights reserved.
2# Use of this source code is governed under the Apache License, Version 2.0
3# that can be found in the LICENSE file.
4"""Recipe for building GN."""
5
6from recipe_engine.recipe_api import Property
7
8DEPS = [
9    'recipe_engine/buildbucket',
10    'recipe_engine/cipd',
11    'recipe_engine/context',
12    'recipe_engine/file',
13    'recipe_engine/json',
14    'recipe_engine/path',
15    'recipe_engine/platform',
16    'recipe_engine/properties',
17    'recipe_engine/python',
18    'recipe_engine/raw_io',
19    'recipe_engine/step',
20    'macos_sdk',
21    'windows_sdk',
22]
23
24PROPERTIES = {
25    'repository': Property(kind=str, default='https://gn.googlesource.com/gn'),
26}
27
28
29def RunSteps(api, repository):
30  src_dir = api.path['start_dir'].join('gn')
31
32  with api.step.nest('git'), api.context(infra_steps=True):
33    api.step('init', ['git', 'init', src_dir])
34
35    with api.context(cwd=src_dir):
36      build_input = api.buildbucket.build_input
37      ref = (
38          build_input.gitiles_commit.id
39          if build_input.gitiles_commit else 'refs/heads/master')
40      # Fetch tags so `git describe` works.
41      api.step('fetch', ['git', 'fetch', '--tags', repository, ref])
42      api.step('checkout', ['git', 'checkout', 'FETCH_HEAD'])
43      for change in build_input.gerrit_changes:
44        api.step('fetch %s/%s' % (change.change, change.patchset), [
45            'git', 'fetch', repository,
46            'refs/changes/%s/%s/%s' %
47            (str(change.change)[-2:], change.change, change.patchset)
48        ])
49        api.step('cherry-pick %s/%s' % (change.change, change.patchset),
50                 ['git', 'cherry-pick', 'FETCH_HEAD'])
51
52  with api.context(infra_steps=True):
53    cipd_dir = api.path['start_dir'].join('cipd')
54    pkgs = api.cipd.EnsureFile()
55    pkgs.add_package('infra/ninja/${platform}', 'version:1.8.2')
56    if api.platform.is_linux or api.platform.is_mac:
57      pkgs.add_package('fuchsia/clang/${platform}',
58                       'git_revision:b920a7f65b13237dc4d5b2b836b29a954fff440a')
59    if api.platform.is_linux:
60      pkgs.add_package('fuchsia/sysroot/${platform}',
61                       'git_revision:a28dfa20af063e5ca00634024c85732e20220419',
62                       'sysroot')
63    api.cipd.ensure(cipd_dir, pkgs)
64
65  # The order is important since release build will get uploaded to CIPD.
66  configs = [
67      {
68          'name': 'debug',
69          'args': ['-d']
70      },
71      {
72          'name': 'release',
73          'args': ['--use-lto', '--use-icf']
74      },
75  ]
76
77  with api.macos_sdk(), api.windows_sdk():
78    if api.platform.is_linux:
79      sysroot = '--sysroot=%s' % cipd_dir.join('sysroot')
80      env = {
81          'CC': cipd_dir.join('bin', 'clang'),
82          'CXX': cipd_dir.join('bin', 'clang++'),
83          'AR': cipd_dir.join('bin', 'llvm-ar'),
84          'CFLAGS': sysroot,
85          'LDFLAGS': sysroot,
86      }
87    elif api.platform.is_mac:
88      sysroot = '--sysroot=%s' % api.step(
89          'xcrun', ['xcrun', '--show-sdk-path'],
90          stdout=api.raw_io.output(name='sdk-path', add_output_log=True),
91          step_test_data=
92          lambda: api.raw_io.test_api.stream_output('/some/xcode/path')
93      ).stdout.strip()
94      stdlib = '-nostdlib++ %s' % cipd_dir.join('lib', 'libc++.a')
95      env = {
96          'CC': cipd_dir.join('bin', 'clang'),
97          'CXX': cipd_dir.join('bin', 'clang++'),
98          'AR': cipd_dir.join('bin', 'llvm-ar'),
99          'CFLAGS': sysroot,
100          'LDFLAGS': '%s %s' % (sysroot, stdlib),
101      }
102    else:
103      env = {}
104
105    for config in configs:
106      with api.step.nest(config['name']):
107        with api.step.nest('build'), api.context(env=env, cwd=src_dir):
108          api.python(
109              'generate', src_dir.join('build', 'gen.py'), args=config['args'])
110
111          # Windows requires the environment modifications when building too.
112          api.step('ninja', [cipd_dir.join('ninja'), '-C', src_dir.join('out')])
113
114        api.step('test', [src_dir.join('out', 'gn_unittests')])
115
116  if build_input.gerrit_changes:
117    return
118
119  cipd_pkg_name = 'gn/gn/${platform}'
120  gn = 'gn' + ('.exe' if api.platform.is_win else '')
121
122  pkg_def = api.cipd.PackageDefinition(
123      package_name=cipd_pkg_name,
124      package_root=src_dir.join('out'),
125      install_mode='copy')
126  pkg_def.add_file(src_dir.join('out', gn))
127  pkg_def.add_version_file('.versions/%s.cipd_version' % gn)
128
129  cipd_pkg_file = api.path['cleanup'].join('gn.cipd')
130
131  api.cipd.build_from_pkg(
132      pkg_def=pkg_def,
133      output_package=cipd_pkg_file,
134  )
135
136  if api.buildbucket.builder_id.project == 'infra-internal':
137    with api.context(cwd=src_dir):
138      revision = api.step(
139          'rev-parse', ['git', 'rev-parse', 'HEAD'],
140          stdout=api.raw_io.output()).stdout.strip()
141
142    cipd_pin = api.cipd.search(cipd_pkg_name, 'git_revision:' + revision)
143    if cipd_pin:
144      api.step('Package is up-to-date', cmd=None)
145      return
146
147    api.cipd.register(
148        package_name=cipd_pkg_name,
149        package_path=cipd_pkg_file,
150        refs=['latest'],
151        tags={
152            'git_repository': repository,
153            'git_revision': revision,
154        },
155    )
156
157
158def GenTests(api):
159  for platform in ('linux', 'mac', 'win'):
160    yield (api.test('ci_' + platform) + api.platform.name(platform) +
161           api.buildbucket.ci_build(
162               project='gn',
163               git_repo='gn.googlesource.com/gn',
164           ))
165
166    yield (api.test('cq_' + platform) + api.platform.name(platform) +
167           api.buildbucket.try_build(
168               project='gn',
169               git_repo='gn.googlesource.com/gn',
170           ))
171
172  yield (api.test('cipd_exists') + api.buildbucket.ci_build(
173      project='infra-internal',
174      git_repo='gn.googlesource.com/gn',
175      revision='a' * 40,
176  ) + api.step_data('rev-parse', api.raw_io.stream_output('a' * 40)) +
177         api.step_data('cipd search gn/gn/${platform} git_revision:' + 'a' * 40,
178                       api.cipd.example_search('gn/gn/linux-amd64',
179                                               ['git_revision:' + 'a' * 40])))
180
181  yield (api.test('cipd_register') + api.buildbucket.ci_build(
182      project='infra-internal',
183      git_repo='gn.googlesource.com/gn',
184      revision='a' * 40,
185  ) + api.step_data('rev-parse', api.raw_io.stream_output('a' * 40)) +
186         api.step_data('cipd search gn/gn/${platform} git_revision:' + 'a' * 40,
187                       api.cipd.example_search('gn/gn/linux-amd64', [])))
188