mujoco icon indicating copy to clipboard operation
mujoco copied to clipboard

How to build code that uses `mjCModel`?

Open BenjaminNavarro opened this issue 2 years ago • 8 comments

As advised to me in #364 I tried to use mjCModel to build a model pragramatically.

However I get some undefined reference errors to some mjCModel member functions.

After some investigation, it seems that these symbols are indeed missing from the distributed shared libs, at least on linux x64.

On the downloaded .so, nm gives me:

> nm --demangle libmujoco.so|grep mjCModel::        
00000000001d63a0 t mjCModel::AddExclude()
00000000001d7bc0 t mjCModel::FindObject(mjtObj_, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
00000000001d6a70 t mjCModel::NumObjects(mjtObj_)
00000000001d6540 t mjCModel::AddEquality(mjCDef*)
00000000001da1e0 t mjCModel::FuseReindex(mjCBody*)
00000000001d99e0 t mjCModel::IndexAssets()
00000000001d6f10 t mjCModel::AddDef(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, int)
00000000001d6880 t mjCModel::AddKey()
00000000001d5e00 t mjCModel::AddMesh(mjCDef*)
00000000001d5fa0 t mjCModel::AddSkin()
00000000001db070 t mjCModel::Compile(mjVFS_ const*)
00000000001d6dc0 t mjCModel::FindDef(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
00000000001eca30 t mjCModel::CopyBack(mjModel_ const*)
00000000001d6200 t mjCModel::AddHField()
00000000001d66e0 t mjCModel::AddTendon(mjCDef*)
00000000001d6c10 t mjCModel::GetObject(mjtObj_, int)
00000000001d90e0 t mjCModel::MakeLists(mjCBody*)
00000000001d4410 t mjCModel::mjCModel()
00000000001d5000 t mjCModel::~mjCModel()

But if I compile the mujoco myself and run nm on the resulting .so I get this instead:

> nm --demangle lib/libmujoco.so|grep mjCModel::
0000000000171130 t mjCModel::AddExclude()
0000000000171100 t mjCModel::AddExclude() [clone .cold]
0000000000171f10 t mjCModel::AddNumeric()
0000000000171ee0 t mjCModel::AddNumeric() [clone .cold]
00000000001708e0 t mjCModel::AddTexture()
00000000001708b0 t mjCModel::AddTexture() [clone .cold]
000000000015bb40 t mjCModel::FindObject(mjtObj_, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
0000000000159f30 t mjCModel::FindObject(mjtObj_, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) [clone .constprop.1]
000000000016e7d0 t mjCModel::FuseStatic()
000000000016e774 t mjCModel::FuseStatic() [clone .cold]
000000000015ba50 t mjCModel::IsCompiled()
000000000015b4c0 t mjCModel::NumObjects(mjtObj_)
0000000000171990 t mjCModel::AddActuator(mjCDef*)
0000000000171960 t mjCModel::AddActuator(mjCDef*) [clone .cold]
00000000001713d0 t mjCModel::AddEquality(mjCDef*)
00000000001713a0 t mjCModel::AddEquality(mjCDef*) [clone .cold]
0000000000170b80 t mjCModel::AddMaterial(mjCDef*)
0000000000170b50 t mjCModel::AddMaterial(mjCDef*) [clone .cold]
000000000016c470 t mjCModel::CopyObjects(mjModel_*)
000000000016ba20 t mjCModel::FuseReindex(mjCBody*)
000000000015d580 t mjCModel::IndexAssets()
000000000015d2d2 t mjCModel::IndexAssets() [clone .cold]
0000000000161e80 t mjCModel::LengthRange(mjModel_*, mjData_*)
0000000000161d4a t mjCModel::LengthRange(mjModel_*, mjData_*) [clone .cold]
000000000015e660 t mjCModel::SetDefaultNames()
000000000015e4d4 t mjCModel::SetDefaultNames() [clone .cold]
0000000000161920 t mjCModel::AutoSpringDamper(mjModel_*)
000000000015a0a0 t mjCModel::Clear()
00000000001688f0 t mjCModel::AddDef(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)
00000000001688d0 t mjCModel::AddDef(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int) [clone .cold]
00000000001726d0 t mjCModel::AddKey()
00000000001726a0 t mjCModel::AddKey() [clone .cold]
00000000001700e0 t mjCModel::AddMesh(mjCDef*)
00000000001700b0 t mjCModel::AddMesh(mjCDef*) [clone .cold]
0000000000170e60 t mjCModel::AddPair(mjCDef*)
0000000000170e30 t mjCModel::AddPair(mjCDef*) [clone .cold]
00000000001703b0 t mjCModel::AddSkin()
0000000000170380 t mjCModel::AddSkin() [clone .cold]
00000000001721b0 t mjCModel::AddText()
0000000000172180 t mjCModel::AddText() [clone .cold]
0000000000174800 t mjCModel::Compile(mjVFS_ const*)
0000000000173102 t mjCModel::Compile(mjVFS_ const*) [clone .cold]
000000000015bac0 t mjCModel::FindDef(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
0000000000172440 t mjCModel::AddTuple()
0000000000172410 t mjCModel::AddTuple() [clone .cold]
0000000000166cd0 t mjCModel::CopyBack(mjModel_ const*)
0000000000163790 t mjCModel::CopyTree(mjModel_*)
0000000000163648 t mjCModel::CopyTree(mjModel_*) [clone .cold]
000000000015ba60 t mjCModel::GetError()
000000000015bab0 t mjCModel::GetWorld()
000000000015f8f0 t mjCModel::SetSizes()
000000000015f8a2 t mjCModel::SetSizes() [clone .cold]
0000000000170640 t mjCModel::AddHField()
0000000000170610 t mjCModel::AddHField() [clone .cold]
0000000000171c70 t mjCModel::AddSensor()
0000000000171c40 t mjCModel::AddSensor() [clone .cold]
00000000001716b0 t mjCModel::AddTendon(mjCDef*)
0000000000171680 t mjCModel::AddTendon(mjCDef*) [clone .cold]
0000000000162ae0 t mjCModel::CopyNames(mjModel_*)
0000000000162a8a t mjCModel::CopyNames(mjModel_*) [clone .cold]
000000000015b6e0 t mjCModel::GetObject(mjtObj_, int)
000000000016bf60 t mjCModel::MakeLists(mjCBody*)
000000000016f900 t mjCModel::mjCModel()
000000000016f900 t mjCModel::mjCModel()
000000000016f5e0 t mjCModel::mjCModel() [clone .cold]
000000000015a260 t mjCModel::~mjCModel()
000000000015a260 t mjCModel::~mjCModel()

BenjaminNavarro avatar Jul 18 '22 15:07 BenjaminNavarro

We should've mentioned it in the previous issue, but this isn't a bug. We deliberately avoid exposing a C++ ABI in our precompiled library.

If you want to experiment with mjCModel, you'll need to build MuJoCo from source alongside your own code. I'll rephrase the issue title, but leave it open so that you can ask more questions about this if necessary.

saran-t avatar Jul 18 '22 15:07 saran-t

Ok thanks for the explanation.

But there is one more problem though, you need to add MJAPI to classes in users otherwise we can't link to them from the outside

BenjaminNavarro avatar Jul 19 '22 08:07 BenjaminNavarro

That's true, but we are hesitant to export symbols that might change/disappear in the future. If you don't mind adding MJAPI in your codebase for now, that would be easiest. It should be trivial to to reconcile that change with future updates, at least until we start touching the compiler. Let us know if that solution doesn't work for you for some reason.

yuvaltassa avatar Jul 21 '22 13:07 yuvaltassa

A possibly better alternative is to statically link MuJoCo into your program, and build everything without -fvisibility=hidden.

saran-t avatar Jul 21 '22 13:07 saran-t

you'll need to build MuJoCo from source alongside your own code.

@saran-t Does this mean the CMakeLists.txt in the mujoco repo should be modified to include other packages for our / my own personal projects? I've been trying to include the mujoco library in my C++ project with my own CMakeLists.txt. Bringing mujoco into my project is not doable? I'm just trying to get a clear picture of what to do.
I'm somewhat new to cmake and I will need to compile my single, personal C++ file over and over again as fast as possible, like how it is possible with the make command in the sample file of the repo.
I've been asking a few question about this here and made a little progress I commented and closed a few with but I still have not gotten it to work.
I want to include the mujoco library in my C++ script build with CMakeLists.txt. Other libraries are not this complicated. I can find_package Torch and other libraries no problem and use everything in the library with my C++. Not so with MuJoCo.

MotorCityCobra avatar Jul 28 '22 02:07 MotorCityCobra

MJAPI

@BenjaminNavarro @yuvaltassa What is this?
How can I use this mujoco library in my project?

MotorCityCobra avatar Jul 28 '22 13:07 MotorCityCobra

@MotorCityCobra this is only about trying to depend on MuJoCo's currently private, internal API, rather than functions that are meant to be user-facing.

To answer your question, to depend on MuJoCo in CMake, you should cmake --install MuJoCo, then from your own project it's sufficient to just find_package(mujoco), then target_link_libraries(your_target mujoco::mujoco).

saran-t avatar Jul 28 '22 14:07 saran-t

Maybe you could add a CMake option to export the private API or not? Default would be off of course to keep the current behavior but it would make it easy to just build and use MuJoCo as usual

BenjaminNavarro avatar Jul 30 '22 19:07 BenjaminNavarro