Skip to content

Commit 97d8d27

Browse files
committed
[BE] Remind users to update submodule
Summary: As titled. This adds messages when we suspect the user forgot to update git submodule or cleanup the CMake cache. Test Plan: See the following error messages Reviewers: Subscribers: Tasks: Tags: ghstack-source-id: 14d8e65 Pull Request resolved: #8203
1 parent e63c923 commit 97d8d27

File tree

2 files changed

+146
-30
lines changed

2 files changed

+146
-30
lines changed

build/extract_sources.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import argparse
99
import copy
10+
import logging
1011
import os
1112
import re
1213

@@ -18,7 +19,7 @@
1819
try:
1920
import tomllib # Standard in 3.11 and later
2021
except ModuleNotFoundError:
21-
import tomli as tomllib
22+
import tomli as tomllib # type: ignore[no-redef]
2223

2324
"""Extracts source lists from the buck2 build system and writes them to a file.
2425
@@ -66,6 +67,12 @@
6667
]
6768
"""
6869

70+
# Set up logging
71+
logging.basicConfig(
72+
level=logging.INFO, format="%(asctime)s [ExecuTorch] %(levelname)s: %(message)s"
73+
)
74+
logger = logging.getLogger()
75+
6976

7077
class Target:
7178
"""Parsed [targets.*] entry from the TOML file.
@@ -118,7 +125,22 @@ def get_sources(
118125
)
119126

120127
# Get the complete list of source files that this target depends on.
121-
sources: set[str] = set(runner.run(["cquery", query] + buck_args))
128+
# If user doesn't setup their git submodules correctly, this will fail.
129+
# If we hit here, setup.py:check_submodule() should have already run
130+
# but it could be that the submodules are not synced or there's local changes.
131+
try:
132+
sources: set[str] = set(runner.run(["cquery", query] + buck_args))
133+
except RuntimeError as e:
134+
logger.error(
135+
f"\033[31;1mFailed to query buck for sources. Failed command:\n\n"
136+
f" buck2 cquery {query} {' '.join(buck_args)}\n\n"
137+
"This is likely due "
138+
"to missing git submodules or outdated CMake cache. "
139+
"Please run the following before retry:\033[0m\n\n"
140+
" \033[32;1m./install_executorch.sh --clean\033[0m\n"
141+
" \033[32;1mgit submodule update --init --recursive\033[0m\n"
142+
)
143+
raise e
122144

123145
# Keep entries that match all of the filters.
124146
filters = [re.compile(p) for p in self._config.get("filters", [])]

setup.py

Lines changed: 122 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@
5555
# Import this before distutils so that setuptools can intercept the distuils
5656
# imports.
5757
import setuptools # noqa: F401 # usort: skip
58+
import logging
59+
import subprocess
5860

5961
from distutils import log
6062
from distutils.sysconfig import get_python_lib
@@ -66,9 +68,93 @@
6668
from setuptools.command.build_ext import build_ext
6769
from setuptools.command.build_py import build_py
6870

71+
# Set up logging
72+
logging.basicConfig(
73+
level=logging.INFO, format="%(asctime)s [ExecuTorch] %(levelname)s: %(message)s"
74+
)
75+
logger = logging.getLogger()
76+
6977
# For information on setuptools Command subclassing see
7078
# https://setuptools.pypa.io/en/latest/userguide/extension.html
7179

80+
################################################################################
81+
# Git submodules
82+
################################################################################
83+
# The following submodules are required to be able to build ExecuTorch. If any of
84+
# these folders are missing or missing CMakeLists.txt, we will run
85+
# `git submodule update` to try to fix it. If the command fails, we will raise an
86+
# error.
87+
# An alternative to this would be to run `git submodule status` and run
88+
# `git submodule update` if there's any local changes. However this is a bit
89+
# too restrictive for users who modifies and tests the dependencies locally.
90+
91+
# keep sorted
92+
REQUIRED_SUBMODULES = [
93+
"ao",
94+
"cpuinfo",
95+
"eigen",
96+
"flatbuffers",
97+
"FP16",
98+
"FXdiv",
99+
"gflags",
100+
"prelude",
101+
"pthreadpool",
102+
"pybind11",
103+
"XNNPACK",
104+
]
105+
106+
107+
def get_required_submodule_paths():
108+
gitsubmodule_path = os.path.join(os.getcwd(), ".gitsubmodule")
109+
110+
if not os.path.isfile(gitsubmodule_path):
111+
print("Error: .gitsubmodule file not found.")
112+
exit(1)
113+
114+
with open(gitsubmodule_path, "r") as file:
115+
lines = file.readlines()
116+
117+
# Extract paths of required submodules
118+
required_paths = []
119+
for line in lines:
120+
if line.strip().startswith("path ="):
121+
path = line.split("=")[1].strip()
122+
if any(submodule in path for submodule in REQUIRED_SUBMODULES):
123+
required_paths.append(path)
124+
return required_paths
125+
126+
127+
def check_and_update_submodules():
128+
def check_folder(folder: str) -> bool:
129+
return os.path.isdir(folder) and os.path.isfile(
130+
os.path.join(folder, "CMakeLists.txt")
131+
)
132+
133+
# Check if the directories exist for each required submodule
134+
missing_submodules = []
135+
for path in get_required_submodule_paths():
136+
if not check_folder(path):
137+
missing_submodules.append(path)
138+
139+
# If any required submodule directories are missing, update them
140+
if missing_submodules:
141+
logger.warn("Some required submodules are missing. Updating submodules...")
142+
try:
143+
subprocess.check_call(
144+
["git", "submodule", "update", "--init", "--recursive"]
145+
)
146+
except subprocess.CalledProcessError as e:
147+
logger.error(f"Error updating submodules: {e}")
148+
exit(1)
149+
150+
# After updating submodules, check again
151+
for path in missing_submodules:
152+
if not check_folder(path):
153+
logger.error(f"Error: CMakeLists.txt not found in {path}.")
154+
logger.error("Please run `git submodule update --init --recursive`.")
155+
exit(1)
156+
logger.info("All required submodules are present and contain CMakeLists.txt.")
157+
72158

73159
class ShouldBuild:
74160
"""Indicates whether to build various components."""
@@ -720,31 +806,39 @@ def get_ext_modules() -> List[Extension]:
720806
return ext_modules
721807

722808

723-
setup(
724-
version=Version.string(),
725-
# TODO(dbort): Could use py_modules to restrict the set of modules we
726-
# package, and package_data to restrict the set up non-python files we
727-
# include. See also setuptools/discovery.py for custom finders.
728-
package_dir={
729-
"executorch/backends": "backends",
730-
"executorch/codegen": "codegen",
731-
# TODO(mnachin T180504136): Do not put examples/models
732-
# into core pip packages. Refactor out the necessary utils
733-
# or core models files into a separate package.
734-
"executorch/examples/models": "examples/models",
735-
"executorch/exir": "exir",
736-
"executorch/extension": "extension",
737-
"executorch/kernels/quantized": "kernels/quantized",
738-
"executorch/schema": "schema",
739-
"executorch/devtools": "devtools",
740-
"executorch/devtools/bundled_program": "devtools/bundled_program",
741-
"executorch/runtime": "runtime",
742-
"executorch/util": "util",
743-
},
744-
cmdclass={
745-
"build": CustomBuild,
746-
"build_ext": InstallerBuildExt,
747-
"build_py": CustomBuildPy,
748-
},
749-
ext_modules=get_ext_modules(),
750-
)
809+
def main():
810+
# Check submodules
811+
check_and_update_submodules()
812+
813+
setup(
814+
version=Version.string(),
815+
# TODO(dbort): Could use py_modules to restrict the set of modules we
816+
# package, and package_data to restrict the set up non-python files we
817+
# include. See also setuptools/discovery.py for custom finders.
818+
package_dir={
819+
"executorch/backends": "backends",
820+
"executorch/codegen": "codegen",
821+
# TODO(mnachin T180504136): Do not put examples/models
822+
# into core pip packages. Refactor out the necessary utils
823+
# or core models files into a separate package.
824+
"executorch/examples/models": "examples/models",
825+
"executorch/exir": "exir",
826+
"executorch/extension": "extension",
827+
"executorch/kernels/quantized": "kernels/quantized",
828+
"executorch/schema": "schema",
829+
"executorch/devtools": "devtools",
830+
"executorch/devtools/bundled_program": "devtools/bundled_program",
831+
"executorch/runtime": "runtime",
832+
"executorch/util": "util",
833+
},
834+
cmdclass={
835+
"build": CustomBuild,
836+
"build_ext": InstallerBuildExt,
837+
"build_py": CustomBuildPy,
838+
},
839+
ext_modules=get_ext_modules(),
840+
)
841+
842+
843+
if __name__ == "__main__":
844+
main()

0 commit comments

Comments
 (0)