# Copyright (c) Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. .PHONY: all clean test LEVEL=.. include $(LEVEL)/Makefile.common LIBTOOLING=$(LEVEL)/libtooling ATDLIB=$(LEVEL)/libtooling/atdlib # see README for the required versions ATDGEN=atdgen ATDCAT=atdcat -i OCAMLOPT=ocamlfind ocamlopt -package unix,atdgen,atdgen-runtime,camlzip -I build -safe-string all: build/clang_ast_converter build/clang_ast_named_decl_printer # type definitions %_t.ml %_t.mli: %.atd $(ATDGEN) -t -o $* $< # yojson %_j.ml %_j.mli: %.atd $(ATDGEN) -j -o $* $< # biniou %_b.ml %_b.mli: %.atd $(ATDGEN) -b -o $* $< # validator %_v.ml %_v.mli: %.atd $(ATDGEN) -v -o $* $< # standard ocaml rules build/%.cmx:%.ml $(OCAMLOPT) -o $@ -c $< build/%.cmi:%.mli $(OCAMLOPT) -o $@ -c $< build/%.cmx:build/%.ml $(OCAMLOPT) -o $@ -c $< build/%.cmi:build/%.mli $(OCAMLOPT) -o $@ -c $< # clang AST build/ast_inline.atd.p: $(LIBTOOLING)/ASTExporter.h @mkdir -p build @$(MAKE) -C $(LIBTOOLING) build/ASTExporter.h.p $(ATDLIB)/extract_atd_from_cpp.py $(LIBTOOLING)/build/ASTExporter.h.p | $(ATDLIB)/normalize_names_in_atd.py > $@ build/ast_inline.atd: build/ast_inline.atd.p $(ATD_CPP) $< > $@ build/clang_ast.atd: build/ast_inline.atd # $(ATDCAT) returns 0 even if it fails - look at the output file to # determine whether it failed or not. Then remove the result file as # make misteriously doesn't do that by itself $(ATDCAT) $< > $@ && { [ -s $@ ] || { rm $@; exit 1; }; } build/ast_inline.atd.inc: build/ast_inline.atd.p cat $< | grep '^#' > $@ build/ast_inline.pat.inc: build/ast_inline.atd.inc cat $< | sed 's/*/,/g; s/ list/_list/g' > $@ build/clang_ast_proj.mli: clang_ast_proj.mli.p build/ast_inline.atd.inc cat $< | $(ATD_CPP) -include build/ast_inline.atd.inc > $@ build/clang_ast_proj.ml: clang_ast_proj.ml.p build/ast_inline.pat.inc $(OCAML_CPP) -I$(CLANG_PREFIX)/include $< -o - | $(ATDLIB)/normalize_names_in_atd.py | $(ATD_CPP) -include build/ast_inline.pat.inc > $@ # test files except for Objective-C TEST_FILES_COMMON=c_attributes.c bind_temporary.cpp \ c_cast.cpp const_cast.cpp dynamic_cast.cpp expr_with_cleanups.cpp inheritance.cpp \ lambda.cpp materialize_temporary.cpp namespace_decl.cpp new.cpp struct.cpp this.cpp \ unresolved_lookup.cpp using_directive.cpp class_template.cpp function_template.cpp \ type_trait.cpp no_except_expr.cpp friend.cpp TEST_FILES=$(TEST_FILES_COMMON) # only add Objective-C(++) files on mac ifeq ($(HAS_OBJC),yes) TEST_FILES+=Hello.m ObjCTest.m ObjCBridgeTransferTest.m objcpp_template_unboxing.mm endif PRINTER_TEST_FILES=$(TEST_FILES) CONVERTER_TEST_FILE=struct.cpp YOJSON_VALIDATOR_TEST_FILE=$(TEST_FILES) # simple library for composing unix processes build/process_test: build/process.cmx build/process_test.cmx $(OCAMLOPT) -linkpkg -o $@ $^ # Utilities build/utils_test: build/process.cmx build/utils.cmx build/utils_test.cmx $(OCAMLOPT) -linkpkg -o $@ $^ CLANG_AST_LIBS=$(patsubst %,build/%.cmx,clang_ast_types clang_ast_t clang_ast_j process utils yojson_utils) build/yojson_utils_test: $(CLANG_AST_LIBS) build/yojson_utils_test.cmx $(OCAMLOPT) -linkpkg -o $@ $^ build/clang_ast_proj_test: $(CLANG_AST_LIBS) build/clang_ast_proj.cmx build/clang_ast_proj_test.cmx $(OCAMLOPT) -linkpkg -o $@ $^ # AST format converter build/clang_ast_converter: $(CLANG_AST_LIBS) build/clang_ast_converter.cmx $(OCAMLOPT) -linkpkg -o $@ $^ CLANG_AST_PROJ_LIBS=$(patsubst %,build/%.cmx,clang_ast_types clang_ast_t clang_ast_j clang_ast_proj clang_ast_visit clang_ast_v clang_ast_main) # example of AST visitor build/clang_ast_named_decl_printer: $(CLANG_AST_PROJ_LIBS) build/clang_ast_named_decl_printer.cmx $(OCAMLOPT) -linkpkg -o $@ $^ build/clang_ast_main_test: $(CLANG_AST_PROJ_LIBS) build/clang_ast_main_test.cmx $(OCAMLOPT) -linkpkg -o $@ $^ test: $(patsubst %,build/%,process_test utils_test yojson_utils_test clang_ast_proj_test clang_ast_converter clang_ast_named_decl_printer clang_ast_main_test) @$(MAKE) -C $(LIBTOOLING) $(PRINTER_TEST_FILES:%=build/ast_samples/%.yjson) $(TEST_FILES:%=build/ast_samples/%.yjson.gz) $(CONVERTER_TEST_FILE:%=build/ast_samples/%.yjson) @export LIMIT=100; \ $(RUNTEST) tests/process_test build/process_test; \ $(RUNTEST) tests/utils_test build/utils_test; \ $(RUNTEST) tests/yojson_utils_test build/yojson_utils_test; \ $(RUNTEST) tests/clang_ast_proj_test build/clang_ast_proj_test; \ if [ "$(HAS_OBJC)" = "yes" ]; then \ $(RUNTEST) tests/clang_ast_named_decl_printer build/clang_ast_named_decl_printer $(PRINTER_TEST_FILES:%=$(LIBTOOLING)/build/ast_samples/%.yjson); \ else \ printf "[~] %s skipped (no Objective-C support)\n" clang_ast_named_decl_printer; \ fi; \ $(RUNTEST) tests/clang_ast_converter build/clang_ast_converter --pretty $(CONVERTER_TEST_FILE:%=$(LIBTOOLING)/build/ast_samples/%.yjson); \ $(RUNTEST) tests/clang_ast_yojson_validation ./yojson_validator.sh build/clang_ast_converter $(YOJSON_VALIDATOR_TEST_FILE:%=$(LIBTOOLING)/build/ast_samples/%.yjson.gz); \ if [ "$(HAS_OBJC)" = "yes" ]; then \ $(RUNTEST) tests/clang_ast_main_test build/clang_ast_main_test $(PRINTER_TEST_FILES:%=$(LIBTOOLING)/build/ast_samples/%.yjson); \ else \ printf "[~] %s skipped (no Objective-C support)\n" clang_ast_main_test; \ fi @if [ ! $$KEEP_TEST_OUTPUTS ]; then rm -f tests/*.out; fi record-test-outputs: @rm -f tests/*.out @$(MAKE) DEBUG=1 KEEP_TEST_OUTPUTS=1 test || true @for F in tests/*.out; do cp $$F $${F%.out}.exp; done @rm -f tests/*.out .PHONY: fmt fmt: ocamlformat -i $(wildcard *.ml) $(wildcard *.mli) -include .depend .depend: $(wildcard *.ml) $(wildcard *.mli) build/clang_ast_t.mli build/clang_ast_t.ml build/clang_ast_j.mli build/clang_ast_j.ml build/clang_ast_v.mli build/clang_ast_v.ml build/clang_ast_proj.mli build/clang_ast_proj.ml ocamldep -native -I build $^ | sed -e 's/\([a-zA-Z0-9_]*\.cm.\)/build\/\1/g' | sed -e 's/build\/build\//build\//g' > .depend clean: rm -rf tests/*.out build .depend