carla/Configure.py

1204 lines
38 KiB
Python
Raw Normal View History

2023-10-28 07:21:01 +08:00
from concurrent.futures import ProcessPoolExecutor, as_completed
from pathlib import Path
2023-11-24 07:10:37 +08:00
import subprocess, tarfile, zipfile, argparse, requests, psutil, shutil, glob, json, sys, os
2023-11-15 03:48:24 +08:00
2023-11-23 07:50:55 +08:00
# Constants:
2023-11-24 07:10:37 +08:00
EXE_EXT = '.exe' if os.name == 'nt' else ''
LIB_PREFIX = '' if os.name == 'nt' else 'lib'
2023-11-24 07:10:37 +08:00
LIB_EXT = '.lib' if os.name == 'nt' else '.a'
OBJ_EXT = '.obj' if os.name == 'nt' else '.o'
SHELL_EXT = '.bat' if os.name == 'nt' else ''
2023-11-18 06:18:00 +08:00
WORKSPACE_PATH = Path(__file__).parent.resolve()
2023-11-23 14:15:14 +08:00
LIBCARLA_PATH = WORKSPACE_PATH / 'LibCarla'
LIBCARLA_SOURCE_PATH = LIBCARLA_PATH / 'source'
2023-11-23 07:50:55 +08:00
PYTHON_API_PATH = WORKSPACE_PATH / 'PythonAPI' / 'carla'
2023-11-18 06:18:00 +08:00
EXAMPLES_PATH = WORKSPACE_PATH / 'Examples'
UTIL_PATH = WORKSPACE_PATH / 'Util'
DOCKER_UTILS_PATH = UTIL_PATH / 'DockerUtils'
2023-11-23 07:50:55 +08:00
PATCHES_PATH = UTIL_PATH / 'Patches'
2023-11-18 06:18:00 +08:00
CARLA_UE_PATH = WORKSPACE_PATH / 'Unreal' / 'CarlaUE4'
CARLA_UE_PLUGIN_ROOT_PATH = CARLA_UE_PATH / 'Plugins'
CARLA_UE_PLUGIN_PATH = CARLA_UE_PLUGIN_ROOT_PATH / 'Carla'
CARLA_UE_PLUGIN_DEPENDENCIES_PATH = CARLA_UE_PLUGIN_ROOT_PATH / 'CarlaDependencies'
2023-11-23 07:50:55 +08:00
CARLA_UE_CONTENT_PATH = CARLA_UE_PATH / 'Content'
CARLA_UE_CONTENT_CARLA_PATH = CARLA_UE_CONTENT_PATH / 'Carla'
CARLA_UE_CONTENT_VERSIONS_FILE_PATH = WORKSPACE_PATH / 'Util' / 'ContentVersions.json'
2023-12-01 00:43:27 +08:00
FALLBACK_CARLA_VERSION_STRING = '0.9.15'
2023-11-23 07:50:55 +08:00
LOGICAL_PROCESSOR_COUNT = psutil.cpu_count(logical = True)
DEFAULT_PARALLELISM = LOGICAL_PROCESSOR_COUNT + (2 if LOGICAL_PROCESSOR_COUNT >= 8 else 0)
READTHEDOCS_URL_SUFFIX = 'how_to_build_on_windows/\n' if os.name == "nt" else 'build_linux/\n'
DEFAULT_ERROR_MESSAGE = (
'\n'
'Ok, an error ocurred, don\'t panic!\n'
'We have different platforms where you can find some help:\n'
'\n'
'- Make sure you have read the documentation:\n'
f' https://carla.readthedocs.io/en/latest/{READTHEDOCS_URL_SUFFIX}'
'\n'
'- If the problem persists, submit an issue on our GitHub page:\n'
' https://github.com/carla-simulator/carla/issues\n'
'\n'
'- Or just use our Discord server!\n'
' We\'ll be glad to help you there:\n'
' https://discord.gg/42KJdRj\n'
)
def FindExecutable(candidates : list):
for e in candidates:
ec = subprocess.call(
[ 'where' if os.name == 'nt' else 'whereis', e ],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
shell = True)
if ec == 0:
return e
return None
DEFAULT_C_COMPILER = FindExecutable([
2023-11-24 07:10:37 +08:00
'cl',
2023-11-23 07:50:55 +08:00
'clang-cl',
] if os.name == 'nt' else [
'clang',
2023-11-24 07:10:37 +08:00
'gcc',
2023-11-23 07:50:55 +08:00
])
DEFAULT_CPP_COMPILER = FindExecutable([
2023-11-24 07:10:37 +08:00
'cl',
2023-11-23 07:50:55 +08:00
'clang-cl',
] if os.name == 'nt' else [
'clang++',
2023-11-24 07:10:37 +08:00
'g++',
2023-11-23 07:50:55 +08:00
])
DEFAULT_LINKER = FindExecutable([
2023-11-24 07:10:37 +08:00
'link',
2023-11-23 07:50:55 +08:00
'llvm-link',
] if os.name == 'nt' else [
'lld',
2023-11-24 07:10:37 +08:00
'ld',
2023-11-23 07:50:55 +08:00
])
DEFAULT_LIB = FindExecutable([
'lib',
2023-11-24 07:10:37 +08:00
'llvm-lib',
2023-11-23 07:50:55 +08:00
'llvm-ar'
] if os.name == 'nt' else [
'llvm-ar',
2023-11-24 07:10:37 +08:00
'ar',
2023-11-23 07:50:55 +08:00
])
DEFAULT_C_STANDARD = 11
2023-12-01 00:43:27 +08:00
DEFAULT_CPP_STANDARD = 20
2023-11-23 07:50:55 +08:00
argp = argparse.ArgumentParser(description = __doc__)
2023-12-20 18:28:14 +08:00
def AddCLIFlag(name : str, help : str):
2023-11-23 07:50:55 +08:00
argp.add_argument(f'--{name}', action = 'store_true', help = help)
2023-12-20 18:28:14 +08:00
def AddCLIStringOption(name : str, default : str, help : str):
2023-11-24 07:10:37 +08:00
argp.add_argument(f'--{name}', type = str, default = str(default), help = f'{help} (default = "{default}").')
2023-12-20 18:28:14 +08:00
def ADDCLIIntOption(name : str, default : int, help : str):
2023-11-24 07:10:37 +08:00
argp.add_argument(f'--{name}', type = int, default = int(default), help = f'{help} (default = {default}).')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'launch',
2023-11-24 14:52:40 +08:00
'Build and open the CarlaUE4 project in the Unreal Engine editor.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'launch-only',
2023-11-24 14:52:40 +08:00
'Open the CARLA project in the Unreal Engine editor, skipping all build steps.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'import',
f'Import maps and assets from "{WORKSPACE_PATH / "Import"}" into Unreal.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'package',
'Build a packaged version of CARLA ready for distribution.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'docs',
'Build the CARLA documentation, through Doxygen.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'clean',
'Delete all build files.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'rebuild',
'Delete all build files and recompiles.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'check-libcarla',
'Run unit the test suites for LibCarla')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'check-python-api',
'Run unit the test suites for PythonAPI')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'check',
'Run unit the test suites for LibCarla and PythonAPI')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'carla-ue',
'Build the CARLA Unreal Engine plugin and project.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'python-api',
'Build the CARLA Python API.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'libcarla-client',
'Build the LibCarla Client module.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'libcarla-server',
'Build the LibCarla Server module.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-24 07:10:37 +08:00
'update-deps',
2023-11-23 07:50:55 +08:00
'Download all project dependencies.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-24 07:10:37 +08:00
'build-deps',
2023-11-23 07:50:55 +08:00
'Build all project dependencies.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'configure-sequential',
'Whether to disable parallelism in the configuration script.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-24 14:52:40 +08:00
'no-log',
'Whether to disable saving logs.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'pytorch',
'Whether to enable PyTorch.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'chrono',
'Whether to enable Chrono.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
'carsim',
'Whether to enable CarSim')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
'ros2',
'Whether to enable ROS2')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
'unity-build',
'Whether to enable Unity Build for Unreal Engine projects.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'osm2odr',
'Whether to enable OSM2ODR.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'osm-world-renderer',
'Whether to enable OSM World Renderer.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'nv-omniverse',
'Whether to enable the NVIDIA Omniverse Plugin.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'march-native',
2023-11-24 14:52:40 +08:00
'Whether to add "-march=native" to C/C++ compile flags.')
2023-12-20 18:28:14 +08:00
AddCLIFlag(
2023-11-23 07:50:55 +08:00
'rss',
'Whether to enable RSS.')
2023-12-20 18:28:14 +08:00
ADDCLIIntOption(
2023-11-23 07:50:55 +08:00
'parallelism',
DEFAULT_PARALLELISM,
'Set the configure/build parallelism.')
2023-12-20 18:28:14 +08:00
ADDCLIIntOption(
2023-11-23 07:50:55 +08:00
'c-standard',
DEFAULT_C_STANDARD,
2023-11-23 07:50:55 +08:00
'Set the target C standard.')
2023-12-20 18:28:14 +08:00
ADDCLIIntOption(
2023-11-23 07:50:55 +08:00
'cpp-standard',
DEFAULT_CPP_STANDARD,
2023-11-23 07:50:55 +08:00
'Set the target C++ standard.')
2023-12-20 18:28:14 +08:00
AddCLIStringOption(
2023-11-23 07:50:55 +08:00
'c-compiler',
DEFAULT_C_COMPILER,
'Set the target C compiler.')
2023-12-20 18:28:14 +08:00
AddCLIStringOption(
2023-11-23 07:50:55 +08:00
'cpp-compiler',
DEFAULT_CPP_COMPILER,
'Set the target C++ compiler.')
2023-12-20 18:28:14 +08:00
AddCLIStringOption(
2023-11-23 07:50:55 +08:00
'linker',
DEFAULT_LINKER,
'Set the target linker.')
2023-12-20 18:28:14 +08:00
AddCLIStringOption(
2023-11-23 07:50:55 +08:00
'ar',
DEFAULT_LIB,
'Set the target ar/lib tool.')
2023-12-20 18:28:14 +08:00
AddCLIStringOption(
2023-11-23 07:50:55 +08:00
'version',
FALLBACK_CARLA_VERSION_STRING,
2023-11-24 14:52:40 +08:00
'Override the CARLA version.')
2023-12-20 18:28:14 +08:00
AddCLIStringOption(
2023-11-23 07:50:55 +08:00
'generator',
'Ninja',
'Set the CMake generator.')
2023-12-20 18:28:14 +08:00
AddCLIStringOption(
2023-11-23 07:50:55 +08:00
'build-path',
WORKSPACE_PATH / 'Build',
'Set the CARLA build path.')
2023-12-20 18:28:14 +08:00
AddCLIStringOption(
'boost-toolset',
'msvc-14.3',
'Set the target boost toolset.')
AddCLIStringOption(
2023-11-23 07:50:55 +08:00
'ue-path',
os.getenv(
'UNREAL_ENGINE_PATH',
'<Could not automatically infer Unreal Engine source path using the "UNREAL_ENGINE_PATH" environment variable>'),
'Set the path of Unreal Engine.')
2023-11-24 14:52:40 +08:00
ARGS_SYNC_PATH = WORKSPACE_PATH / 'ArgsSync.json'
2023-11-24 07:10:37 +08:00
def SyncArgs():
argv = argparse.Namespace()
if __name__ == '__main__':
argv = argp.parse_args()
2023-11-24 14:52:40 +08:00
with open(ARGS_SYNC_PATH, 'w') as file:
2023-11-24 07:10:37 +08:00
json.dump(argv.__dict__, file)
else:
2023-11-24 14:52:40 +08:00
with open(ARGS_SYNC_PATH, 'r') as file:
2023-11-24 07:10:37 +08:00
argv.__dict__ = json.load(file)
return argv
ARGV = SyncArgs()
2023-12-01 00:43:27 +08:00
2023-11-24 14:52:40 +08:00
SEQUENTIAL = ARGV.configure_sequential
2023-11-24 02:06:48 +08:00
ENABLE_OSM2ODR = ARGV.osm2odr or ARGV.python_api
ENABLE_OSM_WORLD_RENDERER = ARGV.osm_world_renderer
ENABLE_CARLA_UE = ARGV.carla_ue
2023-11-24 07:10:37 +08:00
ENABLE_PYTHON_API = ARGV.python_api
ENABLE_LIBCARLA_CLIENT = ARGV.libcarla_client
ENABLE_LIBCARLA_SERVER = ARGV.libcarla_server
ENABLE_LIBCARLA = any([
ENABLE_CARLA_UE,
ENABLE_PYTHON_API,
ENABLE_LIBCARLA_CLIENT,
ENABLE_LIBCARLA_SERVER,
])
ENABLE_CARSIM = ARGV.carsim
ENABLE_CHRONO = ARGV.chrono
ENABLE_ROS2 = ARGV.ros2
ENABLE_UNITY_BUILD = ARGV.unity_build
2023-11-24 02:06:48 +08:00
ENABLE_NVIDIA_OMNIVERSE = ARGV.nv_omniverse
ENABLE_RSS = ARGV.rss
2023-11-24 14:52:40 +08:00
UPDATE_DEPENDENCIES = ARGV.update_deps
BUILD_DEPENDENCIES = ARGV.build_deps
2023-11-24 07:10:37 +08:00
PARALLELISM = ARGV.parallelism
2023-11-23 07:50:55 +08:00
# Root paths:
CARLA_VERSION_STRING = ARGV.version
2023-11-24 02:06:48 +08:00
BUILD_PATH = Path(ARGV.build_path)
2023-11-23 07:50:55 +08:00
LOG_PATH = BUILD_PATH / 'BuildLogs'
DEPENDENCIES_PATH = BUILD_PATH / 'Dependencies'
LIBCARLA_BUILD_PATH = BUILD_PATH / 'LibCarla'
LIBCARLA_INSTALL_PATH = WORKSPACE_PATH / 'Install' / 'LibCarla'
2023-11-23 07:50:55 +08:00
# Language options
C_COMPILER = ARGV.c_compiler
CPP_COMPILER = ARGV.cpp_compiler
LINKER = ARGV.linker
LIB = ARGV.ar
C_STANDARD = ARGV.c_standard
CPP_STANDARD = ARGV.cpp_standard
2023-11-24 07:10:37 +08:00
C_COMPILER_CLI_TYPE = 'msvc' if 'cl' in C_COMPILER else 'gnu'
CPP_COMPILER_CLI_TYPE = 'msvc' if 'cl' in CPP_COMPILER else 'gnu'
2023-11-24 14:52:40 +08:00
C_COMPILER_IS_CLANG = 'clang' in C_COMPILER
CPP_COMPILER_IS_CLANG = 'clang' in CPP_COMPILER
C_ENABLE_MARCH_NATIVE = ARGV.march_native and C_COMPILER_CLI_TYPE == 'gnu'
CPP_ENABLE_MARCH_NATIVE = ARGV.march_native and CPP_COMPILER_CLI_TYPE == 'gnu'
LIB_IS_AR = 'ar' in LIB
2023-11-18 06:18:00 +08:00
# Unreal Engine
2023-11-23 07:50:55 +08:00
UNREAL_ENGINE_PATH = Path(ARGV.ue_path)
# Dependencies:
# Boost
BOOST_VERSION = (1, 83, 0)
BOOST_VERSION_MAJOR, BOOST_VERSION_MINOR, BOOST_VERSION_PATCH = BOOST_VERSION
BOOST_VERSION_STRING = f'{BOOST_VERSION_MAJOR}.{BOOST_VERSION_MINOR}.{BOOST_VERSION_PATCH}'
2023-12-20 18:28:14 +08:00
BOOST_TOOLSET = ARGV.boost_toolset
2023-11-23 07:50:55 +08:00
BOOST_SOURCE_PATH = DEPENDENCIES_PATH / 'boost-source'
BOOST_BUILD_PATH = DEPENDENCIES_PATH / 'boost-build'
BOOST_INSTALL_PATH = DEPENDENCIES_PATH / 'boost-install'
2023-12-01 22:21:12 +08:00
BOOST_INCLUDE_PATH = BOOST_INSTALL_PATH / 'include'
2023-11-23 07:50:55 +08:00
BOOST_LIBRARY_PATH = BOOST_INSTALL_PATH / 'lib'
BOOST_B2_PATH = BOOST_SOURCE_PATH / f'b2{EXE_EXT}'
# Eigen
EIGEN_SOURCE_PATH = DEPENDENCIES_PATH / 'eigen-source'
EIGEN_BUILD_PATH = DEPENDENCIES_PATH / 'eigen-build'
EIGEN_INSTALL_PATH = DEPENDENCIES_PATH / 'eigen-install'
EIGEN_INCLUDE_PATH = EIGEN_INSTALL_PATH / 'include'
# Chrono
CHRONO_SOURCE_PATH = DEPENDENCIES_PATH / 'chrono-source'
CHRONO_BUILD_PATH = DEPENDENCIES_PATH / 'chrono-build'
CHRONO_INSTALL_PATH = DEPENDENCIES_PATH / 'chrono-install'
CHRONO_INCLUDE_PATH = CHRONO_INSTALL_PATH / 'include'
CHRONO_LIBRARY_PATH = CHRONO_INSTALL_PATH / 'lib'
# Google Test
GTEST_SOURCE_PATH = DEPENDENCIES_PATH / 'gtest-source'
GTEST_BUILD_PATH = DEPENDENCIES_PATH / 'gtest-build'
GTEST_INSTALL_PATH = DEPENDENCIES_PATH / 'gtest-install'
GTEST_INCLUDE_PATH = GTEST_INSTALL_PATH / 'include'
GTEST_LIBRARY_PATH = GTEST_INSTALL_PATH / 'lib'
# ZLib
ZLIB_SOURCE_PATH = DEPENDENCIES_PATH / 'zlib-source'
ZLIB_BUILD_PATH = DEPENDENCIES_PATH / 'zlib-build'
ZLIB_INSTALL_PATH = DEPENDENCIES_PATH / 'zlib-install'
ZLIB_INCLUDE_PATH = ZLIB_INSTALL_PATH / 'include'
ZLIB_LIBRARY_PATH = ZLIB_INSTALL_PATH / 'lib'
ZLIB_LIB_PATH = ZLIB_LIBRARY_PATH / f'{LIB_PREFIX}zlib{LIB_EXT}'
2023-11-23 07:50:55 +08:00
# LibPNG
LIBPNG_SOURCE_PATH = DEPENDENCIES_PATH / 'libpng-source'
LIBPNG_BUILD_PATH = DEPENDENCIES_PATH / 'libpng-build'
LIBPNG_INSTALL_PATH = DEPENDENCIES_PATH / 'libpng-install'
LIBPNG_INCLUDE_PATH = LIBPNG_INSTALL_PATH / 'include'
LIBPNG_LIBRARY_PATH = LIBPNG_INSTALL_PATH / 'lib'
# SQLite
SQLITE_SOURCE_PATH = DEPENDENCIES_PATH / 'sqlite-source'
SQLITE_BUILD_PATH = DEPENDENCIES_PATH / 'sqlite-build'
SQLITE_LIBRARY_PATH = SQLITE_BUILD_PATH
SQLITE_INCLUDE_PATH = SQLITE_SOURCE_PATH
SQLITE_LIB_PATH = SQLITE_BUILD_PATH / f'{LIB_PREFIX}sqlite{LIB_EXT}'
2023-11-23 07:50:55 +08:00
SQLITE_EXE_PATH = SQLITE_BUILD_PATH / f'sqlite{EXE_EXT}'
# Proj
PROJ_SOURCE_PATH = DEPENDENCIES_PATH / 'proj-source'
PROJ_BUILD_PATH = DEPENDENCIES_PATH / 'proj-build'
PROJ_INSTALL_PATH = DEPENDENCIES_PATH / 'proj-install'
PROJ_INCLUDE_PATH = PROJ_INSTALL_PATH / 'include'
PROJ_LIBRARY_PATH = PROJ_INSTALL_PATH / 'lib'
# Recast & Detour
RECAST_SOURCE_PATH = DEPENDENCIES_PATH / 'recast-source'
RECAST_BUILD_PATH = DEPENDENCIES_PATH / 'recast-build'
RECAST_INSTALL_PATH = DEPENDENCIES_PATH / 'recast-install'
RECAST_INCLUDE_PATH = RECAST_INSTALL_PATH / 'include'
RECAST_LIBRARY_PATH = RECAST_INSTALL_PATH / 'lib'
# RPCLib
RPCLIB_SOURCE_PATH = DEPENDENCIES_PATH / 'rpclib-source'
RPCLIB_BUILD_PATH = DEPENDENCIES_PATH / 'rpclib-build'
RPCLIB_INSTALL_PATH = DEPENDENCIES_PATH / 'rpclib-install'
RPCLIB_INCLUDE_PATH = RPCLIB_INSTALL_PATH / 'include'
RPCLIB_LIBRARY_PATH = RPCLIB_INSTALL_PATH / 'lib'
# Xerces-C
XERCESC_SOURCE_PATH = DEPENDENCIES_PATH / 'xercesc-source'
XERCESC_BUILD_PATH = DEPENDENCIES_PATH / 'xercesc-build'
XERCESC_INSTALL_PATH = DEPENDENCIES_PATH / 'xercesc-install'
XERCESC_LIBRARY_PATH = XERCESC_INSTALL_PATH / 'lib'
XERCESC_INCLUDE_PATH = XERCESC_INSTALL_PATH / 'include'
# LibOSMScout
LIBOSMSCOUT_SOURCE_PATH = DEPENDENCIES_PATH / 'libosmscout-source'
LIBOSMSCOUT_BUILD_PATH = DEPENDENCIES_PATH / 'libosmscout-build'
LIBOSMSCOUT_INSTALL_PATH = DEPENDENCIES_PATH / 'libosmscout-install'
LIBOSMSCOUT_INCLUDE_PATH = LIBOSMSCOUT_INSTALL_PATH / 'include'
LIBOSMSCOUT_LIBRARY_PATH = LIBOSMSCOUT_INSTALL_PATH / 'lib'
# LunaSVG
LUNASVG_SOURCE_PATH = DEPENDENCIES_PATH / 'lunasvg-source'
LUNASVG_BUILD_PATH = DEPENDENCIES_PATH / 'lunasvg-build'
LUNASVG_INSTALL_PATH = DEPENDENCIES_PATH / 'lunasvg-install'
LUNASVG_INCLUDE_PATH = LUNASVG_INSTALL_PATH / 'include'
LUNASVG_LIBRARY_PATH = LUNASVG_INSTALL_PATH / 'lib'
# SUMO
SUMO_SOURCE_PATH = DEPENDENCIES_PATH / 'sumo-source'
SUMO_BUILD_PATH = DEPENDENCIES_PATH / 'sumo-build'
SUMO_INSTALL_PATH = DEPENDENCIES_PATH / 'sumo-install'
SUMO_INCLUDE_PATH = SUMO_INSTALL_PATH / 'include'
SUMO_LIBRARY_PATH = SUMO_INSTALL_PATH / 'lib'
# Nvidia Omniverse
NV_OMNIVERSE_PLUGIN_PATH = UNREAL_ENGINE_PATH / 'Engine' / 'Plugins' / 'Marketplace' / 'NVIDIA' / 'Omniverse'
NV_OMNIVERSE_PATCH_PATH = PATCHES_PATH / 'omniverse_4.26'
2023-11-23 07:50:55 +08:00
# Basic IO functions:
def Log(message):
message = str(message)
message += '\n'
print(message, end='')
def LaunchSubprocess(
cmd : list,
2023-12-01 22:21:12 +08:00
working_directory : Path = None,
log = None):
2023-11-23 07:50:55 +08:00
return subprocess.run(
cmd,
2023-12-01 22:21:12 +08:00
stdout = log,
stderr = log,
2023-11-23 07:50:55 +08:00
cwd = working_directory)
def LaunchSubprocessImmediate(
cmd : list,
working_directory : Path = None,
log_name : str = None):
2023-12-01 22:21:12 +08:00
sp = None
if not ARGV.no_log and log_name != None:
with open(LOG_PATH / f'{log_name}.log', 'w') as file:
sp = subprocess.run(
cmd,
cwd = working_directory,
stdout = file,
stderr = file)
else:
sp = subprocess.run(cmd, cwd = working_directory)
sp.check_returncode()
2023-11-23 07:50:55 +08:00
# Convenience classes for listing dependencies:
class Download:
2023-11-23 07:50:55 +08:00
def __init__(self, url : str):
self.url = url
class GitRepository:
2023-12-01 22:21:12 +08:00
def __init__(self, url : str, tag_or_branch : str = None, commit : str = None):
self.url = url
2023-12-01 22:21:12 +08:00
self.tag_or_branch = tag_or_branch
self.commit = commit
2023-11-23 07:50:55 +08:00
class Dependency:
2023-11-23 07:50:55 +08:00
def __init__(self, name : str, *sources):
self.name = name
2023-11-23 07:50:55 +08:00
self.sources = [ *sources ]
assert all(
type(e) is Download or
type(e) is GitRepository
for e in self.sources)
class DependencyUEPlugin(Dependency):
def __init__(self, name: str, *sources):
super().__init__(name, *sources)
DEFAULT_DEPENDENCIES = [
2023-12-01 22:21:12 +08:00
# Dependency(
# 'boost-asio',
# GitRepository('https://github.com/boostorg/asio.git')),
# Dependency(
# 'boost-python',
# GitRepository('https://github.com/boostorg/python.git')),
2023-12-20 18:42:39 +08:00
# Dependency(
# 'boost-gil',
# GitRepository('https://github.com/boostorg/gil.git')),
Dependency(
'boost',
Download(f'https://boostorg.jfrog.io/artifactory/main/release/{BOOST_VERSION_STRING}/source/boost_{BOOST_VERSION_MAJOR}_{BOOST_VERSION_MINOR}_{BOOST_VERSION_PATCH}.zip'),
Download(f'https://carla-releases.s3.eu-west-3.amazonaws.com/Backup/boost_{BOOST_VERSION_MAJOR}_{BOOST_VERSION_MINOR}_{BOOST_VERSION_PATCH}.zip')),
Dependency(
'eigen',
2023-12-01 22:21:12 +08:00
GitRepository('https://gitlab.com/libeigen/eigen.git', tag_or_branch = '3.4.0')),
Dependency(
'libpng',
2023-12-01 22:21:12 +08:00
GitRepository('https://github.com/glennrp/libpng.git', tag_or_branch = 'v1.6.40')),
Dependency(
'proj',
2023-12-01 22:21:12 +08:00
GitRepository('https://github.com/OSGeo/PROJ.git', tag_or_branch = '9.3.0'),
Download('https://download.osgeo.org/proj/proj-9.3.0.tar.gz')),
Dependency(
'gtest',
2023-12-01 22:21:12 +08:00
GitRepository('https://github.com/google/googletest.git', tag_or_branch = 'v1.14.0')),
Dependency(
'zlib',
GitRepository('https://github.com/madler/zlib.git'),
Download('https://zlib.net/current/zlib.tar.gz')),
Dependency(
'xercesc',
2023-12-01 22:21:12 +08:00
GitRepository('https://github.com/apache/xerces-c.git', tag_or_branch = 'v3.2.4'),
Download('https://archive.apache.org/dist/xerces/c/3/sources/xerces-c-3.2.3.zip'),
Download('https://carla-releases.s3.eu-west-3.amazonaws.com/Backup/xerces-c-3.2.3.zip')),
Dependency(
'sqlite',
Download('https://www.sqlite.org/2021/sqlite-amalgamation-3340100.zip')),
Dependency(
'rpclib',
2023-12-01 22:21:12 +08:00
GitRepository('https://github.com/rpclib/rpclib.git', tag_or_branch = 'v2.3.0')),
Dependency(
'recast',
2023-12-01 22:21:12 +08:00
GitRepository('https://github.com/carla-simulator/recastnavigation.git', tag_or_branch = 'carla')),
]
CHRONO_DEPENDENCIES = [
Dependency(
'chrono',
2023-12-01 22:21:12 +08:00
GitRepository('https://github.com/projectchrono/chrono.git', tag_or_branch = '8.0.0')),
]
OSM_WORLD_RENDERER_DEPENDENCIES = [
Dependency(
'libosmscout',
GitRepository('https://github.com/Framstag/libosmscout.git')),
Dependency(
'lunasvg',
GitRepository('https://github.com/sammycage/lunasvg.git')),
]
OSM2ODR_DEPENDENCIES = [
Dependency(
'sumo',
2023-12-01 22:21:12 +08:00
GitRepository('https://github.com/carla-simulator/sumo.git', tag_or_branch = 'carla_osm2odr')),
]
CARLA_UE_DEPENDENCIES = [
DependencyUEPlugin(
'StreetMap',
GitRepository(
'https://github.com/carla-simulator/StreetMap.git',
2023-12-01 22:21:12 +08:00
tag_or_branch = 'ue5.3')),
]
2023-11-23 07:50:55 +08:00
class Task:
2023-12-01 00:43:27 +08:00
def __init__(self, name : str, in_edges : list, body, *args):
assert all([ type(e) == Task for e in in_edges ])
self.name = name
self.body = body
self.args = args
2023-11-22 19:22:15 +08:00
self.in_edge_done_count = 0
2023-12-01 00:43:27 +08:00
self.in_edges = in_edges
self.out_edges = [] # Filled right before task graph execution.
2023-11-23 07:50:55 +08:00
self.done = False
def CreateSubprocessTask(name : str, in_edges : list, command : list):
2023-12-01 22:21:12 +08:00
return Task(name, in_edges, LaunchSubprocessImmediate, command, None, name)
2023-12-20 18:42:39 +08:00
def CreateCMakeConfigureDefaultCommandLine(source_path : Path, build_path : Path) -> list:
2023-11-23 07:50:55 +08:00
cpp_flags_release = '/MD'
2023-11-24 14:52:40 +08:00
if CPP_ENABLE_MARCH_NATIVE:
2023-11-23 07:50:55 +08:00
cpp_flags_release += ' -march=native'
2023-11-23 00:29:27 +08:00
return [
'cmake',
2023-11-23 07:50:55 +08:00
'-G', ARGV.generator,
'-S', source_path,
'-B', build_path,
2023-11-22 00:32:55 +08:00
'-DCMAKE_C_COMPILER=' + C_COMPILER,
'-DCMAKE_CXX_COMPILER=' + CPP_COMPILER,
'-DCMAKE_BUILD_TYPE=Release',
2023-11-23 07:50:55 +08:00
f'-DCMAKE_CXX_FLAGS_RELEASE={cpp_flags_release}',
]
2023-11-23 00:29:27 +08:00
2023-11-23 07:50:55 +08:00
def CreateCMakeConfigureDefault(name : str, in_edges : list, source_path : Path, build_path : Path, *args, install_path : Path = None):
2023-11-23 00:29:27 +08:00
cmd = Task.CreateCMakeConfigureDefaultCommandLine(source_path, build_path)
2023-11-18 06:18:00 +08:00
if install_path != None:
cmd.append('-DCMAKE_INSTALL_PREFIX=' + str(install_path))
cmd.extend([ *args, source_path ])
return Task.CreateSubprocessTask(name, in_edges, cmd)
2023-11-23 07:50:55 +08:00
def CreateCMakeBuildDefault(name : str, in_edges : list, build_path : Path, *args):
cmd = [ 'cmake', '--build', build_path ]
cmd.extend([ *args ])
return Task.CreateSubprocessTask(name, in_edges, cmd)
2023-11-23 07:50:55 +08:00
def CreateCMakeInstallDefault(name : str, in_edges : list, build_path : Path, install_path : Path, *args):
cmd = [ 'cmake', '--install', build_path, '--prefix', install_path ]
cmd.extend([ *args ])
return Task.CreateSubprocessTask(name, in_edges, cmd)
def Run(self):
self.body(*self.args)
2023-11-23 07:50:55 +08:00
class TaskGraph:
2023-11-23 07:50:55 +08:00
2023-11-24 07:10:37 +08:00
def __init__(self, parallelism : int = PARALLELISM):
2023-11-24 14:52:40 +08:00
self.sequential = SEQUENTIAL
2023-11-22 19:22:15 +08:00
self.parallelism = parallelism
self.tasks = []
self.sources = []
self.task_map = {}
def Reset(self):
self.tasks = []
self.sources = []
self.task_map = {}
2023-11-23 07:50:55 +08:00
def Add(self, task : Task):
self.tasks.append(task)
2023-12-01 00:43:27 +08:00
if len(task.in_edges) == 0:
2023-12-01 22:21:12 +08:00
self.sources.append(task)
self.task_map[task.name] = self.tasks[-1]
2023-11-23 07:50:55 +08:00
return task
2023-11-22 00:32:55 +08:00
def Validate(self):
return True
2023-11-18 06:18:00 +08:00
def Execute(self, sequential : bool = False):
2023-11-23 00:29:27 +08:00
if len(self.tasks) == 0:
return
2023-11-22 19:22:15 +08:00
from collections import deque
2023-11-22 00:32:55 +08:00
assert self.Validate()
2023-11-18 06:18:00 +08:00
prior_sequential = self.sequential
2023-11-23 00:29:27 +08:00
self.sequential = sequential
2023-11-18 06:18:00 +08:00
try:
2023-11-23 00:29:27 +08:00
for task in self.tasks:
2023-12-01 00:43:27 +08:00
for in_edge in task.in_edges:
2023-11-22 19:22:15 +08:00
assert in_edge != None
2023-11-23 00:29:27 +08:00
in_edge.out_edges.append(task)
2023-11-24 14:52:40 +08:00
2023-11-22 19:22:15 +08:00
task_queue = deque()
active_count = 0
2023-11-23 07:50:55 +08:00
done_count = 0
2023-11-22 19:22:15 +08:00
2023-12-01 22:21:12 +08:00
def UpdateOutEdges(task):
nonlocal task_queue
2023-11-23 00:29:27 +08:00
if len(task.out_edges) == 0:
return
2023-11-22 19:22:15 +08:00
for out in task.out_edges:
2023-11-23 00:29:27 +08:00
assert out.in_edge_done_count < len(out.in_edges)
2023-11-22 19:22:15 +08:00
out.in_edge_done_count += 1
if out.in_edge_done_count == len(out.in_edges):
task_queue.append(out)
2023-11-23 00:29:27 +08:00
2023-12-01 22:21:12 +08:00
def Flush():
nonlocal futures
nonlocal future_map
2023-11-23 07:50:55 +08:00
nonlocal done_count
2023-11-23 00:29:27 +08:00
nonlocal active_count
if active_count != 0:
2023-11-24 14:52:40 +08:00
done = [ e for e in as_completed(futures) ]
done_tasks = [ future_map[e] for e in done ]
for e in done_tasks:
e.done = True
Log(f'{e.name} - done')
2023-12-01 22:21:12 +08:00
UpdateOutEdges(e)
2023-11-24 14:52:40 +08:00
assert active_count == len(done_tasks)
done_count += len(done_tasks)
2023-11-23 00:29:27 +08:00
active_count = 0
2023-11-24 14:52:40 +08:00
future_map = {}
2023-11-23 00:29:27 +08:00
futures = []
2023-11-22 19:22:15 +08:00
2023-12-01 22:21:12 +08:00
assert len(set(self.sources)) == len(self.sources)
task_queue.extend(self.sources)
2023-11-24 14:52:40 +08:00
with ProcessPoolExecutor(self.parallelism) as pool:
2023-12-01 00:43:27 +08:00
futures = []
future_map = {}
2023-11-24 14:52:40 +08:00
while len(task_queue) != 0:
while len(task_queue) != 0 and active_count < self.parallelism:
task = task_queue.popleft()
Log(f'{task.name} - start')
if not self.sequential:
active_count += 1
future = pool.submit(task.Run)
future_map[future] = task
futures.append(future)
else:
task.Run()
Log(f'{task.name} - done')
task.done = True
done_count += 1
UpdateOutEdges(task)
2023-12-01 22:21:12 +08:00
Flush()
2023-11-23 07:50:55 +08:00
if done_count != len(self.tasks):
pending_tasks = []
for e in self.tasks:
if not e.done:
pending_tasks.append(e)
Log(f'{len(self.tasks) - done_count} did not complete: {pending_tasks}.')
assert False
2023-11-22 19:22:15 +08:00
2023-11-18 06:18:00 +08:00
finally:
self.sequential = prior_sequential
self.Reset()
def UpdateGitRepository(path : Path, url : str, branch : str = None, commit : str = None):
2023-11-15 03:48:24 +08:00
if path.exists():
LaunchSubprocessImmediate([ 'git', '-C', str(path), 'pull' ])
2023-11-15 03:48:24 +08:00
else:
cmd = [ 'git', '-C', str(path.parent), 'clone', '--depth', '1', '--single-branch' ]
2023-11-15 03:48:24 +08:00
if branch != None:
cmd.extend([ '-b', branch ])
cmd.extend([ url, path.stem ])
LaunchSubprocessImmediate(cmd)
if commit != None:
LaunchSubprocessImmediate([ 'git', '-C', str(path), 'fetch' ])
LaunchSubprocessImmediate([ 'git', '-C', str(path), 'checkout', commit ])
2023-11-15 03:48:24 +08:00
def DownloadDependency(name : str, path : Path, url : str):
# Download:
try:
temp_path = Path(str(path) + '.tmp')
with requests.Session() as session:
with session.get(url, stream = True) as result:
result.raise_for_status()
with open(temp_path, 'wb') as file:
shutil.copyfileobj(result.raw, file)
except Exception as err:
Log(f'Failed to download dependency "{name}": {err}')
# Extract:
try:
extract_path = path.with_name(path.name + '-temp')
if url.endswith('.tar.gz'):
archive_path = temp_path.with_suffix('.tar.gz')
temp_path.rename(archive_path)
with tarfile.open(archive_path) as file:
file.extractall(extract_path)
elif url.endswith('.zip'):
archive_path = temp_path.with_suffix('.zip')
temp_path.rename(archive_path)
zipfile.ZipFile(archive_path).extractall(extract_path)
# Peel unnecessary outer directory:
entries = [ file for file in extract_path.iterdir() ]
if len(entries) == 1 and entries[0].is_dir():
Path(entries[0]).rename(path)
if extract_path.exists():
extract_path.rmdir()
2023-11-15 03:48:24 +08:00
else:
extract_path.rename(path)
except Exception as err:
Log(f'Failed to extract dependency "{name}": {err}')
2023-10-28 07:21:01 +08:00
def UpdateDependency(dep : Dependency):
name = dep.name
download_path = DEPENDENCIES_PATH / f'{name}-source'
if type(dep) is DependencyUEPlugin: # Override download path if we're dealing with an Unreal Engine Plugin.
download_path = CARLA_UE_PLUGIN_ROOT_PATH / name
for source in dep.sources:
2023-11-15 03:48:24 +08:00
try:
if type(source) is GitRepository:
2023-12-01 22:21:12 +08:00
UpdateGitRepository(download_path, source.url, source.tag_or_branch, source.commit)
elif type(source) is Download:
2023-11-15 03:48:24 +08:00
if download_path.exists():
Log(f'Dependency "{name}" already present. Delete "{download_path}" if you wish for it to be downloaded again.')
else:
DownloadDependency(name, download_path, source.url)
2023-11-15 03:48:24 +08:00
return
finally:
pass
Log(f'Failed to update dependency "{name}".')
assert False
2023-11-23 07:50:55 +08:00
def UpdateDependencies(task_graph : TaskGraph):
2023-11-24 02:06:48 +08:00
DEPENDENCIES_PATH.mkdir(exist_ok = True)
2023-11-24 07:10:37 +08:00
unique_deps = set(DEFAULT_DEPENDENCIES)
if ENABLE_CARLA_UE:
unique_deps.update(CARLA_UE_DEPENDENCIES)
2023-11-24 02:06:48 +08:00
if ENABLE_OSM_WORLD_RENDERER:
2023-11-24 07:10:37 +08:00
unique_deps.update(OSM_WORLD_RENDERER_DEPENDENCIES)
2023-11-24 02:06:48 +08:00
if ENABLE_OSM2ODR:
2023-11-24 07:10:37 +08:00
unique_deps.update(OSM2ODR_DEPENDENCIES)
2023-11-24 02:06:48 +08:00
if ENABLE_CHRONO:
2023-11-24 07:10:37 +08:00
unique_deps.update(CHRONO_DEPENDENCIES)
2023-12-01 00:43:27 +08:00
return [
2023-12-20 18:08:55 +08:00
task_graph.Add(Task(f'update-{dep.name}', [], UpdateDependency, dep)) for dep in unique_deps
2023-12-01 00:43:27 +08:00
]
2023-11-15 03:48:24 +08:00
2023-11-24 02:06:48 +08:00
def CleanDownloadsMain():
for ext in [ '*.tmp', '*.zip', '*.tar.gz' ]:
for e in DEPENDENCIES_PATH.glob(ext):
e.unlink(missing_ok = True)
def CleanDownloads(task_graph : TaskGraph):
2023-12-01 00:43:27 +08:00
return task_graph.Add(Task('clean-downloads', [], CleanDownloadsMain))
2023-11-24 02:06:48 +08:00
2023-11-15 03:48:24 +08:00
def ConfigureBoost():
if BOOST_B2_PATH.exists():
2023-11-15 03:48:24 +08:00
return
LaunchSubprocessImmediate(
[ BOOST_SOURCE_PATH / f'bootstrap{SHELL_EXT}' ],
working_directory = BOOST_SOURCE_PATH)
2023-11-15 03:48:24 +08:00
def BuildAndInstallBoost():
2023-12-01 22:21:12 +08:00
LaunchSubprocessImmediate([
BOOST_B2_PATH,
2023-11-24 07:10:37 +08:00
f'-j{PARALLELISM}',
'architecture=x86',
'address-model=64',
f'toolset={BOOST_TOOLSET}',
2023-11-15 03:48:24 +08:00
'variant=release',
'link=static',
'runtime-link=shared',
'threading=multi',
'--layout=versioned',
'--with-system',
'--with-filesystem',
'--with-python',
'--with-date_time',
f'--build-dir={BOOST_BUILD_PATH}',
f'--prefix={BOOST_INSTALL_PATH}',
f'--libdir={BOOST_LIBRARY_PATH}',
2023-12-01 22:21:12 +08:00
f'--includedir={BOOST_INCLUDE_PATH}',
2023-11-15 03:48:24 +08:00
'install'
2023-12-01 22:21:12 +08:00
],
working_directory = BOOST_SOURCE_PATH,
log_name = 'build-boost')
if (BOOST_INCLUDE_PATH / 'boost').exists():
return
candidates = glob.glob(f'{BOOST_INCLUDE_PATH}/**/boost', recursive = True)
candidates.sort()
boost_path = Path(candidates[0])
shutil.move(boost_path, BOOST_INCLUDE_PATH / 'boost')
boost_path.parent.rmdir()
2023-11-15 03:48:24 +08:00
def BuildSQLite():
SQLITE_BUILD_PATH.mkdir(exist_ok = True)
sqlite_sources = glob.glob(f'{SQLITE_SOURCE_PATH}/**/*.c', recursive = True)
2023-11-24 14:52:40 +08:00
sqlite_sources = [ Path(e) for e in sqlite_sources ]
if not SQLITE_EXE_PATH.exists():
cmd = [ C_COMPILER ]
cmd.extend([
f'-std=c{C_STANDARD}',
f'-fuse-ld={LINKER}',
'-O2',
] if C_COMPILER_CLI_TYPE == 'gnu' else [
f'/std:c{C_STANDARD}',
'/O2',
'/Qvec',
'/MD',
'/EHsc',
])
if C_ENABLE_MARCH_NATIVE:
cmd.append('-march=native')
cmd.extend(sqlite_sources)
if C_COMPILER_CLI_TYPE == 'msvc':
cmd.append(f'/Fe{SQLITE_EXE_PATH}')
else:
cmd.extend([ '-o', SQLITE_EXE_PATH ])
2023-11-24 14:52:40 +08:00
LaunchSubprocessImmediate(cmd, log_name = 'build-sqlite-exe')
if not SQLITE_LIB_PATH.exists():
if C_COMPILER_IS_CLANG:
cmd = [
C_COMPILER,
f'-fuse-ld={LIB}',
]
2023-11-24 07:10:37 +08:00
cmd.extend([
2023-11-24 14:52:40 +08:00
f'-std=c{C_STANDARD}',
'-march=native',
'-O2',
] if C_COMPILER_CLI_TYPE == 'gnu' else [
f'/std:c{C_STANDARD}',
2023-11-23 07:50:55 +08:00
'/O2',
2023-11-24 14:52:40 +08:00
'/Qvec',
2023-11-23 07:50:55 +08:00
'/MD',
2023-11-24 07:10:37 +08:00
'/EHsc',
])
2023-11-24 14:52:40 +08:00
if C_ENABLE_MARCH_NATIVE:
cmd.append('-march=native')
cmd.extend(sqlite_sources)
cmd.extend([ '/Fo:' if C_COMPILER_CLI_TYPE == 'msvc' else '-o', SQLITE_LIB_PATH ])
2023-11-24 14:52:40 +08:00
LaunchSubprocessImmediate(
cmd,
log_name = 'build-sqlite-lib')
else:
objs = []
for e in sqlite_sources:
cmd = [
C_COMPILER,
'-c' if C_COMPILER_CLI_TYPE == 'gnu' else '/c',
]
cmd.extend([
f'-std=c{C_STANDARD}',
'-march=native',
'-O2',
] if C_COMPILER_CLI_TYPE == 'gnu' else [
f'/std:c{C_STANDARD}',
'/O2',
'/Qvec',
'/MD',
'/EHsc',
])
obj_path = SQLITE_BUILD_PATH / f'{e.name}{OBJ_EXT}'
cmd.extend([ e, '/Fo:' if C_COMPILER_CLI_TYPE == 'msvc' else '-o', obj_path ])
2023-11-24 14:52:40 +08:00
LaunchSubprocessImmediate(cmd, log_name = f'build-sqlite-{e.stem}')
objs.append(obj_path)
cmd = [
LIB,
f'/OUT:{SQLITE_LIB_PATH}',
]
cmd.extend(objs)
LaunchSubprocessImmediate(cmd, log_name = 'build-sqlite-lib')
2023-11-15 03:48:24 +08:00
2023-11-23 00:29:27 +08:00
def ConfigureSUMO():
2023-12-20 18:42:39 +08:00
xercesc_path_candidates = glob.glob(f'{XERCESC_INSTALL_PATH}/**/{LIB_PREFIX}xerces-c*{LIB_EXT}', recursive=True)
if len(xercesc_path_candidates) == 0:
raise Exception('Could not configure SUMO since xerces-c could not be found.')
if len(xercesc_path_candidates) > 1:
Log('Warning: multiple xerces-c libraries found.')
xercesc_path_candidates.sort()
XERCESC_PATH = xercesc_path_candidates[0]
2023-11-23 00:29:27 +08:00
cmd = Task.CreateCMakeConfigureDefaultCommandLine(
SUMO_SOURCE_PATH,
SUMO_BUILD_PATH)
cmd.extend([
SUMO_SOURCE_PATH,
SUMO_BUILD_PATH,
f'-DZLIB_INCLUDE_DIR={ZLIB_INCLUDE_PATH}',
f'-DZLIB_LIBRARY={ZLIB_LIBRARY_PATH}',
f'-DPROJ_INCLUDE_DIR={PROJ_INSTALL_PATH}/include',
f'-DPROJ_LIBRARY={PROJ_INSTALL_PATH}/lib/{LIB_PREFIX}proj{LIB_EXT}',
2023-11-23 00:29:27 +08:00
f'-DXercesC_INCLUDE_DIR={XERCESC_INSTALL_PATH}/include',
2023-12-20 18:42:39 +08:00
f'-DXercesC_LIBRARY={XERCESC_PATH}',
2023-11-23 00:29:27 +08:00
'-DSUMO_LIBRARIES=OFF',
# '-DPROFILING=OFF',
# '-DPPROF=OFF',
# '-DCOVERAGE=OFF',
# '-DSUMO_UTILS=OFF',
# '-DFMI=OFF',
# '-DNETEDIT=OFF',
# '-DENABLE_JAVA_BINDINGS=OFF',
# '-DENABLE_CS_BINDINGS=OFF',
# '-DCCACHE_SUPPORT=OFF',
])
LaunchSubprocessImmediate(cmd)
2023-12-20 18:08:55 +08:00
def BuildDependencies(
task_graph : TaskGraph):
# Configure:
2023-12-01 00:43:27 +08:00
build_sqlite = task_graph.Add(Task('build-sqlite', [], BuildSQLite))
2023-11-23 07:50:55 +08:00
task_graph.Add(Task('configure-boost', [], ConfigureBoost))
2023-12-01 00:43:27 +08:00
configure_zlib = task_graph.Add(Task.CreateCMakeConfigureDefault(
'configure-zlib',
[],
ZLIB_SOURCE_PATH,
2023-11-18 06:18:00 +08:00
ZLIB_BUILD_PATH,
2023-11-24 02:06:48 +08:00
install_path = ZLIB_INSTALL_PATH))
2023-12-01 00:43:27 +08:00
build_zlib = task_graph.Add(Task.CreateCMakeBuildDefault(
2023-11-24 02:06:48 +08:00
'build-zlib',
2023-12-01 00:43:27 +08:00
[ configure_zlib ],
2023-11-24 02:06:48 +08:00
ZLIB_BUILD_PATH))
task_graph.Add(Task.CreateCMakeInstallDefault(
'install-zlib',
2023-12-01 00:43:27 +08:00
[ build_zlib ],
2023-11-24 02:06:48 +08:00
ZLIB_BUILD_PATH,
ZLIB_INSTALL_PATH))
2023-11-23 07:50:55 +08:00
task_graph.Add(Task.CreateCMakeConfigureDefault(
'configure-gtest',
[],
GTEST_SOURCE_PATH,
GTEST_BUILD_PATH))
2023-11-23 07:50:55 +08:00
task_graph.Add(Task.CreateCMakeConfigureDefault(
'configure-libpng',
[],
LIBPNG_SOURCE_PATH,
LIBPNG_BUILD_PATH,
'-DPNG_TESTS=OFF',
'-DPNG_TOOLS=OFF',
'-DPNG_BUILD_ZLIB=ON',
2023-11-18 06:18:00 +08:00
f'-DZLIB_INCLUDE_DIRS={ZLIB_INCLUDE_PATH}',
2023-11-22 00:32:55 +08:00
f'-DZLIB_LIBRARIES={ZLIB_LIB_PATH}'))
2023-11-23 07:50:55 +08:00
task_graph.Add(Task.CreateCMakeConfigureDefault(
'configure-proj',
2023-12-01 00:43:27 +08:00
[ build_sqlite ],
PROJ_SOURCE_PATH,
PROJ_BUILD_PATH,
f'-DSQLITE3_INCLUDE_DIR={SQLITE_SOURCE_PATH}',
2023-11-22 00:32:55 +08:00
f'-DSQLITE3_LIBRARY={SQLITE_LIB_PATH}',
f'-DEXE_SQLITE3={SQLITE_EXE_PATH}',
2023-11-15 03:48:24 +08:00
'-DWIN32_LEAN_AND_MEAN=1',
'-DVC_EXTRALEAN=1',
'-DNOMINMAX=1',
'-DENABLE_TIFF=OFF',
'-DENABLE_CURL=OFF',
'-DBUILD_SHARED_LIBS=OFF',
'-DBUILD_PROJSYNC=OFF',
'-DBUILD_PROJINFO=OFF',
'-DBUILD_CCT=OFF',
'-DBUILD_CS2CS=OFF',
'-DBUILD_GEOD=OFF',
'-DBUILD_GIE=OFF',
'-DBUILD_PROJ=OFF',
'-DBUILD_TESTING=OFF',
install_path = PROJ_INSTALL_PATH))
2023-11-23 07:50:55 +08:00
task_graph.Add(Task.CreateCMakeConfigureDefault(
'configure-recast',
[],
RECAST_SOURCE_PATH,
RECAST_BUILD_PATH,
2023-11-15 03:48:24 +08:00
'-DRECASTNAVIGATION_DEMO=OFF',
'-DRECASTNAVIGATION_TESTS=OFF',
'-DRECASTNAVIGATION_EXAMPLES=OFF'))
2023-11-23 07:50:55 +08:00
task_graph.Add(Task.CreateCMakeConfigureDefault(
'configure-rpclib',
[],
RPCLIB_SOURCE_PATH,
RPCLIB_BUILD_PATH,
2023-11-15 03:48:24 +08:00
'-DRPCLIB_BUILD_TESTS=OFF',
'-DRPCLIB_GENERATE_COMPDB=OFF',
'-DRPCLIB_BUILD_EXAMPLES=OFF',
'-DRPCLIB_ENABLE_LOGGING=OFF',
'-DRPCLIB_ENABLE_COVERAGE=OFF',
'-DRPCLIB_MSVC_STATIC_RUNTIME=OFF'))
2023-11-23 07:50:55 +08:00
task_graph.Add(Task.CreateCMakeConfigureDefault(
'configure-xercesc',
[],
XERCESC_SOURCE_PATH,
XERCESC_BUILD_PATH))
2023-11-24 02:06:48 +08:00
if ENABLE_OSM_WORLD_RENDERER:
2023-11-23 07:50:55 +08:00
task_graph.Add(Task.CreateCMakeConfigureDefault(
'configure-libosmscout',
[],
LIBOSMSCOUT_SOURCE_PATH,
LIBOSMSCOUT_BUILD_PATH,
'-DOSMSCOUT_BUILD_TOOL_STYLEEDITOR=OFF',
'-DOSMSCOUT_BUILD_TOOL_OSMSCOUT2=OFF',
'-DOSMSCOUT_BUILD_TESTS=OFF',
'-DOSMSCOUT_BUILD_CLIENT_QT=OFF',
'-DOSMSCOUT_BUILD_DEMOS=OFF'))
2023-11-23 07:50:55 +08:00
task_graph.Add(Task.CreateCMakeConfigureDefault(
'configure-lunasvg',
[],
LUNASVG_SOURCE_PATH,
LUNASVG_BUILD_PATH))
2023-11-24 02:06:48 +08:00
if ENABLE_CHRONO:
2023-11-23 07:50:55 +08:00
task_graph.Add(Task.CreateCMakeConfigureDefault(
'configure-chrono',
[],
CHRONO_SOURCE_PATH,
CHRONO_BUILD_PATH,
f'-DEIGEN3_INCLUDE_DIR={EIGEN_SOURCE_PATH}',
'-DENABLE_MODULE_VEHICLE=ON'))
2023-11-23 07:50:55 +08:00
task_graph.Execute()
2023-12-01 22:21:12 +08:00
# Build:
2023-11-23 07:50:55 +08:00
task_graph.Add(Task('build-boost', [], BuildAndInstallBoost))
task_graph.Add(Task.CreateCMakeBuildDefault('build-gtest', [], GTEST_BUILD_PATH))
task_graph.Add(Task.CreateCMakeBuildDefault('build-libpng', [], LIBPNG_BUILD_PATH))
task_graph.Add(Task.CreateCMakeBuildDefault('build-proj', [], PROJ_BUILD_PATH))
task_graph.Add(Task.CreateCMakeBuildDefault('build-recast', [], RECAST_BUILD_PATH))
task_graph.Add(Task.CreateCMakeBuildDefault('build-rpclib', [], RPCLIB_BUILD_PATH))
2023-12-01 00:43:27 +08:00
build_xercesc = task_graph.Add(Task.CreateCMakeBuildDefault('build-xercesc', [], XERCESC_BUILD_PATH))
2023-12-20 18:42:39 +08:00
install_xercesc = task_graph.Add(Task.CreateCMakeInstallDefault('install-xercesc', [ build_xercesc ], XERCESC_BUILD_PATH, XERCESC_INSTALL_PATH))
2023-11-24 02:06:48 +08:00
if ENABLE_OSM_WORLD_RENDERER:
2023-11-23 07:50:55 +08:00
task_graph.Add(Task.CreateCMakeBuildDefault('build-lunasvg', [], LUNASVG_BUILD_PATH))
task_graph.Add(Task.CreateCMakeBuildDefault('build-libosmscout', [], LIBOSMSCOUT_BUILD_PATH))
2023-11-24 02:06:48 +08:00
if ENABLE_OSM2ODR:
2023-12-20 18:42:39 +08:00
configure_sumo = task_graph.Add(Task('configure-sumo', [ install_xercesc ], ConfigureSUMO))
2023-12-01 00:43:27 +08:00
task_graph.Add(Task.CreateCMakeBuildDefault('build-sumo', [ configure_sumo ], SUMO_BUILD_PATH))
2023-11-24 02:06:48 +08:00
if ENABLE_CHRONO:
2023-11-23 07:50:55 +08:00
task_graph.Add(Task.CreateCMakeBuildDefault('build-chrono', [], CHRONO_BUILD_PATH))
2023-12-20 18:42:39 +08:00
2023-11-23 07:50:55 +08:00
task_graph.Execute(sequential = True) # The underlying build system should already parallelize.
2023-12-01 22:21:12 +08:00
# Install:
2023-11-23 07:50:55 +08:00
task_graph.Add(Task.CreateCMakeInstallDefault('install-gtest', [], GTEST_BUILD_PATH, GTEST_INSTALL_PATH))
task_graph.Add(Task.CreateCMakeInstallDefault('install-libpng', [], LIBPNG_BUILD_PATH, LIBPNG_INSTALL_PATH))
task_graph.Add(Task.CreateCMakeInstallDefault('install-proj', [], PROJ_BUILD_PATH, PROJ_INSTALL_PATH))
task_graph.Add(Task.CreateCMakeInstallDefault('install-recast', [], RECAST_BUILD_PATH, RECAST_INSTALL_PATH))
task_graph.Add(Task.CreateCMakeInstallDefault('install-rpclib', [], RPCLIB_BUILD_PATH, RPCLIB_INSTALL_PATH))
2023-11-24 02:06:48 +08:00
if ENABLE_OSM_WORLD_RENDERER:
2023-11-23 07:50:55 +08:00
task_graph.Add(Task.CreateCMakeInstallDefault('install-lunasvg', [], LUNASVG_BUILD_PATH, LUNASVG_INSTALL_PATH))
task_graph.Add(Task.CreateCMakeInstallDefault('install-libosmscout', [], LIBOSMSCOUT_BUILD_PATH, LIBOSMSCOUT_INSTALL_PATH))
2023-11-24 02:06:48 +08:00
if ENABLE_OSM2ODR:
2023-11-23 07:50:55 +08:00
task_graph.Add(Task.CreateCMakeInstallDefault('install-sumo', [], SUMO_BUILD_PATH, SUMO_INSTALL_PATH))
2023-11-24 02:06:48 +08:00
if ENABLE_CHRONO:
2023-11-23 07:50:55 +08:00
task_graph.Add(Task.CreateCMakeInstallDefault('install-chrono', [], CHRONO_BUILD_PATH, CHRONO_INSTALL_PATH))
task_graph.Execute()
def BuildLibCarlaMain(task_graph : TaskGraph):
2023-12-01 00:43:27 +08:00
configure_libcarla = task_graph.Add(Task.CreateCMakeConfigureDefault(
'configure-libcarla',
[],
WORKSPACE_PATH,
LIBCARLA_BUILD_PATH,
f'-DCARLA_DEPENDENCIES_PATH={DEPENDENCIES_PATH}',
f'-DBUILD_LIBCARLA_SERVER={"ON" if ARGV.libcarla_server else "OFF"}',
f'-DBUILD_LIBCARLA_CLIENT={"ON" if ARGV.libcarla_client else "OFF"}',
f'-DBUILD_OSM_WORLD_RENDERER={"ON" if ENABLE_OSM_WORLD_RENDERER else "OFF"}',
f'-DLIBCARLA_PYTORCH={"ON" if ARGV.pytorch else "OFF"}'))
2023-12-01 00:43:27 +08:00
build_libcarla = task_graph.Add(Task.CreateCMakeBuildDefault(
'build-libcarla',
2023-12-01 00:43:27 +08:00
[ configure_libcarla ],
LIBCARLA_BUILD_PATH))
2023-12-01 00:43:27 +08:00
return task_graph.Add(Task.CreateCMakeInstallDefault(
'install-libcarla',
2023-12-01 00:43:27 +08:00
[ build_libcarla ],
LIBCARLA_BUILD_PATH,
LIBCARLA_INSTALL_PATH))
def BuildPythonAPIMain():
content = ''
with open(PYTHON_API_PATH / 'setup.py.in', 'r') as file:
content = file.read()
content = content.format_map(globals())
if os.name == 'nt':
content = content.replace(os.sep, '\\\\')
with open(PYTHON_API_PATH / 'setup.py', 'w') as file:
file.write(content)
LaunchSubprocessImmediate([
sys.executable, 'setup.py', 'bdist_wheel', 'bdist_egg'
], working_directory = PYTHON_API_PATH)
def BuildPythonAPI(task_graph : TaskGraph):
2023-12-01 00:43:27 +08:00
install_libcarla = task_graph.task_map.get('install-libcarla')
task_graph.Add(Task('build-python-api', [ install_libcarla ], BuildPythonAPIMain))
def SetupUnrealEngine(task_graph : TaskGraph):
pass
def BuildCarlaUEMain():
assert UNREAL_ENGINE_PATH.exists()
unreal_build_tool_args = []
if ENABLE_CARSIM:
unreal_build_tool_args.append('-carsim')
if ENABLE_CHRONO:
unreal_build_tool_args.append('-chrono')
if ENABLE_ROS2:
unreal_build_tool_args.append('-ros2')
if ENABLE_UNITY_BUILD:
unreal_build_tool_args.append('-unity-build')
if ENABLE_NVIDIA_OMNIVERSE:
unreal_build_tool_args.append('-nv-omniverse')
if os.name == 'nt':
LaunchSubprocessImmediate([
UNREAL_ENGINE_PATH / 'Engine' / 'Build' / 'BatchFiles' / 'Build.bat',
'CarlaUE4Editor',
'Win64',
'Development',
'-WaitMutex',
'-FromMsBuild',
CARLA_UE_PATH / 'CarlaUE4.uproject',
], log_name = 'build-carla-ue-editor')
LaunchSubprocessImmediate([
UNREAL_ENGINE_PATH / 'Engine' / 'Build' / 'BatchFiles' / 'Build.bat',
'CarlaUE4',
'Win64',
'Development',
'-WaitMutex',
'-FromMsBuild',
CARLA_UE_PATH / 'CarlaUE4.uproject',
], log_name = 'build-carla-ue')
else:
pass
def BuildCarlaUE(task_graph : TaskGraph):
if ENABLE_NVIDIA_OMNIVERSE:
task_graph.Add(Task('install-nv-omniverse', [], InstallNVIDIAOmniverse))
2023-12-01 00:43:27 +08:00
dependencies = []
if ENABLE_LIBCARLA:
dependencies.append(task_graph.task_map.get('install-libcarla'))
if ENABLE_PYTHON_API:
dependencies.append(task_graph.task_map.get('build-python-api'))
task_graph.Add(Task('build-carla-ue', dependencies, BuildCarlaUEMain))
def InstallNVIDIAOmniverse():
filename = 'USDCarlaInterface'
header = f'{filename}.h'
source = f'{filename}.cpp'
omniverse_usd_path = NV_OMNIVERSE_PLUGIN_PATH / 'Source' / 'OmniverseUSD'
files = [
[ omniverse_usd_path / 'Public' / header, NV_OMNIVERSE_PATCH_PATH / header ],
[ omniverse_usd_path / 'Private' / source, NV_OMNIVERSE_PATCH_PATH / source ],
]
for src, dst in files:
shutil.copyfile(src, dst)
2023-11-23 07:50:55 +08:00
2023-11-24 02:06:48 +08:00
def Clean():
if not BUILD_PATH.exists():
return
try:
shutil.rmtree(BUILD_PATH)
finally:
Log(f'Failed to remove {BUILD_PATH}.')
exit(-1)
2023-11-23 07:50:55 +08:00
2023-10-28 07:21:01 +08:00
if __name__ == '__main__':
2023-11-15 03:48:24 +08:00
try:
2023-11-24 07:10:37 +08:00
task_graph = TaskGraph(PARALLELISM)
2023-11-23 07:50:55 +08:00
if ARGV.clean or ARGV.rebuild:
2023-11-24 02:06:48 +08:00
Clean()
BUILD_PATH.mkdir(exist_ok = True)
2023-11-24 14:52:40 +08:00
if not ARGV.no_log:
LOG_PATH.mkdir(exist_ok = True)
2023-11-24 02:06:48 +08:00
if UPDATE_DEPENDENCIES:
2023-11-23 07:50:55 +08:00
UpdateDependencies(task_graph)
2023-11-24 02:06:48 +08:00
CleanDownloads(task_graph)
if BUILD_DEPENDENCIES:
2023-11-23 07:50:55 +08:00
BuildDependencies(task_graph)
2023-11-24 02:06:48 +08:00
if ENABLE_LIBCARLA:
2023-11-23 07:50:55 +08:00
BuildLibCarlaMain(task_graph)
2023-11-24 07:10:37 +08:00
if ENABLE_PYTHON_API:
2023-11-23 07:50:55 +08:00
BuildPythonAPI(task_graph)
2023-12-01 00:43:27 +08:00
if ENABLE_CARLA_UE:
2023-11-23 07:50:55 +08:00
BuildCarlaUE(task_graph)
task_graph.Execute()
2023-11-15 03:48:24 +08:00
except Exception as err:
Log(err)
2023-11-23 07:50:55 +08:00
Log(DEFAULT_ERROR_MESSAGE)
2023-11-24 14:52:40 +08:00
exit(-1)
finally:
try:
ARGS_SYNC_PATH.unlink(missing_ok = True)
finally:
2023-12-01 00:43:27 +08:00
pass
exit(0)