Packages

MuJoCo physics from Elixir: models, data, the state and every field of them, through a compile-time generated Fine NIF. PyTorch-free, Python-free.

Current section

Files

Jump to
ex_mujoco Makefile.win
Raw

Makefile.win

# The NIF, on Windows, with MSVC and nmake — the toolchain an Elixir install on
# Windows already needs, and the one Fine's own example uses.
#
# `mix` runs this with MIX_APP_PATH, ERTS_INCLUDE_DIR and FINE_INCLUDE_DIR set,
# and with MUJOCO_DIR pointing at a MuJoCo prepared by
# scripts/prepare_mujoco.exs. The MuJoCo release ships `lib\mujoco.lib` to link
# against and `bin\mujoco.dll` to load. Both sit together in priv, which is not
# enough: Windows resolves a library's imports against the modules already in
# the process, and will not look beside the importing library. `preload.cpp`
# loads MuJoCo first, from a library of its own that imports nothing.

PRIV_DIR=$(MIX_APP_PATH)\priv
NIF_PATH=$(PRIV_DIR)\ex_mujoco_nif.dll
PRELOAD_PATH=$(PRIV_DIR)\ex_mujoco_preload.dll

C_SRC=$(EX_MUJOCO_PROJECT_DIR)\c_src
SCRIPT=$(EX_MUJOCO_PROJECT_DIR)\scripts\prepare_mujoco.exs

# `/wd4100` is MSVC for `-Wno-unused-parameter`: a NIF that does not need
# `env` is the common case, and the parameter is what Fine calls through.
# `/wd4611` is the `setjmp` / destructor warning, and it is the one caveat this
# design owns: MuJoCo's fatal error is caught by a longjmp, and the lambda the
# call runs in owns nothing that needs unwinding. `c_src/mj_call.hpp` says so.
CPPFLAGS=/LD /std:c++17 /W4 /WX /EHsc /O2 /wd4100 /wd4611
CPPFLAGS=$(CPPFLAGS) /I"$(ERTS_INCLUDE_DIR)" /I"$(FINE_INCLUDE_DIR)"
CPPFLAGS=$(CPPFLAGS) /I"$(MUJOCO_DIR)\include" /I"$(C_SRC)"

LDFLAGS=/link /LIBPATH:"$(MUJOCO_DIR)\lib" mujoco.lib

SOURCES=$(C_SRC)\ex_mujoco_nif.cpp
PRELOAD_SOURCES=$(C_SRC)\preload.cpp
FINE_HEADERS=$(FINE_INCLUDE_DIR)\*.hpp

all: mujoco $(NIF_PATH) $(PRELOAD_PATH)

mujoco:
	@ elixir "$(SCRIPT)" --ensure --priv "$(PRIV_DIR)"

# `/Fe` is a compiler option and has to come before `/link`; after it, `cl` hands
# it to the linker, which does not recognise it, warns, and writes the DLL under
# its default name instead of ours.
$(NIF_PATH): $(SOURCES) $(FINE_HEADERS)
	@ if not exist "$(PRIV_DIR)" mkdir "$(PRIV_DIR)"
	cl $(CPPFLAGS) $(SOURCES) /Fe"$(NIF_PATH)" $(LDFLAGS)

# No `mujoco.lib`: this one is built to load MuJoCo, not to call it.
$(PRELOAD_PATH): $(PRELOAD_SOURCES) $(FINE_HEADERS)
	@ if not exist "$(PRIV_DIR)" mkdir "$(PRIV_DIR)"
	cl $(CPPFLAGS) $(PRELOAD_SOURCES) /Fe"$(PRELOAD_PATH)" /link

clean:
	@ if exist "$(NIF_PATH)" del /q "$(NIF_PATH)"
	@ if exist "$(PRELOAD_PATH)" del /q "$(PRELOAD_PATH)"