Compile-time size assertions for MuJoCo basic types
PiperOrigin-RevId: 919107499 Change-Id: I07fcba4f33c77a2a1e68528dba6d399af94d0220
This commit is contained in:
committed by
Copybara-Service
parent
585be6cee5
commit
15d27b363f
@@ -108,6 +108,7 @@ include(MujocoMacOS)
|
||||
include(MujocoDependencies)
|
||||
|
||||
set(MUJOCO_HEADERS
|
||||
include/mujoco/mjassert.h
|
||||
include/mujoco/mjdata.h
|
||||
include/mujoco/mjexport.h
|
||||
include/mujoco/mjmacro.h
|
||||
|
||||
@@ -80,6 +80,12 @@ General
|
||||
- MJX: Removed the deprecated ``nconmax`` argument from ``mjx.make_data`` and ``mjx.put_data`` in favor of
|
||||
``naconmax``.
|
||||
|
||||
- Maybe-breaking: Added `mjassert.h
|
||||
<https://github.com/google-deepmind/mujoco/blob/main/include/mujoco/mjassert.h>`__, a new header containing
|
||||
compile-time assertions that verify the sizes of MuJoCo's public types for ABI stability. This is a first step
|
||||
towards replacing ``int`` with strongly-typed enums in the public API. If these assertions fail on your compiler or
|
||||
platform, please report the issue on GitHub.
|
||||
|
||||
Version 3.8.1 (May 11, 2026)
|
||||
----------------------------
|
||||
|
||||
|
||||
@@ -184,6 +184,8 @@ links below, to make this documentation self-contained.
|
||||
code.
|
||||
`mjsan.h <https://github.com/google-deepmind/mujoco/blob/main/include/mujoco/mjsan.h>`__
|
||||
Definitions required when building with sanitizer instrumentation.
|
||||
`mjassert.h <https://github.com/google-deepmind/mujoco/blob/main/include/mujoco/mjassert.h>`__
|
||||
Compile-time size assertions verifying MuJoCo ABI stability across C and C++ compilers.
|
||||
|
||||
.. _inVersion:
|
||||
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
// Copyright 2026 DeepMind Technologies Limited
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef MUJOCO_MJASSERT_H_
|
||||
#define MUJOCO_MJASSERT_H_
|
||||
|
||||
#include <mujoco/mjdata.h>
|
||||
#include <mujoco/mjmodel.h>
|
||||
#include <mujoco/mjplugin.h>
|
||||
#include <mujoco/mjrender.h>
|
||||
#include <mujoco/mjspec.h>
|
||||
#include <mujoco/mjthread.h>
|
||||
#include <mujoco/mjtype.h>
|
||||
#include <mujoco/mjui.h>
|
||||
#include <mujoco/mjvisualize.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#define MJ_ASSERT_SIZE(type, size) \
|
||||
static_assert(sizeof(type) == (size), #type " must be " #size " bytes for MuJoCo ABI stability")
|
||||
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
|
||||
#define MJ_ASSERT_SIZE(type, size) \
|
||||
_Static_assert(sizeof(type) == (size), #type " must be " #size " bytes for MuJoCo ABI stability")
|
||||
#else
|
||||
#define MJ_ASSERT_SIZE(type, size) \
|
||||
typedef char mj_assert_##type[sizeof(type) == (size) ? 1 : -1]
|
||||
#endif
|
||||
|
||||
// mjtnum.h
|
||||
MJ_ASSERT_SIZE(mjtByte, 1);
|
||||
MJ_ASSERT_SIZE(mjtSize, 8);
|
||||
#if !defined(mjUSESINGLE)
|
||||
MJ_ASSERT_SIZE(mjtNum, 8);
|
||||
#else
|
||||
MJ_ASSERT_SIZE(mjtNum, 4);
|
||||
#endif
|
||||
|
||||
// mjmodel.h
|
||||
MJ_ASSERT_SIZE(mjtDisableBit, 4);
|
||||
MJ_ASSERT_SIZE(mjtEnableBit, 4);
|
||||
MJ_ASSERT_SIZE(mjtJoint, 4);
|
||||
MJ_ASSERT_SIZE(mjtGeom, 4);
|
||||
MJ_ASSERT_SIZE(mjtProjection, 4);
|
||||
MJ_ASSERT_SIZE(mjtCamLight, 4);
|
||||
MJ_ASSERT_SIZE(mjtLightType, 4);
|
||||
MJ_ASSERT_SIZE(mjtTexture, 4);
|
||||
MJ_ASSERT_SIZE(mjtTextureRole, 4);
|
||||
MJ_ASSERT_SIZE(mjtColorSpace, 4);
|
||||
MJ_ASSERT_SIZE(mjtIntegrator, 4);
|
||||
MJ_ASSERT_SIZE(mjtCone, 4);
|
||||
MJ_ASSERT_SIZE(mjtJacobian, 4);
|
||||
MJ_ASSERT_SIZE(mjtSolver, 4);
|
||||
MJ_ASSERT_SIZE(mjtEq, 4);
|
||||
MJ_ASSERT_SIZE(mjtWrap, 4);
|
||||
MJ_ASSERT_SIZE(mjtTrn, 4);
|
||||
MJ_ASSERT_SIZE(mjtDyn, 4);
|
||||
MJ_ASSERT_SIZE(mjtGain, 4);
|
||||
MJ_ASSERT_SIZE(mjtBias, 4);
|
||||
MJ_ASSERT_SIZE(mjtObj, 4);
|
||||
MJ_ASSERT_SIZE(mjtSensor, 4);
|
||||
MJ_ASSERT_SIZE(mjtStage, 4);
|
||||
MJ_ASSERT_SIZE(mjtDataType, 4);
|
||||
MJ_ASSERT_SIZE(mjtConDataField, 4);
|
||||
MJ_ASSERT_SIZE(mjtRayDataField, 4);
|
||||
MJ_ASSERT_SIZE(mjtCamOutBit, 4);
|
||||
MJ_ASSERT_SIZE(mjtSameFrame, 4);
|
||||
MJ_ASSERT_SIZE(mjtSleepPolicy, 4);
|
||||
MJ_ASSERT_SIZE(mjtLRMode, 4);
|
||||
MJ_ASSERT_SIZE(mjtFlexSelf, 4);
|
||||
MJ_ASSERT_SIZE(mjtSDFType, 4);
|
||||
|
||||
// mjdata.h
|
||||
MJ_ASSERT_SIZE(mjtState, 4);
|
||||
MJ_ASSERT_SIZE(mjtConstraint, 4);
|
||||
MJ_ASSERT_SIZE(mjtConstraintState, 4);
|
||||
MJ_ASSERT_SIZE(mjtWarning, 4);
|
||||
MJ_ASSERT_SIZE(mjtTimer, 4);
|
||||
MJ_ASSERT_SIZE(mjtSleepState, 4);
|
||||
|
||||
// mjspec.h
|
||||
MJ_ASSERT_SIZE(mjtGeomInertia, 4);
|
||||
MJ_ASSERT_SIZE(mjtMeshInertia, 4);
|
||||
MJ_ASSERT_SIZE(mjtMeshBuiltin, 4);
|
||||
MJ_ASSERT_SIZE(mjtBuiltin, 4);
|
||||
MJ_ASSERT_SIZE(mjtMark, 4);
|
||||
MJ_ASSERT_SIZE(mjtLimited, 4);
|
||||
MJ_ASSERT_SIZE(mjtAlignFree, 4);
|
||||
MJ_ASSERT_SIZE(mjtInertiaFromGeom, 4);
|
||||
MJ_ASSERT_SIZE(mjtOrientation, 4);
|
||||
|
||||
// mjvisualize.h
|
||||
MJ_ASSERT_SIZE(mjtCatBit, 4);
|
||||
MJ_ASSERT_SIZE(mjtMouse, 4);
|
||||
MJ_ASSERT_SIZE(mjtPertBit, 4);
|
||||
MJ_ASSERT_SIZE(mjtCamera, 4);
|
||||
MJ_ASSERT_SIZE(mjtLabel, 4);
|
||||
MJ_ASSERT_SIZE(mjtFrame, 4);
|
||||
MJ_ASSERT_SIZE(mjtVisFlag, 4);
|
||||
MJ_ASSERT_SIZE(mjtRndFlag, 4);
|
||||
MJ_ASSERT_SIZE(mjtStereo, 4);
|
||||
|
||||
// mjrender.h
|
||||
MJ_ASSERT_SIZE(mjtGridPos, 4);
|
||||
MJ_ASSERT_SIZE(mjtFramebuffer, 4);
|
||||
MJ_ASSERT_SIZE(mjtDepthMap, 4);
|
||||
MJ_ASSERT_SIZE(mjtFontScale, 4);
|
||||
MJ_ASSERT_SIZE(mjtFont, 4);
|
||||
|
||||
// mjui.h
|
||||
MJ_ASSERT_SIZE(mjtButton, 4);
|
||||
MJ_ASSERT_SIZE(mjtEvent, 4);
|
||||
MJ_ASSERT_SIZE(mjtItem, 4);
|
||||
MJ_ASSERT_SIZE(mjtSection, 4);
|
||||
|
||||
// mjthread.h
|
||||
MJ_ASSERT_SIZE(mjtTaskStatus, 4);
|
||||
|
||||
// mjplugin.h
|
||||
MJ_ASSERT_SIZE(mjtPluginCapabilityBit, 4);
|
||||
|
||||
#undef MJ_ASSERT_SIZE
|
||||
|
||||
#endif // MUJOCO_MJASSERT_H_
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <mujoco/mjtype.h>
|
||||
#include <mujoco/mjui.h>
|
||||
#include <mujoco/mjvisualize.h>
|
||||
#include <mujoco/mjassert.h>
|
||||
|
||||
// this is a C-API
|
||||
#ifdef __cplusplus
|
||||
|
||||
+1
-54
@@ -21,12 +21,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <mujoco/mjdata.h>
|
||||
#include <mujoco/mjmodel.h>
|
||||
#include <mujoco/mjrender.h>
|
||||
#include <mujoco/mjtype.h>
|
||||
#include <mujoco/mjui.h>
|
||||
#include <mujoco/mjvisualize.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include <mujoco/mjxmacro.h>
|
||||
#include "test/fixture.h"
|
||||
|
||||
@@ -58,59 +53,11 @@ void CheckAddressOrdering(
|
||||
|
||||
using HeaderTest = MujocoTest;
|
||||
|
||||
TEST_F(HeaderTest, IntsHave4Bytes) {
|
||||
EXPECT_EQ(4, sizeof(int));
|
||||
}
|
||||
|
||||
TEST_F(HeaderTest, IntsHaveAtLeast31Bits) {
|
||||
int shift_left_30 = 1 << 30;
|
||||
EXPECT_GT(shift_left_30, 0);
|
||||
}
|
||||
|
||||
TEST_F(HeaderTest, EnumsAreInts) {
|
||||
EXPECT_EQ(sizeof(mjtDisableBit), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtEnableBit), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtJoint), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtGeom), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtCamLight), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtTexture), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtIntegrator), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtCone), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtJacobian), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtSolver), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtEq), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtWrap), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtTrn), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtDyn), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtGain), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtBias), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtObj), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtConstraint), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtConstraintState), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtSensor), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtStage), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtDataType), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtLRMode), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtWarning), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtTimer), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtGridPos), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtFramebuffer), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtFontScale), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtFont), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtButton), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtEvent), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtItem), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtCatBit), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtMouse), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtPertBit), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtCamera), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtLabel), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtFrame), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtVisFlag), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtRndFlag), sizeof(int));
|
||||
EXPECT_EQ(sizeof(mjtStereo), sizeof(int));
|
||||
}
|
||||
|
||||
TEST_F(HeaderTest, MjOptionFields) {
|
||||
mjOption o;
|
||||
std::vector<std::pair<const void*, const char*>> fields;
|
||||
|
||||
@@ -24,6 +24,7 @@ public static class MujocoLib {
|
||||
|
||||
// ----------------------------------Constants----------------------------------
|
||||
|
||||
public const bool THIRD_PARTY_MUJOCO_MJASSERT_H_ = true;
|
||||
public const bool THIRD_PARTY_MUJOCO_MJDATA_H_ = true;
|
||||
public const bool THIRD_PARTY_MUJOCO_MJEXPORT_H_ = true;
|
||||
public const bool MUJOCO_HELPER_DLL_LOCAL = true;
|
||||
|
||||
Reference in New Issue
Block a user