-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathsetup.py
executable file
·183 lines (151 loc) · 7.87 KB
/
setup.py
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
#!/usr/bin/env python3
import os
import platform
import sys
import re
import subprocess
import shutil
import argparse
class Config:
# Default values for Linux
CUDA_MIN_VER_MAJOR = 11
CUDA_MIN_VER_MINOR = 2
CUDA_MIN_VER_PATCH = 0
CMAKE_GENERATOR = "'Unix Makefiles'"
VCPKG_INSTALL_DIR = os.path.join("external", "vcpkg")
VCPKG_TAG = "2023.06.20"
VCPKG_EXEC = "vcpkg"
VCPKG_BOOTSTRAP = "bootstrap-vcpkg.sh"
VCPKG_PLATFORM_SPEC = ""
def __init__(self):
# Platform-dependent configuration
if inside_docker():
self.VCPKG_INSTALL_DIR = os.path.join("/rgldep", "vcpkg")
if on_windows():
self.CUDA_MIN_VER_MINOR = 4
self.CUDA_MIN_VER_PATCH = 152 # patch for CUDA 11.4 Update 4
self.CMAKE_GENERATOR = "Ninja"
self.VCPKG_EXEC = "vcpkg.exe"
self.VCPKG_BOOTSTRAP = "bootstrap-vcpkg.bat"
self.VCPKG_PLATFORM_SPEC = ":x64-windows"
def main():
cfg = Config()
# Parse arguments
parser = argparse.ArgumentParser(description="Helper script to build RGL.")
parser.add_argument("--build-dir", type=str, default="build",
help="Path to build directory. Default: 'build'")
parser.add_argument("--install-pcl-deps", action='store_true',
help="Install dependencies for PCL extension and exit")
parser.add_argument("--clean-build", action='store_true',
help="Remove build directory before cmake")
parser.add_argument("--with-pcl", action='store_true',
help="Build RGL with PCL extension")
parser.add_argument("--with-ros2", action='store_true',
help="Build RGL with ROS2 extension")
parser.add_argument("--with-ros2-standalone", action='store_true',
help="Build RGL with ROS2 extension in standalone mode")
parser.add_argument("--cmake", type=str, default="",
help="Pass arguments to cmake. Usage: --cmake=\"args...\"")
if on_linux():
parser.add_argument("--make", type=str, default=f"-j{os.cpu_count()}", dest="build_args",
help="Pass arguments to make. Usage: --make=\"args...\". Defaults to \"-j <cpu count>\"")
parser.add_argument("--lib-rpath", type=str, nargs='*',
help="Add run-time search path(s) for RGL library. $ORIGIN (actual library path) is added by default.")
if on_windows():
parser.add_argument("--ninja", type=str, default=f"-j{os.cpu_count()}", dest="build_args",
help="Pass arguments to ninja. Usage: --ninja=\"args...\". Defaults to \"-j <cpu count>\"")
args = parser.parse_args()
# Install dependencies for PCL extension
if args.install_pcl_deps:
# Clone vcpkg
if not os.path.isdir(cfg.VCPKG_INSTALL_DIR):
if on_linux() and not inside_docker(): # Inside docker already installed
print("Installing dependencies for vcpkg...")
run_system_command("sudo apt update")
run_system_command("sudo apt install git curl zip unzip tar freeglut3-dev libglew-dev libglfw3-dev")
run_subprocess_command(f"git clone -b {cfg.VCPKG_TAG} --single-branch --depth 1 https://github.com/microsoft/vcpkg {cfg.VCPKG_INSTALL_DIR}")
# Bootstrap vcpkg
if not os.path.isfile(os.path.join(cfg.VCPKG_INSTALL_DIR, cfg.VCPKG_EXEC)):
run_subprocess_command(f"{os.path.join(cfg.VCPKG_INSTALL_DIR, cfg.VCPKG_BOOTSTRAP)}")
# Install dependencies via vcpkg
run_subprocess_command(f"{os.path.join(cfg.VCPKG_INSTALL_DIR, cfg.VCPKG_EXEC)} install --clean-after-build pcl[core,visualization]{cfg.VCPKG_PLATFORM_SPEC}")
return 0
# Check CUDA
def is_cuda_version_ok():
nvcc_process = subprocess.run("nvcc --version", shell=True, stdout=subprocess.PIPE)
nvcc_ver_match = re.search("V[0-9]+.[0-9]+.[0-9]+", nvcc_process.stdout.decode("utf-8"))
if not nvcc_ver_match:
raise RuntimeError("CUDA not found")
major = int(nvcc_ver_match[0].split(".")[0][1:]) # [1:] to remove char 'v'
minor = int(nvcc_ver_match[0].split(".")[1])
patch = int(nvcc_ver_match[0].split(".")[2])
print(f"Found CUDA {major}.{minor}.{patch}")
for (actual, expected) in [(major, cfg.CUDA_MIN_VER_MAJOR), (minor, cfg.CUDA_MIN_VER_MINOR), (patch, cfg.CUDA_MIN_VER_PATCH)]:
if actual > expected:
return True
if actual < expected:
return False
return True
if not is_cuda_version_ok():
raise RuntimeError(f"CUDA version not supported! Get CUDA {cfg.CUDA_MIN_VER_MAJOR}.{cfg.CUDA_MIN_VER_MINOR}.{cfg.CUDA_MIN_VER_PATCH}+")
# Check OptiX_INSTALL_DIR
if os.environ["OptiX_INSTALL_DIR"] == "":
raise RuntimeError("OptiX not found! Make sure you have exported environment variable OptiX_INSTALL_DIR")
# Check extension requirements
if args.with_pcl and not os.path.isdir(cfg.VCPKG_INSTALL_DIR):
raise RuntimeError("PCL extension requires dependencies to be installed: run this script with --install-pcl-deps flag")
# Go to script directory
os.chdir(sys.path[0])
# Prepare build directory
if args.clean_build and os.path.isdir(args.build_dir):
shutil.rmtree(args.build_dir, ignore_errors=True)
if not os.path.isdir(args.build_dir):
os.makedirs(args.build_dir)
# Extend Path with libRobotecGPULidar location to link tests properly during the build on Windows
if on_windows():
os.environ["Path"] = os.environ["Path"] + ";" + os.path.join(os.getcwd(), args.build_dir)
# Build
cmake_args = [
f"-DCMAKE_TOOLCHAIN_FILE={os.path.join(cfg.VCPKG_INSTALL_DIR, 'scripts', 'buildsystems', 'vcpkg.cmake') if args.with_pcl else ''}",
f"-DRGL_BUILD_PCL_EXTENSION={'ON' if args.with_pcl else 'OFF'}",
f"-DRGL_BUILD_ROS2_EXTENSION={'ON' if args.with_ros2 else 'OFF'}",
f"-DRGL_BUILD_ROS2_EXTENSION_STANDALONE={'ON' if args.with_ros2_standalone else 'OFF'}"
]
if on_linux():
# Set rpaths
linker_rpath_flags = ["-Wl,-rpath=\\$ORIGIN"] # add directory in which an RGL library is located
if args.lib_rpath is not None:
for rpath in args.lib_rpath:
rpath = rpath.replace("$ORIGIN", "\\$ORIGIN") # cmake should not treat this as variable
linker_rpath_flags.append(f"-Wl,-rpath={rpath}")
cmake_args.append(f"-DCMAKE_SHARED_LINKER_FLAGS=\"{' '.join(linker_rpath_flags)}\"")
cmake_args.append(f"-DCMAKE_INSTALL_PREFIX={os.path.join(os.getcwd(), args.build_dir)}")
# Append user args, possibly overwriting
cmake_args.append(args.cmake)
cmake_args = " ".join(cmake_args)
run_subprocess_command(f"cmake -B {args.build_dir} -G {cfg.CMAKE_GENERATOR} {cmake_args}")
run_subprocess_command(f"cmake --build {args.build_dir} -- {args.build_args}")
if args.with_ros2_standalone:
run_subprocess_command(f"cmake --install {args.build_dir}")
def on_linux():
return platform.system() == "Linux"
def on_windows():
return platform.system() == "Windows"
def inside_docker():
path = "/proc/self/cgroup"
return (
os.path.exists("/.dockerenv") or
os.path.isfile(path) and any("docker" in line for line in open(path))
)
def run_subprocess_command(command: str, shell=True, stderr=sys.stderr, stdout=sys.stdout):
print(f"Executing command: '{command}'")
process = subprocess.Popen(command, shell=shell, stderr=stderr, stdout=stdout)
process.wait()
if process.returncode != 0:
raise RuntimeError(f"Failed to execute command: '{command}'")
def run_system_command(command: str):
print(f"Executing command: '{command}'")
if os.system(command) != 0:
raise RuntimeError(f"Failed to execute command: '{command}'")
if __name__ == "__main__":
sys.exit(main())