forked from symforce-org/symforce
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Makefile
183 lines (146 loc) · 6.82 KB
/
Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# Development utilities for SymForce
#
# This plays no part in the SymForce build process. For instructions on building SymForce (which is
# done with CMake), see the README. For documentation of these commands, see
# https://symforce.org/development.html.
BUILD_DIR=build
PYTHON ?= /usr/bin/env python3
CPP_FORMAT=clang-format
# -----------------------------------------------------------------------------
# Main
# -----------------------------------------------------------------------------
# Build documentation, run tests, measure coverage, show in browser
all: clean docs coverage coverage_open docs_open
FIND_CPP_FILES_TO_FORMAT=find . \
-not -path "*/lcmtypes/*" \
-and -not -path "./third_party/*" \
-and -not -path "./build/*" \
-and -not -path "./.eggs/*" \
-and -not -path "./symforce/benchmarks/matrix_multiplication/gen/*" \
-regextype posix-extended -regex ".*\.(h|cc|tcc)"
# Format using black, isort, and clang-format
BLACK_CMD=$(PYTHON) -m black . --exclude "third_party/.*|build/.*|\.eggs/.*"
ISORT_CMD=$(PYTHON) -m isort \
--skip-glob="**/third_party" \
--extend-skip-glob="**/build" \
--extend-skip-glob="**/.eggs" \
.
format:
$(BLACK_CMD)
$(ISORT_CMD)
$(FIND_CPP_FILES_TO_FORMAT) | xargs $(CPP_FORMAT) -i
# Check formatting using black and clang-format - print diff, do not modify files
check_format:
$(BLACK_CMD) --check --diff
$(ISORT_CMD) --check --diff
$(FIND_CPP_FILES_TO_FORMAT) | xargs $(CPP_FORMAT) --dry-run -Werror
# Check type hints using mypy
# NOTE(aaron): mypy does not recurse through directories unless they're packages, so we run `find`.
# See https://github.com/python/mypy/issues/8548
# We don't need to run find on `symforce` because we know the whole thing is a package
MYPY_COMMAND=$(PYTHON) -m mypy --show-error-code --config-file=pyproject.toml
SYMFORCE_LCMTYPES_DIR ?= build/lcmtypes/python2.7
check_types:
export SYMFORCE_LCMTYPES_DIR=$(SYMFORCE_LCMTYPES_DIR); \
$(MYPY_COMMAND) symforce $(shell find . \
\( -path ./symforce \
-o -path ./third_party \
-o -path ./build \
-o -path ./.eggs \
-o -path ./gen/python/setup.py \
-o -path ./test/symforce_function_codegen_test_data \
-o -path ./gen/python/build \
\) -prune -o -name "*.py" -print) \
--exclude "symforce/examples/.*/gen/python2\.7/lcmtypes"
$(MYPY_COMMAND) $(shell find test/symforce_function_codegen_test_data/sympy \
-path "*/lcmtypes" -prune -false \
-o -name "*.py")
$(MYPY_COMMAND) $(shell find test/symforce_function_codegen_test_data/symengine \
-path "*/lcmtypes" -prune -false \
-o -name "*.py")
# Run pylint on the symforce package, and tests
# TODO(aaron): Also run on other python code in symforce. Generated code will require a different
# config since it is py6 and contains a lot of duplicate code
pylint:
$(PYTHON) -m pylint symforce test/*.py
# Lint check for formatting and type hints
# This needs pass before any merge.
lint: check_types check_format pylint
# Clean all artifacts
clean: docs_clean coverage_clean
rm -rf $(BUILD_DIR)
.PHONY: all reqs format check_format check_types pylint lint clean
# -----------------------------------------------------------------------------
# Tests
# -----------------------------------------------------------------------------
# Generic target to run a SymEngine codegen test with --update
update_%:
SYMFORCE_SYMBOLIC_API=symengine $(PYTHON) test/$*.py --update
# All SymForce codegen tests, formatted as update_my_codegen_test targets
GEN_FILES_UPDATE_TARGETS=$(shell \
find test -name "*_codegen_test.py" \
| sed -r 's|test/([a-zA-Z0-9_]+).py|update_\1|g')
# Target to update all code generated by SymEngine codegen tests
test_update: $(GEN_FILES_UPDATE_TARGETS)
# Generic target to run a SymPy codegen test with --update --run_slow_tests
sympy_update_%:
SYMFORCE_SYMBOLIC_API=sympy $(PYTHON) test/$*.py --update --run_slow_tests
# All SymForce codegen tests, formatted as sympy_update_my_codegen_test targets
GEN_FILES_SYMPY_UPDATE_TARGETS=$(shell \
find test -name "*_codegen_test.py" \
| sed 's/test\/\(\w\+\).py/sympy_update_\1/g')
# Target to update all code generated by SymPy codegen tests
test_update_sympy: $(GEN_FILES_SYMPY_UPDATE_TARGETS)
# Target to regenerate all code
test_update_all: test_update test_update_sympy
.PHONY: update_% sympy_update_% test_update test_update_sympy test_update_all
# -----------------------------------------------------------------------------
# Test coverage
# -----------------------------------------------------------------------------
COVERAGE_DIR=$(BUILD_DIR)/coverage
coverage_clean:
rm -rf $(COVERAGE_DIR)
# NOTE(aaron): This is currently broken, since we can't run all our tests with `unittest discover`
coverage_run:
$(TEST_ENV) $(PYTHON) -m coverage run --source=symforce,gen \
-m unittest discover -s test/ -p *_test.py -v
coverage_html:
$(PYTHON) -m coverage html -d $(COVERAGE_DIR) && echo "Coverage report at $(COVERAGE_DIR)/index.html"
coverage: coverage_clean coverage_run coverage_html
coverage_open: coverage
open $(COVERAGE_DIR)/index.html
.PHONY: coverage_clean coverage_run coverage_html coverage coverage_open
# -----------------------------------------------------------------------------
# Documentation
# -----------------------------------------------------------------------------
DOCS_DIR=$(BUILD_DIR)/docs
docs_clean:
rm -rf $(DOCS_DIR) docs/api docs/api-cpp docs/api-gen-cpp docs/api-gen-py \
$(BUILD_DIR)/doxygen-cpp $(BUILD_DIR)/doxygen-gen-cpp
docs_dir:
mkdir -p $(BUILD_DIR)
docs_py_apidoc: docs_dir
sphinx-apidoc --separate --module-first -o docs/api ./symforce
sphinx-apidoc --separate --module-first -o docs/api-gen-py ./gen/python
# The generated symforce.cc_sym.rst file says to generate docs for symforce.cc_sym. However, that file
# only rexports cc_sym, and consequently the actual contents of cc_sym are not documented. We replace
# symforce.cc_sym.rst with a copy which is the same except it says to generate docs for cc_sym instead.
rm docs/api/symforce.cc_sym.rst
cp docs/symforce.cc_sym.rst docs/api/symforce.cc_sym.rst
# This is very slow, and breaks incremental builds. If iterating on the Python docs, you'll want to
# remove this from docs_html, and not run docs_clean. If
docs_cpp_apidoc: docs_dir
doxygen docs/Doxyfile-cpp
doxygen docs/Doxyfile-gen-cpp
$(PYTHON) -m breathe.apidoc -o docs/api-cpp --project api-cpp $(BUILD_DIR)/doxygen-cpp/xml
$(PYTHON) -m breathe.apidoc -o docs/api-gen-cpp --project api-gen-cpp $(BUILD_DIR)/doxygen-gen-cpp/xml
PY_EXTENSION_MODULE_PATH?=$(BUILD_DIR)/pybind
docs_html: docs_cpp_apidoc docs_py_apidoc
export PYTHONPATH=$(PY_EXTENSION_MODULE_PATH):$(PYTHONPATH); \
SYMFORCE_LOGLEVEL=WARNING $(PYTHON) -m sphinx -b html docs $(DOCS_DIR) -j auto
mkdir -p $(DOCS_DIR)/docs
ln -s -f ../_static $(DOCS_DIR)/docs/static
docs: docs_html
docs_open: docs
xdg-open $(DOCS_DIR)/index.html
.PHONY: docs_clean docs_dir docs_py_apidoc docs_cpp_apidoc docs_html docs docs_open