|
1 | 1 | import argparse |
2 | 2 | import os |
3 | 3 | import platform |
| 4 | +import json |
4 | 5 | import shutil |
5 | 6 | import subprocess |
6 | 7 | import sys |
7 | 8 | from datetime import datetime |
| 9 | +from typing import Optional, Callable |
8 | 10 |
|
9 | 11 | import importlib.metadata |
10 | 12 | from packaging.requirements import Requirement |
@@ -201,6 +203,9 @@ def requirements(self): |
201 | 203 | self.requires("protobuf/3.21.12") # For compatibility with openCV |
202 | 204 | self.requires("cppzmq/4.5.0") |
203 | 205 |
|
| 206 | + if self.options.get_safe("mujoco"): |
| 207 | + self.requires(f"mujoco/{get_mujoco_version()}") |
| 208 | + |
204 | 209 | def configure(self): |
205 | 210 | if self.options.get_safe("clean"): |
206 | 211 | # clean the distribution folder to start fresh |
@@ -354,13 +359,48 @@ def add_basilisk_to_sys_path(self): |
354 | 359 | if err.decode() != "": |
355 | 360 | print("This resulted in the stderr: \n%s" % err.decode()) |
356 | 361 |
|
| 362 | +def get_mujoco_version(): |
| 363 | + with open("./libs/mujoco/version.txt") as f: |
| 364 | + return f.read().strip() |
| 365 | + |
| 366 | +def is_conan_package_available(ref: str): |
| 367 | + """ |
| 368 | + Run 'conan list' and return True if package exists in local or remote caches. |
| 369 | + """ |
| 370 | + try: |
| 371 | + output = subprocess.check_output( |
| 372 | + [sys.executable, "-m", "conans.conan", "list", ref, "-c", "-f", "json", "-verror"], |
| 373 | + stderr=subprocess.STDOUT, |
| 374 | + universal_newlines=True |
| 375 | + ) |
| 376 | + parsed = json.loads(output) |
| 377 | + return any( "error" not in v for v in parsed.values() ) |
| 378 | + except subprocess.CalledProcessError: |
| 379 | + return False |
| 380 | + |
| 381 | +def conan_create_mujoco(print_fn: Optional[Callable[[str], None]] = print): |
| 382 | + """ |
| 383 | + If the 'mujoco/VERSION' package is not found in any remote or the local cache, |
| 384 | + then the mujoco project (as defined in '/libs/mujoco/conanfile.py') is created |
| 385 | + into the local cache. |
| 386 | + """ |
| 387 | + ref = f"mujoco/{get_mujoco_version()}" |
| 388 | + if not is_conan_package_available(ref): |
| 389 | + if print_fn is not None: |
| 390 | + print_fn(f"Package {ref} not found locally, creating it...") |
| 391 | + # Run 'conan create' in the external recipe directory |
| 392 | + subprocess.run([sys.executable, "-m", "conans.conan", "create", ".", "-s" ,"compiler.cppstd=17"], cwd="./libs/mujoco" ) |
| 393 | + else: |
| 394 | + if print_fn is not None: |
| 395 | + print_fn(f"Package {ref} already available, skipping creation.") |
| 396 | + |
357 | 397 | if __name__ == "__main__": |
358 | 398 | # make sure conan is configured to use the libstdc++11 by default |
359 | 399 | # XXX: This needs to be run before dispatching to Conan (i.e. outside of the |
360 | 400 | # ConanFile object), because it affects the configuration of the first run. |
361 | 401 | # (Running it here fixes https://github.com/AVSLab/basilisk/issues/525) |
362 | 402 | try: |
363 | | - subprocess.check_output(["conan", "profile", "detect", "--exist-ok"]) |
| 403 | + subprocess.check_output([sys.executable, "-m", "conans.conan", "profile", "detect", "--exist-ok"]) |
364 | 404 | except: |
365 | 405 | # if profile already exists the above command returns an error. Just ignore in this |
366 | 406 | # case. We don't want to overwrite an existing profile file |
@@ -406,12 +446,24 @@ def add_basilisk_to_sys_path(self): |
406 | 446 | genMod.createCModule() |
407 | 447 | print("Done") |
408 | 448 |
|
| 449 | + # If we're missing MuJoCo, create the conan package |
| 450 | + if args.mujoco: |
| 451 | + conan_create_mujoco() |
| 452 | + |
| 453 | + if args.mujocoReplay: |
| 454 | + print(f"{statusColor}Building 'replay' tool, since '--mujocoReplay true' was used") |
| 455 | + try: |
| 456 | + subprocess.check_output([sys.executable, "-m", "conans.conan", "build", ".", "-s" ,"compiler.cppstd=17", "--build=missing"], cwd="./src/utilities/mujocoUtils" ) |
| 457 | + except: |
| 458 | + raise RuntimeError("Failed to install MuJoCo replay! See error above.") |
| 459 | + |
409 | 460 | # setup conan install command arguments |
410 | 461 | conanInstallList = list() |
411 | 462 | conanInstallList.append(f'{sys.executable} -m conans.conan install . --build=missing') |
412 | 463 | conanInstallList.append(' -s build_type=' + str(args.buildType)) |
| 464 | + conanInstallList.append(' -s compiler.cppstd=17') |
413 | 465 | conanBuildOptionsList = list() # setup list of conan build arguments |
414 | | - # The following options go to both conan install and build commands |
| 466 | + conanBuildOptionsList.append(' -s compiler.cppstd=17') |
415 | 467 | if args.generator: |
416 | 468 | conanBuildOptionsList.append(' -o "&:generator=' + str(args.generator) + '"') |
417 | 469 | for opt, value in bskModuleOptionsBool.items(): |
|
0 commit comments