| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
- from __future__ import absolute_import
- from __future__ import division
- from __future__ import print_function
- from __future__ import unicode_literals
- try:
- from builtins import str
- except ImportError:
- from __builtin__ import str
- from targets_builder import TARGETSBuilder
- import json
- import os
- import fnmatch
- import sys
- from util import ColorString
- # This script generates TARGETS file for Buck.
- # Buck is a build tool specifying dependencies among different build targets.
- # User can pass extra dependencies as a JSON object via command line, and this
- # script can include these dependencies in the generate TARGETS file.
- # Usage:
- # $python buckifier/buckify_rocksdb.py
- # (This generates a TARGET file without user-specified dependency for unit
- # tests.)
- # $python buckifier/buckify_rocksdb.py \
- # '{"fake": { \
- # "extra_deps": [":test_dep", "//fakes/module:mock1"], \
- # "extra_compiler_flags": ["-DROCKSDB_LITE", "-Os"], \
- # } \
- # }'
- # (Generated TARGETS file has test_dep and mock1 as dependencies for RocksDB
- # unit tests, and will use the extra_compiler_flags to compile the unit test
- # source.)
- # tests to export as libraries for inclusion in other projects
- _EXPORTED_TEST_LIBS = ["env_basic_test"]
- # Parse src.mk files as a Dictionary of
- # VAR_NAME => list of files
- def parse_src_mk(repo_path):
- src_mk = repo_path + "/src.mk"
- src_files = {}
- for line in open(src_mk):
- line = line.strip()
- if len(line) == 0 or line[0] == '#':
- continue
- if '=' in line:
- current_src = line.split('=')[0].strip()
- src_files[current_src] = []
- elif '.cc' in line:
- src_path = line.split('.cc')[0].strip() + '.cc'
- src_files[current_src].append(src_path)
- return src_files
- # get all .cc / .c files
- def get_cc_files(repo_path):
- cc_files = []
- for root, dirnames, filenames in os.walk(repo_path): # noqa: B007 T25377293 Grandfathered in
- root = root[(len(repo_path) + 1):]
- if "java" in root:
- # Skip java
- continue
- for filename in fnmatch.filter(filenames, '*.cc'):
- cc_files.append(os.path.join(root, filename))
- for filename in fnmatch.filter(filenames, '*.c'):
- cc_files.append(os.path.join(root, filename))
- return cc_files
- # Get tests from Makefile
- def get_tests(repo_path):
- Makefile = repo_path + "/Makefile"
- # Dictionary TEST_NAME => IS_PARALLEL
- tests = {}
- found_tests = False
- for line in open(Makefile):
- line = line.strip()
- if line.startswith("TESTS ="):
- found_tests = True
- elif found_tests:
- if line.endswith("\\"):
- # remove the trailing \
- line = line[:-1]
- line = line.strip()
- tests[line] = False
- else:
- # we consumed all the tests
- break
- found_parallel_tests = False
- for line in open(Makefile):
- line = line.strip()
- if line.startswith("PARALLEL_TEST ="):
- found_parallel_tests = True
- elif found_parallel_tests:
- if line.endswith("\\"):
- # remove the trailing \
- line = line[:-1]
- line = line.strip()
- tests[line] = True
- else:
- # we consumed all the parallel tests
- break
- return tests
- # Parse extra dependencies passed by user from command line
- def get_dependencies():
- deps_map = {
- '': {
- 'extra_deps': [],
- 'extra_compiler_flags': []
- }
- }
- if len(sys.argv) < 2:
- return deps_map
- def encode_dict(data):
- rv = {}
- for k, v in data.items():
- if isinstance(v, dict):
- v = encode_dict(v)
- rv[k] = v
- return rv
- extra_deps = json.loads(sys.argv[1], object_hook=encode_dict)
- for target_alias, deps in extra_deps.items():
- deps_map[target_alias] = deps
- return deps_map
- # Prepare TARGETS file for buck
- def generate_targets(repo_path, deps_map):
- print(ColorString.info("Generating TARGETS"))
- # parsed src.mk file
- src_mk = parse_src_mk(repo_path)
- # get all .cc files
- cc_files = get_cc_files(repo_path)
- # get tests from Makefile
- tests = get_tests(repo_path)
- if src_mk is None or cc_files is None or tests is None:
- return False
- TARGETS = TARGETSBuilder("%s/TARGETS" % repo_path)
- # rocksdb_lib
- TARGETS.add_library(
- "rocksdb_lib",
- src_mk["LIB_SOURCES"] +
- src_mk["TOOL_LIB_SOURCES"])
- # rocksdb_test_lib
- TARGETS.add_library(
- "rocksdb_test_lib",
- src_mk.get("MOCK_LIB_SOURCES", []) +
- src_mk.get("TEST_LIB_SOURCES", []) +
- src_mk.get("EXP_LIB_SOURCES", []) +
- src_mk.get("ANALYZER_LIB_SOURCES", []),
- [":rocksdb_lib"])
- # rocksdb_tools_lib
- TARGETS.add_library(
- "rocksdb_tools_lib",
- src_mk.get("BENCH_LIB_SOURCES", []) +
- src_mk.get("ANALYZER_LIB_SOURCES", []) +
- ["test_util/testutil.cc"],
- [":rocksdb_lib"])
- # rocksdb_stress_lib
- TARGETS.add_library(
- "rocksdb_stress_lib",
- src_mk.get("ANALYZER_LIB_SOURCES", [])
- + src_mk.get('STRESS_LIB_SOURCES', [])
- + ["test_util/testutil.cc"],
- [":rocksdb_lib"])
- print("Extra dependencies:\n{0}".format(str(deps_map)))
- # test for every test we found in the Makefile
- for target_alias, deps in deps_map.items():
- for test in sorted(tests):
- match_src = [src for src in cc_files if ("/%s.c" % test) in src]
- if len(match_src) == 0:
- print(ColorString.warning("Cannot find .cc file for %s" % test))
- continue
- elif len(match_src) > 1:
- print(ColorString.warning("Found more than one .cc for %s" % test))
- print(match_src)
- continue
- assert(len(match_src) == 1)
- is_parallel = tests[test]
- test_target_name = \
- test if not target_alias else test + "_" + target_alias
- TARGETS.register_test(
- test_target_name,
- match_src[0],
- is_parallel,
- deps['extra_deps'],
- deps['extra_compiler_flags'])
- if test in _EXPORTED_TEST_LIBS:
- test_library = "%s_lib" % test_target_name
- TARGETS.add_library(test_library, match_src, [":rocksdb_test_lib"])
- TARGETS.flush_tests()
- print(ColorString.info("Generated TARGETS Summary:"))
- print(ColorString.info("- %d libs" % TARGETS.total_lib))
- print(ColorString.info("- %d binarys" % TARGETS.total_bin))
- print(ColorString.info("- %d tests" % TARGETS.total_test))
- return True
- def get_rocksdb_path():
- # rocksdb = {script_dir}/..
- script_dir = os.path.dirname(sys.argv[0])
- script_dir = os.path.abspath(script_dir)
- rocksdb_path = os.path.abspath(
- os.path.join(script_dir, "../"))
- return rocksdb_path
- def exit_with_error(msg):
- print(ColorString.error(msg))
- sys.exit(1)
- def main():
- deps_map = get_dependencies()
- # Generate TARGETS file for buck
- ok = generate_targets(get_rocksdb_path(), deps_map)
- if not ok:
- exit_with_error("Failed to generate TARGETS files")
- if __name__ == "__main__":
- main()
|