mirror of
https://github.com/facebook/proxygen.git
synced 2025-08-07 07:02:53 +03:00
fbcode_builder: getdeps: add testing concept
Summary: Adds a `test` subcommand that runs the tests for project. We're mostly interested in the 1st party facebook projects for this. The `sandcastle` flow will run the `test` subcommand just for the "leaf" project--the one named on the command line. Reviewed By: simpkins Differential Revision: D14710331 fbshipit-source-id: 7d04a46cfd723894d61018de2f230140b52285ac
This commit is contained in:
committed by
Facebook Github Bot
parent
7b7e3d8b06
commit
ec06ce8fa5
@@ -153,10 +153,9 @@ class BuildCmd(SubCmd):
|
|||||||
reconfigure = change_status.build_changed()
|
reconfigure = change_status.build_changed()
|
||||||
sources_changed = change_status.sources_changed()
|
sources_changed = change_status.sources_changed()
|
||||||
|
|
||||||
hash = fetcher.hash()
|
dirs = opts.compute_dirs(m, fetcher)
|
||||||
directory = "%s-%s" % (m.name, hash)
|
build_dir = dirs["build_dir"]
|
||||||
build_dir = os.path.join(opts.scratch_dir, "build", directory)
|
inst_dir = dirs["inst_dir"]
|
||||||
inst_dir = os.path.join(opts.scratch_dir, "installed", directory)
|
|
||||||
|
|
||||||
built_marker = os.path.join(inst_dir, ".built-by-getdeps")
|
built_marker = os.path.join(inst_dir, ".built-by-getdeps")
|
||||||
if os.path.exists(built_marker):
|
if os.path.exists(built_marker):
|
||||||
@@ -175,7 +174,7 @@ class BuildCmd(SubCmd):
|
|||||||
builder.build(install_dirs, reconfigure=reconfigure)
|
builder.build(install_dirs, reconfigure=reconfigure)
|
||||||
|
|
||||||
with open(built_marker, "w") as f:
|
with open(built_marker, "w") as f:
|
||||||
f.write(hash)
|
f.write(dirs["hash"])
|
||||||
|
|
||||||
install_dirs.append(inst_dir)
|
install_dirs.append(inst_dir)
|
||||||
|
|
||||||
@@ -198,6 +197,56 @@ class BuildCmd(SubCmd):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@cmd("test", "test a given project")
|
||||||
|
class TestCmd(SubCmd):
|
||||||
|
def run(self, args):
|
||||||
|
opts = setup_build_options(args)
|
||||||
|
manifest = load_project(opts, args.project)
|
||||||
|
|
||||||
|
ctx = context_from_host_tuple()
|
||||||
|
projects = manifests_in_dependency_order(opts, manifest, ctx)
|
||||||
|
|
||||||
|
# Accumulate the install directories so that the test steps
|
||||||
|
# can find their dep installation
|
||||||
|
install_dirs = []
|
||||||
|
|
||||||
|
for m in projects:
|
||||||
|
fetcher = m.create_fetcher(opts, ctx)
|
||||||
|
|
||||||
|
dirs = opts.compute_dirs(m, fetcher)
|
||||||
|
build_dir = dirs["build_dir"]
|
||||||
|
inst_dir = dirs["inst_dir"]
|
||||||
|
|
||||||
|
if m == manifest or args.test_all:
|
||||||
|
built_marker = os.path.join(inst_dir, ".built-by-getdeps")
|
||||||
|
if not os.path.exists(built_marker):
|
||||||
|
print("project %s has not been built" % m.name)
|
||||||
|
# TODO: we could just go ahead and build it here, but I
|
||||||
|
# want to tackle that as part of adding build-for-test
|
||||||
|
# support.
|
||||||
|
return 1
|
||||||
|
src_dir = fetcher.get_src_dir()
|
||||||
|
builder = m.create_builder(opts, src_dir, build_dir, inst_dir, ctx)
|
||||||
|
builder.run_tests(install_dirs)
|
||||||
|
|
||||||
|
install_dirs.append(inst_dir)
|
||||||
|
|
||||||
|
def setup_parser(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"project",
|
||||||
|
help=(
|
||||||
|
"name of the project or path to a manifest "
|
||||||
|
"file describing the project"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--test-all",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="Enable running tests for the named project and all of its deps",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def build_argparser():
|
def build_argparser():
|
||||||
common_args = argparse.ArgumentParser(add_help=False)
|
common_args = argparse.ArgumentParser(add_help=False)
|
||||||
common_args.add_argument(
|
common_args.add_argument(
|
||||||
|
@@ -83,6 +83,11 @@ class BuilderBase(object):
|
|||||||
|
|
||||||
self._build(install_dirs=install_dirs, reconfigure=reconfigure)
|
self._build(install_dirs=install_dirs, reconfigure=reconfigure)
|
||||||
|
|
||||||
|
def run_tests(self, install_dirs):
|
||||||
|
""" Execute any tests that we know how to run. If they fail,
|
||||||
|
raise an exception. """
|
||||||
|
pass
|
||||||
|
|
||||||
def _build(self, install_dirs, reconfigure):
|
def _build(self, install_dirs, reconfigure):
|
||||||
""" Perform the build.
|
""" Perform the build.
|
||||||
install_dirs contains the list of installation directories for
|
install_dirs contains the list of installation directories for
|
||||||
@@ -171,6 +176,43 @@ class CMakeBuilder(BuilderBase):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _compute_env(self, install_dirs):
|
||||||
|
# CMAKE_PREFIX_PATH is only respected when passed through the
|
||||||
|
# environment, so we construct an appropriate path to pass down
|
||||||
|
env = self.env.copy()
|
||||||
|
|
||||||
|
lib_path = None
|
||||||
|
if self.build_opts.is_darwin():
|
||||||
|
lib_path = "DYLD_LIBRARY_PATH"
|
||||||
|
elif self.build_opts.is_linux():
|
||||||
|
lib_path = "LD_LIBRARY_PATH"
|
||||||
|
else:
|
||||||
|
lib_path = None
|
||||||
|
|
||||||
|
for d in install_dirs:
|
||||||
|
add_path_entry(env, "CMAKE_PREFIX_PATH", d)
|
||||||
|
|
||||||
|
pkgconfig = os.path.join(d, "lib/pkgconfig")
|
||||||
|
if os.path.exists(pkgconfig):
|
||||||
|
add_path_entry(env, "PKG_CONFIG_PATH", pkgconfig)
|
||||||
|
|
||||||
|
# Allow resolving shared objects built earlier (eg: zstd
|
||||||
|
# doesn't include the full path to the dylib in its linkage
|
||||||
|
# so we need to give it an assist)
|
||||||
|
if lib_path:
|
||||||
|
for lib in ["lib", "lib64"]:
|
||||||
|
libdir = os.path.join(d, lib)
|
||||||
|
if os.path.exists(libdir):
|
||||||
|
add_path_entry(env, lib_path, libdir)
|
||||||
|
|
||||||
|
# Allow resolving binaries (eg: cmake, ninja) and dlls
|
||||||
|
# built by earlier steps
|
||||||
|
bindir = os.path.join(d, "bin")
|
||||||
|
if os.path.exists(bindir):
|
||||||
|
add_path_entry(env, "PATH", bindir, append=False)
|
||||||
|
|
||||||
|
return env
|
||||||
|
|
||||||
def _build(self, install_dirs, reconfigure):
|
def _build(self, install_dirs, reconfigure):
|
||||||
reconfigure = reconfigure or self._needs_reconfigure()
|
reconfigure = reconfigure or self._needs_reconfigure()
|
||||||
|
|
||||||
@@ -183,6 +225,24 @@ class CMakeBuilder(BuilderBase):
|
|||||||
# medium.
|
# medium.
|
||||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
|
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
|
||||||
}
|
}
|
||||||
|
env = self._compute_env(install_dirs)
|
||||||
|
if self.build_opts.is_darwin():
|
||||||
|
# Try to persuade cmake to set the rpath to match the lib
|
||||||
|
# dirs of the dependencies. This isn't automatic, and to
|
||||||
|
# make things more interesting, cmake uses `;` as the path
|
||||||
|
# separator, so translate the runtime path to something
|
||||||
|
# that cmake will parse
|
||||||
|
defines["CMAKE_INSTALL_RPATH"] = ";".join(
|
||||||
|
env.get("DYLD_LIBRARY_PATH", "").split(":")
|
||||||
|
)
|
||||||
|
# Tell cmake that we want to set the rpath in the tree
|
||||||
|
# at build time. Without this the rpath is only set
|
||||||
|
# at the moment that the binaries are installed. That
|
||||||
|
# default is problematic for example when using the
|
||||||
|
# gtest integration in cmake which runs the built test
|
||||||
|
# executables during the build to discover the set of
|
||||||
|
# tests.
|
||||||
|
defines["CMAKE_BUILD_WITH_INSTALL_RPATH"] = "ON"
|
||||||
|
|
||||||
defines.update(self.defines)
|
defines.update(self.defines)
|
||||||
define_args = ["-D%s=%s" % (k, v) for (k, v) in defines.items()]
|
define_args = ["-D%s=%s" % (k, v) for (k, v) in defines.items()]
|
||||||
@@ -191,16 +251,6 @@ class CMakeBuilder(BuilderBase):
|
|||||||
# define_args += ["-G", "Visual Studio 15 2017 Win64"]
|
# define_args += ["-G", "Visual Studio 15 2017 Win64"]
|
||||||
define_args += ["-G", "Ninja"]
|
define_args += ["-G", "Ninja"]
|
||||||
|
|
||||||
# CMAKE_PREFIX_PATH is only respected when passed through the
|
|
||||||
# environment, so we construct an appropriate path to pass down
|
|
||||||
env = self.env.copy()
|
|
||||||
for d in install_dirs:
|
|
||||||
add_path_entry(env, "CMAKE_PREFIX_PATH", d)
|
|
||||||
add_path_entry(env, "PKG_CONFIG_PATH", "%s/lib/pkgconfig" % d)
|
|
||||||
|
|
||||||
bindir = os.path.join(d, "bin")
|
|
||||||
add_path_entry(env, "PATH", bindir, append=False)
|
|
||||||
|
|
||||||
# Resolve the cmake that we installed
|
# Resolve the cmake that we installed
|
||||||
cmake = path_search(env, "cmake")
|
cmake = path_search(env, "cmake")
|
||||||
|
|
||||||
@@ -223,6 +273,13 @@ class CMakeBuilder(BuilderBase):
|
|||||||
env=env,
|
env=env,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def run_tests(self, install_dirs):
|
||||||
|
env = self._compute_env(install_dirs)
|
||||||
|
ctest = path_search(env, "ctest")
|
||||||
|
self._run_cmd(
|
||||||
|
[ctest, "--output-on-failure", "-j", str(self.build_opts.num_jobs)], env=env
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class NinjaBootstrap(BuilderBase):
|
class NinjaBootstrap(BuilderBase):
|
||||||
def __init__(self, build_opts, ctx, manifest, build_dir, src_dir, inst_dir):
|
def __init__(self, build_opts, ctx, manifest, build_dir, src_dir, inst_dir):
|
||||||
|
@@ -89,6 +89,14 @@ class BuildOptions(object):
|
|||||||
def is_linux(self):
|
def is_linux(self):
|
||||||
return self.host_type.is_linux()
|
return self.host_type.is_linux()
|
||||||
|
|
||||||
|
def compute_dirs(self, manifest, fetcher):
|
||||||
|
hash = fetcher.hash()
|
||||||
|
directory = "%s-%s" % (manifest.name, hash)
|
||||||
|
build_dir = os.path.join(self.scratch_dir, "build", directory)
|
||||||
|
inst_dir = os.path.join(self.scratch_dir, "installed", directory)
|
||||||
|
|
||||||
|
return {"build_dir": build_dir, "inst_dir": inst_dir, "hash": hash}
|
||||||
|
|
||||||
|
|
||||||
def list_win32_subst_letters():
|
def list_win32_subst_letters():
|
||||||
output = subprocess.check_output(["subst"]).decode("utf-8")
|
output = subprocess.check_output(["subst"]).decode("utf-8")
|
||||||
|
@@ -49,3 +49,4 @@ fbcode/folly = folly
|
|||||||
|
|
||||||
[cmake.defines]
|
[cmake.defines]
|
||||||
BUILD_SHARED_LIBS=OFF
|
BUILD_SHARED_LIBS=OFF
|
||||||
|
BUILD_TESTS=ON
|
||||||
|
@@ -12,7 +12,7 @@ builder = cmake
|
|||||||
subdir = wangle
|
subdir = wangle
|
||||||
|
|
||||||
[cmake.defines]
|
[cmake.defines]
|
||||||
BUILD_TESTS = OFF
|
BUILD_TESTS = ON
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
folly
|
folly
|
||||||
|
Reference in New Issue
Block a user