blob: a4dfb8f4c1441f3058fce2e3e96aedda9a8972bc [file] [log] [blame]
# Copyright 2018 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Recipe for building FFmpeg and uploading it and required source files."""
from PB.recipes.fuchsia.contrib.ffmpeg import InputProperties
DEPS = [
"fuchsia/artifacts",
"fuchsia/build",
"fuchsia/buildbucket_util",
"fuchsia/cas_util",
"fuchsia/checkout",
"fuchsia/cipd_util",
"recipe_engine/context",
"recipe_engine/file",
"recipe_engine/path",
"recipe_engine/properties",
"recipe_engine/step",
]
PROPERTIES = InputProperties
# Patterns of source code to include in the archive that this recipe produces.
# All relative to third_party/ffmpeg/src.
SRC_SOURCE_PATTERN = "lib*/*.h"
# Patterns of source code to include in the archive that this recipe produces.
# All relative to build/secondary/third_party/ffmpeg.
SECONDARY_SOURCE_PATTERN = "config/**/*"
def RunSteps(api, props):
checkout = api.checkout.fuchsia_with_options(
manifest=props.manifest,
remote=props.remote,
)
staging_dir = api.path.mkdtemp("ffmpeg")
pkg_dir = staging_dir.join("pkg")
debug_dir = staging_dir.join("debug")
prebuilt_variants = set()
# Build and archive for all targets before uploading any to avoid an
# incomplete upload.
for idx, build in enumerate(props.builds):
api.artifacts.gcs_bucket = props.artifact_gcs_bucket
with api.step.nest(f"{build.target}-{build.profile}"):
# Create a unique namespace per-build since we may build and upload
# more than once.
api.artifacts.namespace = f"{api.buildbucket_util.id}_{int(idx)}"
build_results = api.build.with_options(
checkout=checkout,
fint_params_path=build.fint_params_path,
artifact_gcs_bucket=props.artifact_gcs_bucket,
upload_namespace=api.artifacts.namespace,
)
if props.artifact_gcs_bucket:
build_results.upload_artifacts()
with api.context(infra_steps=True):
shared_build_dir = build_results.build_dir.join(
f"{build.target}-novariant-shared"
)
lib_dir = pkg_dir.join(build.profile, build.target, "lib")
api.file.ensure_directory("create lib dir", lib_dir)
api.file.copy(
"copy libffmpeg.so", shared_build_dir.join("libffmpeg.so"), lib_dir
)
build_id = api.file.read_text(
"read stamp file",
shared_build_dir.join("libffmpeg.so.build-id.stamp"),
test_data="f01cc36fed7d1a4f",
)
build_id_dir = debug_dir.join(build_id[:2])
api.file.ensure_directory("create debug dir", build_id_dir)
api.file.copy(
"copy libffmpeg.so (debug)",
shared_build_dir.join("lib.unstripped", "libffmpeg.so"),
build_id_dir.join(build_id[2:] + ".debug"),
)
for variant in build_results.set_metadata.variants:
prebuilt_variants.add(variant)
with api.step.nest(variant):
shared_variant_build_dir = build_results.build_dir.join(
f"{build.target}-{variant}-shared"
)
lib_variant_dir = lib_dir.join(variant)
api.file.ensure_directory("create lib dir", lib_variant_dir)
api.file.copy(
"copy libffmpeg.so",
shared_variant_build_dir.join("libffmpeg.so"),
lib_variant_dir,
)
build_id = api.file.read_text(
"read stamp file",
shared_variant_build_dir.join(
"libffmpeg.so.build-id.stamp"
),
test_data="f01cc36fed7d1a4f",
)
build_id_dir = debug_dir.join(build_id[:2])
api.file.ensure_directory("create debug dir", build_id_dir)
api.file.copy(
"copy libffmpeg.so (debug)",
shared_variant_build_dir.join(
"lib.unstripped", "libffmpeg.so"
),
build_id_dir.join(build_id[2:] + ".debug"),
)
ffmpeg_src_dir = checkout.root_dir.join("third_party", "ffmpeg", "src")
include_dir = pkg_dir.join("pkg", "ffmpeg", "include")
# Copy include files from third_party/ffmpeg/src (Chromium ffmpeg repo).
with api.step.nest("copy headers"):
paths = api.file.glob_paths(
"glob src paths",
ffmpeg_src_dir,
SRC_SOURCE_PATTERN,
test_data=["libavcodec/avcodec.h"],
)
# Avoid ensuring directories more than once. Step overhead is about 125ms,
# and some directories are ensured > 500 times.
ensured = set()
for srcpath in paths:
if api.path.isdir(srcpath): # pragma: no cover
continue
relpath = api.path.relpath(srcpath, ffmpeg_src_dir)
dstpath = include_dir.join(relpath)
dirname = api.path.dirname(dstpath)
if not dirname in ensured:
api.file.ensure_directory(f"ensure {dirname}", dirname)
ensured.add(dirname)
api.file.copy(f"copy {relpath}", srcpath, dstpath)
ffmpeg_secondary_dir = checkout.root_dir.join(
"build", "secondary", "third_party", "ffmpeg"
)
include_fuchsia_dir = pkg_dir.join("pkg", "ffmpeg", "include", "fuchsia")
# Copy include files from build/secondary/third_party/ffmpeg (Fuchsia ffmpeg repo).
# We copy to ffmpeg/include/fuchsia (rather than ffmpeg/include) to match the previous
# layout.
with api.step.nest("copy secondary headers"):
paths = api.file.glob_paths(
"glob src files",
ffmpeg_secondary_dir,
SECONDARY_SOURCE_PATTERN,
test_data=["config/default/x64/config.h"],
)
# Avoid ensuring directories more than once. Step overhead is about 125ms,
# and some directories are ensured > 500 times.
ensured = set()
for srcpath in paths:
if api.path.isdir(srcpath): # pragma: no cover
continue
relpath = api.path.relpath(srcpath, ffmpeg_secondary_dir)
dstpath = include_fuchsia_dir.join(relpath)
if not dirname in ensured:
dirname = api.path.dirname(dstpath)
api.file.ensure_directory(f"ensure {dirname}", dirname)
api.file.copy(f"copy {relpath}", srcpath, dstpath)
docs_dir = pkg_dir.join("pkg", "ffmpeg", "docs")
api.file.ensure_directory("create docs dir", docs_dir)
# Copy CREDITS.fuchsia and LICENSE.md from build/secondary/third_party/ffmpeg. If the Fuchsia
# ffmpeg repo moves to third_party/ffmpeg, this must be changed to third_party/ffmpeg.
api.file.copy(
"copy credits",
ffmpeg_secondary_dir.join("CREDITS.fuchsia"),
docs_dir.join("CREDITS.fuchsia"),
)
api.file.copy(
"copy license",
ffmpeg_secondary_dir.join("LICENSE.md"),
docs_dir.join("LICENSE.md"),
)
# Create prebuilt_variants.json that includes a list of prebuilt variants.
prebuilt_variants_dest = pkg_dir.join("prebuilt_variants.json")
api.file.write_json(
"create prebuilt_variants.json",
prebuilt_variants_dest,
{"prebuilt_variants": sorted(prebuilt_variants)},
)
# Upload files to CAS for debugging.
api.cas_util.upload(pkg_dir, step_name="archive pkg")
api.cas_util.upload(debug_dir, step_name="archive debug")
if api.buildbucket_util.is_dev_or_try:
return
with api.context(infra_steps=True):
project = checkout.project("integration")
# Upload files to CIPD.
api.cipd_util.upload_package(
"fuchsia/lib/ffmpeg/fuchsia",
pkg_dir,
search_tag={"git_revision": project["revision"]},
repository=project["remote"],
)
api.cipd_util.upload_package(
"fuchsia/lib/ffmpeg/fuchsia-debug-symbols",
debug_dir,
search_tag={"git_revision": project["revision"]},
repository=project["remote"],
)
def GenTests(api):
def properties():
return api.properties(
manifest="third_party/ffmpeg",
remote="https://fuchsia.googlesource.com/integration",
builds=[
{
"profile": "default",
"target": "arm64",
"fint_params_path": "fint_params/ffmpeg-arm64.textproto",
},
{
"profile": "max",
"target": "arm64",
"fint_params_path": "fint_params/ffmpeg-arm64.textproto",
},
{
"profile": "default",
"target": "x64",
"fint_params_path": "fint_params/ffmpeg-x64.textproto",
},
{
"profile": "max",
"target": "x64",
"fint_params_path": "fint_params/ffmpeg-x64.textproto",
},
],
artifact_gcs_bucket="fuchsia-artifacts",
)
yield (
api.buildbucket_util.test("default", repo="third_party/ffmpeg") + properties()
)
yield (
api.buildbucket_util.test("cq", tryjob=True, repo="third_party/ffmpeg")
+ properties()
)