Error adding Bullet to generated modules

Hi all,

This may seem like a small problem, but I haven’t been able to figure out how to successfully include the Bullet library into the .pyd module I’m generating. I’m using the module builder (that makes it a breeze to use interrogate) to generate these modules and it already seems to have a CMakeLists.txt that should automatically do all the linking for me. Is there something I need to manually do? Here is the error I’m getting:

c:\panda3d-1.10.14-x64\include\bullet_includes.h(19): fatal error C1083: Cannot open include file: 'btBulletDynamicsCommon.h': No such file or directory (compiling source file C:\Panda3D-1.10.14-x64\P3DModuleBuilder-master\P3DModuleBuilder-master\source\interrogate_wrapper.cpp) [C:\Panda3D-1.10.14-x64\P3DModuleBuilder-master\P3DModuleBuilder-master\win_amd64_panda1.10.14_py37_vc140\genModule.vcxproj]
Traceback (most recent call last):
  File "build.py", line 52, in <module>
    run_cmake_build(config, args)
  File "C:\Panda3D-1.10.14-x64\P3DModuleBuilder-master\P3DModuleBuilder-master\scripts\setup.py", line 174, in run_cmake_build
    try_execute("cmake", "--build", ".", "--config", configuration, "--", core_option)
  File "C:\Panda3D-1.10.14-x64\P3DModuleBuilder-master\P3DModuleBuilder-master\scripts\common.py", line 271, in try_execute
    raise Exception("Process had non-zero returncode:", process.returncode)
Exception: ('Process had non-zero returncode:', 1)

So what would the step-by-step process be to ensure that one can generate modules that use Bullet without encountering such errors? (And yes, I did download the thirdparty tools, I’m just not sure how to install bullet from them manually).

UPDATE
So I manually moved a bunch of files and folders to this directory: c:\panda3d-1.10.14-x64\include and it did clear the prior error. I moved these files and folders from the third-party package bullet folder: BulletCollision,BulletDynamics,BulletSoftBody,LinerMath and btBulletCollisionCommon.h and btBulletDynamicsCommon.h. However new errors emerge:

Creating library C:/Panda3D-1.10.14-x64/P3DModuleBuilder-master/P3DModuleBuilder-master/win_amd64_panda1.10.14_py37_vc140/RelWithDebInfo/genModule.lib and object C:/Panda3D-1.10.14-x64/P3DModuleBuilder-master/P3DModuleBuilder-master/win_amd64_panda1.10.14_py37_vc140/RelWithDebInfo/genModule.exp
interrogate_wrapper.obj : error LNK2001: unresolved external symbol "public: virtual class TypeHandle __cdecl BulletTriangleMesh::get_type(void)const " (?get_type@BulletTriangleMesh@@UEBA?AVTypeHandle@@XZ) [C:\Panda3D-1.10.14-x64\P3DModuleBuilder-master\P3DModuleBuilder-master\win_amd64_panda1.10.14_py37_vc140\genModule.vcxproj]
interrogate_wrapper.obj : error LNK2001: unresolved external symbol "public: virtual class TypeHandle __cdecl BulletTriangleMesh::force_init_type(void)" (?force_init_type@BulletTriangleMesh@@UEAA?AVTypeHandle@@XZ) [C:\Panda3D-1.10.14-x64\P3DModuleBuilder-master\P3DModuleBuilder-master\win_amd64_panda1.10.14_py37_vc140\genModule.vcxproj]
interrogate_wrapper.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl BulletTriangleMesh::output(class std::basic_ostream<char,struct std::char_traits<char> > &)const " (?output@BulletTriangleMesh@@UEBAXAEAV?$basic_ostream@DU?$char_traits@D@std@@@std@@@Z) [C:\Panda3D-1.10.14-x64\P3DModuleBuilder-master\P3DModuleBuilder-master\win_amd64_panda1.10.14_py37_vc140\genModule.vcxproj]
interrogate_wrapper.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl BulletTriangleMesh::write(class std::basic_ostream<char,struct std::char_traits<char> > &,int)const " (?write@BulletTriangleMesh@@UEBAXAEAV?$basic_ostream@DU?$char_traits@D@std@@@std@@H@Z) [C:\Panda3D-1.10.14-x64\P3DModuleBuilder-master\P3DModuleBuilder-master\win_amd64_panda1.10.14_py37_vc140\genModule.vcxproj]

How would I resolve these?

Thanks in advance.

So, it seems all I had to do was set this variable to True:

set(HAVE_LIB_BULLET 1)

This is how the new full CMakeLists.txt file looks now:


set(PROJECT_NAME CACHE STRING "Module")

cmake_minimum_required (VERSION 2.6)
project (${PROJECT_NAME})

# Project configuration
set(CMAKE_BUILD_TYPE "Release")

# Libraries and options set by the module builder
set(HAVE_LIB_EIGEN CACHE BOOL TRUE)
#set(HAVE_LIB_BULLET CACHE BOOL FALSE)
set(HAVE_LIB_BULLET 1)
set(HAVE_LIB_FREETYPE CACHE BOOL FALSE)
set(OPTIMIZE CACHE STRING "3")
set(IGATE_VERBOSE CACHE STRING "0")
set(INTERROGATE_LIB CACHE STRING "p3interrogatedb")
set(PYTHON_EXECUTABLE CACHE STRING "python")
set(THIRDPARTY_WIN_DIR CACHE STRING "")


# --- User controllable variables ---

# Whether to enable SSE. This only has effect on 32 bit.
# Should probably match the setting for the Panda3D build
set(ENABLE_SSE2 CACHE BOOL 1)
set(TOUCHINPUT_ENABLED CACHE BOOL 0)


# --- End of user variables --

# Reset cmake flags - we user our own
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "")
set(CMAKE_CXX_FLAGS_RELEASE "")
set(CMAKE_CXX_FLAGS_MINSIZEREL "")


set(LIBRARIES "")

# Windows - 32 and 64 bit
if (WIN32)
  if (CMAKE_CL_64 STREQUAL "1")
    message(STATUS "Bitness: 64 bit ('${CMAKE_CL_64}')")
    set(IS_64_BIT TRUE)
    set(IS_32_BIT FALSE)
  else()
    message(STATUS "Bitness: 32 bit ('${CMAKE_CL_64}')")
    set(IS_64_BIT TRUE)
    set(IS_32_BIT FALSE)
  endif()

  set(PYTHONVER CACHE STRING "27")

  # Find panda path
  execute_process(
    COMMAND "${PYTHON_EXECUTABLE}" "-B" "scripts/common.py" "--print-sdk-path"
    OUTPUT_VARIABLE WIN_PANDA_PATH
    WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
  message(STATUS "Detected panda3d installation: ${WIN_PANDA_PATH}")


  # Determine bitness
  set(THIRDPARTY_SUFFIX "-x64")
  if (IS_32_BIT)
    set(THIRDPARTY_SUFFIX "")
  endif()



  # Find visual studio version
  if (MSVC10)
    set(MSVC_VERSION_SHORT "vc10")
  elseif (MSVC12)
    set(MSVC_VERSION_SHORT "vc12")
  elseif(MSVC14)
    set(MSVC_VERSION_SHORT "vc14")
  else()
    message(WARNING "Unable to determine visual studio version, assuming Visual Studio 2010")
    set(MSVC_VERSION_SHORT "vc10")
  endif()
  message(STATUS "Detected visual studio version: ${MSVC_VERSION_SHORT}")


  set(THIRDPARTY_DIR ${THIRDPARTY_WIN_DIR})
  message(STATUS "Detected thirdparty directory: ${THIRDPARTY_DIR}")


  # Find lib and include directory
  set(PANDA_LIBRARY_DIRS "${WIN_PANDA_PATH}/lib")
  set(PANDA_INCLUDE_DIR "${WIN_PANDA_PATH}/include")

  if (NOT (EXISTS "${PANDA_LIBRARY_DIRS}"))
    message(WARNING "Panda3D library directory does not exist! Expected it at: ${PANDA_LIBRARY_DIRS}")
  endif()

  set(PYTHON_LIBRARIES "${WIN_PANDA_PATH}/python/libs/python${PYTHONVER}.lib")
  set(PYTHON_INCLUDE_DIRS "${WIN_PANDA_PATH}/python/include")

  # [LIB] Bullet
  
  if(HAVE_LIB_BULLET)
  
	if (NOT (EXISTS "${PANDA_INCLUDE_DIR}/bullet_includes.h"))
      message(FATAL_ERROR "This module requires the bullet library, but your Panda3D Build was copmiled without bullet support! Use --use-bullet when compiling.")
    endif()

    include_directories("${THIRDPARTY_DIR}/bullet/include/")
    link_directories("${THIRDPARTY_DIR}/bullet/lib/")

    if(EXISTS "${THIRDPARTY_DIR}/bullet/lib/LinearMath_x64.lib")
      set(LIBRARIES "${LIBRARIES};LinearMath_x64;BulletCollision_x64;BulletDynamics_x64;BulletSoftBody_x64")
    else()
      set(LIBRARIES "${LIBRARIES};LinearMath;BulletCollision;BulletDynamics;BulletSoftBody")
    endif()
  endif()

  # [LIB] Eigen 3
  if (HAVE_LIB_EIGEN)
    include_directories("${THIRDPARTY_DIR}/eigen/include")

    # Eigen build flags (sync with Panda)
    if (HAVE_LIB_EIGEN)
      add_definitions("/DEIGEN_MPL2_ONLY=")
      if ((OPTIMIZE STREQUAL "3") OR (OPTIMIZE STREQUAL "4"))
        add_definitions("/DEIGEN_NO_DEBUG=")
        if (MSVC)
          # Squeeze out a bit more performance on MSVC builds...
          # Only do this if EIGEN_NO_DEBUG is also set, otherwise it
          # will turn them into runtime assertions.
          add_definitions("/DEIGEN_NO_STATIC_ASSERT=")
        endif()
      endif()
    endif()
  endif()

  # [LIB] Freetype
  if (HAVE_LIB_FREETYPE)
    include_directories("${THIRDPARTY_DIR}/freetype/include")
    include_directories("${THIRDPARTY_DIR}/freetype/include/freetype2")
    link_directories("${THIRDPARTY_DIR}/freetype/lib")
    set(LIBRARIES "${LIBRARIES};freetype")
  endif()

  # Check if all supplied files exist
  set(CHECK_PATHS ${PANDA_LIBRARY_DIRS} ${PANDA_INCLUDE_DIR} ${PYTHON_LIBRARIES} ${PYTHON_INCLUDE_DIRS})
  foreach(PATH ${CHECK_PATHS})
    if(NOT (EXISTS "${PATH}"))
        message(FATAL_ERROR "The supplied path '${PATH}' could not be found!")
    endif()
  endforeach()

  # Link panda libraries
  set(PANDA_LIBRARIES "libp3framework;libpanda;libpandaexpress;libp3dtool;libp3dtoolconfig;libp3direct;${INTERROGATE_LIB}")
  if(HAVE_LIB_BULLET)
    set(PANDA_LIBRARIES "libpandabullet;${PANDA_LIBRARIES}")
  endif()
  link_directories("${PANDA_LIBRARY_DIRS}")

else()
  set(PYTHONVERDOT CACHE STRING "2.7")
  set(Python_ADDITIONAL_VERSIONS ${PYTHONVERDOT})
  find_package(PythonLibs REQUIRED)

  # [LIB] Bullet
  if (HAVE_LIB_BULLET)
    find_package(Bullet REQUIRED)
    include_directories(${BULLET_INCLUDE_DIRS})
    set(LIBRARIES "${LIBRARIES};${BULLET_LIBRARIES}")
  endif()

  # [LIB] Eigen 3
  if (HAVE_LIB_EIGEN)
    if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
      include_directories(BEFORE "/usr/local/include/eigen3/")
    else()
      include_directories(BEFORE "/usr/include/eigen3/")
    endif()

    # Eigen build flags (sync with Panda)
    if (HAVE_LIB_EIGEN)
      add_definitions("/DEIGEN_MPL2_ONLY=")
      if ((OPTIMIZE STREQUAL "3") OR (OPTIMIZE STREQUAL "4"))
        add_definitions("/DEIGEN_NO_DEBUG=")
      endif()
    endif()
  endif()

  # [LIB] Freetype
  if(HAVE_LIB_FREETYPE)
    find_package(Freetype REQUIRED)
    include_directories(${FREETYPE_INCLUDE_DIRS})
    set(LIBRARIES "${LIBRARIES};${FREETYPE_LIBRARIES}")
  endif()

  # Locate the Panda3D headers
  find_path(PANDA_INCLUDE_DIR dtoolbase.h PATH_SUFFIXES panda3d)

  # Locate the Panda3D libraries
  set(REQ_LIBRARIES p3framework panda pandaexpress p3dtool p3dtoolconfig p3direct ${INTERROGATE_LIB})
  if(HAVE_LIB_BULLET)
    set(REQ_LIBRARIES pandabullet ${REQ_LIBRARIES})
  endif()

  set(PANDA_LIBRARIES "")
  foreach (lib ${REQ_LIBRARIES})
    find_library(PANDA_LIBRARY_${lib} ${lib} PATH_SUFFIXES panda3d)
    set(PANDA_LIBRARIES "${PANDA_LIBRARIES};${PANDA_LIBRARY_${lib}}")
  endforeach()

  find_package_handle_standard_args(Panda DEFAULT_MSG
                                    PANDA_LIBRARIES PANDA_INCLUDE_DIR)

  if (NOT EXISTS ${PANDA_INCLUDE_DIR})
    # Okay, the standard package handling failed. Try finding a local panda3d installation

    # Find panda path
    execute_process(
      COMMAND "${PYTHON_EXECUTABLE}" "-B" "scripts/common.py" "--print-sdk-path"
      OUTPUT_VARIABLE LOCAL_PANDA_PATH
      WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})

    if (NOT EXISTS "${LOCAL_PANDA_PATH}/include")
      message(FATAL_ERROR "Could not find system wide panda3d headers, and no local installation was found!")
    endif()

    set(PANDA_INCLUDE_DIR "${LOCAL_PANDA_PATH}/include")

    set(PANDA_LIBRARIES "")
    foreach(lib ${REQ_LIBRARIES})
      find_library(PANDA_LIBRARY_${lib} ${lib} PATHS "${LOCAL_PANDA_PATH}/lib/")
      set(PANDA_LIBRARIES "${PANDA_LIBRARIES};${PANDA_LIBRARY_${lib}}")
    endforeach()

  endif()

endif()

# Find core.so/core.pyd path
execute_process(
  COMMAND "${PYTHON_EXECUTABLE}" "-B" "scripts/common.py" "--print-core-path"
  OUTPUT_VARIABLE PANDA_CORE_PATH
  WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})


# Link panda includes / libraries
include_directories("${PANDA_INCLUDE_DIR}")
include_directories("${PYTHON_INCLUDE_DIRS}")

# Run interrogate over the files
execute_process(
    COMMAND "${PYTHON_EXECUTABLE}" "-B" "scripts/interrogate.py" "${PROJECT_NAME}" "${IGATE_VERBOSE}"
    OUTPUT_VARIABLE output
    ERROR_VARIABLE errors
    RESULT_VARIABLE return_code
    WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})

if (NOT ("${IGATE_VERBOSE}" STREQUAL "0" ))
  message(STATUS "IGATE stdout = ${output}")
  message(STATUS "IGATE stderr = ${errors}")
endif()

if(NOT ("${return_code}" STREQUAL "0"))
    message(FATAL_ERROR "Interrogate failed: ${output} ${errors}")
endif()

# Set compiler flags
if (MSVC)

  # This matches the makepanda options

  if (IS_64_BIT)
    add_definitions("/favor:blend /DWIN64_VC /DWIN64 /bigobj")
  endif()

  add_definitions("/wd4996 /wd4275 /wd4267 /wd4101 /wd4273")

  if (TOUCHINPUT_ENABLED)
    # If touchinput is enabled
    add_definitions("/DWINVER=0x601")
  else()
    # If touchinput is disabled
    # add_definitions("/DWINVER=0x501")
  endif()

  if(IS_32_BIT AND ENABLE_SSE2)
    # If SSE is enabled
    add_definitions("/arch:SSE2")
  endif()

  # Different optimization settings
  if (OPTIMIZE STREQUAL "1")
    add_definitions("/MDd /Zi /RTCs /GS")
  elseif(OPTIMIZE STREQUAL "2")
    add_definitions("/MDd /Zi")
  elseif(OPTIMIZE STREQUAL "3")
    add_definitions("/MD /Zi /GS- /O2 /Ob2 /Oi /Ot /fp:fast")
  elseif(OPTIMIZE STREQUAL "4")
    add_definitions("/MD /Zi /GS- /Ox /Ob2 /Oi /Ot /fp:fast /DFORCE_INLINING /DNDEBUG /GL /LTCG")
    add_definitions("/Oy /Zp16")
  else()
    message(FATAL_ERROR "Invalid optimize value! Was: '${OPTIMIZE}'")
  endif()

  add_definitions("/Zm300 /DWIN32_VC /DWIN32")

  # No exceptions
  add_definitions("/D_HAS_EXCEPTIONS=0")

  # No RTTI
  add_definitions("/GR-")

  # Warning level 3 should be enough
  add_definitions("/W3")

  # Special case for 32 bit
  if(IS_32_BIT)
    add_definitions("/machine:x86")
  endif()

  # Use multi-core compilation
  add_definitions("/MP")
  # add_definitions("/GM-")


else()
  # Silence CMake warning on macOS
  set(CMAKE_MACOSX_RPATH TRUE)
  # Assuming GCC here

  add_definitions("-ftemplate-depth-70 -fPIC -c")

  # On mac
  if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
    add_definitions("-Wno-deprecated-declarations")
  endif()

  add_definitions("-pthread")
  add_definitions("-std=c++11")

  # No exceptions
  add_definitions("-fno-exceptions")

  # Differnt optimization settings
  if (OPTIMIZE STREQUAL "1")
    add_definitions("-ggdb -D_DEBUG")
  elseif(OPTIMIZE STREQUAL "2")
    add_definitions("-O1 -D_DEBUG")
  elseif(OPTIMIZE STREQUAL "3")
    add_definitions("-O2")
    add_definitions("-fno-finite-math-only -ffast-math")
  elseif(OPTIMIZE STREQUAL "4")
    add_definitions("-O3 -DNDEBUG -ffast-math -fno-rtti")
  else()
    message(FATAL_ERROR "Invalid optimize value! Was: '${OPTIMIZE}'")
  endif()

endif()

# Define the module name
add_definitions("/DPB_MODULE=${PROJECT_NAME}")
add_definitions("/DPB_CFG_MODULE=${PROJECT_NAME}")

# Collect sources for compiling
file(GLOB_RECURSE SOURCES source/*.cpp source/*.cxx source/*.I source/*.hpp source/*.h source/*.cc source/*.c)
include_directories("source/")
set(SOURCES ${SOURCES_H} ${SOURCES})

# Collect subdirs for compiling
file(GLOB POSSIBLE_DIRS RELATIVE ${CMAKE_CURRENT_LIST_DIR} source/*)
foreach(PDIR ${POSSIBLE_DIRS})
  if (IS_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/${PDIR})
    include_directories("${PDIR}")
    file(GLOB POSSIBLE_SUB_DIRS RELATIVE ${CMAKE_CURRENT_LIST_DIR}/${PDIR} ${PDIR}/*)
    foreach(PSUBDIR ${POSSIBLE_SUB_DIRS})
      if (IS_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/${PDIR}/${PSUBDIR})
        include_directories("${PDIR}/${PSUBDIR}")
      endif()
    endforeach()
  endif()
endforeach()


if ((EXISTS "${CMAKE_CURRENT_LIST_DIR}/additional_libs.cmake"))
  include("${CMAKE_CURRENT_LIST_DIR}/additional_libs.cmake")
endif()


# Build library
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
  # macOS won't let us link a .so with another .so, so make a .dylib
  add_library(${PROJECT_NAME} SHARED ${SOURCES})
  # Python doesn't detect .dylibs, so rename it .so
  set(CMAKE_SHARED_LIBRARY_SUFFIX ".so")
else()
  add_library(${PROJECT_NAME} MODULE ${SOURCES})
endif()

# Don't add lib prefix on Linux
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")

# Add the required libraries
target_link_libraries(${PROJECT_NAME} ${PYTHON_LIBRARIES} ${PANDA_LIBRARIES} ${LIBRARIES})

if(WIN32)
#   # Eventually link core.pyd?
else()
  set(CMAKE_MODULE_LINKER_FLAGS ${PANDA_CORE_PATH})
endif()

# After building, copy the file to the current directory
add_custom_command(
    TARGET ${PROJECT_NAME}
    POST_BUILD
    COMMAND "${PYTHON_EXECUTABLE}" "-B" "${CMAKE_CURRENT_LIST_DIR}/scripts/finalize.py" "${PROJECT_NAME}"
    WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})

# Make shared library paths absolute on macOS
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
  execute_process(
    COMMAND "${PYTHON_EXECUTABLE}" "-B" "scripts/common.py" "--print-lib-path"
    OUTPUT_VARIABLE PANDA_LIB_PATH
    WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
  execute_process(
    COMMAND "${PYTHON_EXECUTABLE}" "-B" "scripts/common.py" "--print-short-version"
    OUTPUT_VARIABLE PANDA_SHORT_VERSION
    WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
  )

  foreach(lib ${REQ_LIBRARIES})
    add_custom_command(
      TARGET ${PROJECT_NAME}
      POST_BUILD
      COMMAND "install_name_tool" "-change" "@loader_path/../lib/lib${lib}.${PANDA_SHORT_VERSION}.dylib" "${PANDA_LIB_PATH}/lib${lib}.dylib" "${PROJECT_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}"
      WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
  endforeach()
endif()

That or setting require_lib_bullet=1 in the config.ini file too.
That seems to have resolved all issues, I hope no more crop up!

1 Like