如何在 Linux 中编译 Box2D?

How to compile Box2D in Linux?

编译 Box2d Tesbed 应该很简单:

来自 iforce2d:

Download the Box2D source code archive from here. If you want to use the terminal all the way, you could also do this (if wget is not available, use yum to install it):

wget http://box2d.googlecode.com/files/Box2D_v2.1.2.zip

Use the following commands to unzip and build it. [...]

unzip Box2D_v2.1.2.zip cd Box2D_v2.1.2/Box2D/Build cmake .. make

(这些说明很旧,我确实通过 git clone https://github.com/erincatto/Box2D.git 获得了源代码)

运行 cmake .. from Box2D/Build 在新克隆的目录中导致多个错误:

CMake Error at Testbed/CMakeLists.txt:84 (add_executable):
  Cannot find source file:

    Framework/imgui.h

  Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp
  .hxx .in .txx


CMake Error: Cannot determine link language for target "glfw".
CMake Error: CMake can not determine linker language for target: glfw

当然,make失败了:

[ 42%] Building CXX object Box2D/CMakeFiles/Box2D.dir/Dynamics/b2Body.cpp.o
/home/cabri/Documents/Box2D/Box2D/Box2D/Dynamics/b2Body.cpp: In member function ‘void b2Body::DestroyFixture(b2Fixture*)’:
/home/cabri/Documents/Box2D/Box2D/Box2D/Dynamics/b2Body.cpp:216:17: error: ‘nullptr’ was not declared in this scope
  if (fixture == nullptr)
                 ^
Box2D/CMakeFiles/Box2D.dir/build.make:566: recipe for target 'Box2D/CMakeFiles/Box2D.dir/Dynamics/b2Body.cpp.o' failed
make[2]: *** [Box2D/CMakeFiles/Box2D.dir/Dynamics/b2Body.cpp.o] Error 1
CMakeFiles/Makefile2:85: recipe for target 'Box2D/CMakeFiles/Box2D.dir/all' failed
make[1]: *** [Box2D/CMakeFiles/Box2D.dir/all] Error 2
Makefile:127: recipe for target 'all' failed
make: *** [all] Error 2

可以在这些站点上找到多个类似的问题,但 none 有答案。我知道我可以安装 box2d sudo apt-get install libox2d 但我也想要测试平台。

如何做到这一点?

简答...

是的,这可以构建,回滚 Box2D 的 git 克隆,直到构建不会失败。

长答案...

您似乎遇到了两个不同的问题:

  1. 找不到 imgui.h 文件。
  2. nullptr 引入 Git 源代码树,需要编译器接受 C++11 或更新的语言。

关于问题 1,早在 2017 年 2 月初就有一个问题提交:issue 433. Regarding problem 2, there's also been an issue filed for this back in June 2016: issue 414

虽然我没有在 GitHub 上看到问题 1 的解决方案,但问题 2 显然可以通过应用 pull request #412 来解决。您还应该能够通过让编译器接受 C++11(或更新版本)来解决问题 2。

至于解决问题 1,您可以回滚 Box2D 的 git 克隆,直到可以构建 Testbed。如果回滚足够远,那也应该可以解决问题 2(无需执行任何其他操作)。有关如何进行还原的信息可以在 How to revert Git repository to a previous commit?.

的 SO 问题中找到

Ubuntu 17.10 测试平台

主要的烦恼是您目前需要 premake5,它还处于 alpha 阶段,因此不在 Ubuntu:

cd
git clone https://github.com/premake/premake-core
cd premake-core
git checkout v5.0.0-alpha12
make -f Bootstrap.mak linux

cd
git clone https://github.com/erincatto/Box2D
cd Box2D
git checkout f655c603ba9d83f07fc566d38d2654ba35739102
cd Box2D
~/premake-core/bin/release/premake5 gmake
cd Build/gmake
make
# Must be run from there because of a ttf font is at that reative path. GDB told me that. :-)
cd ../../Testbed
../Build/gmake/bin/Debug/Testbed

这会在 Build/gmake/bin/Debug 下构建 .a 静态库。

https://github.com/erincatto/Box2D/issues/387#issuecomment-219168623 深入了解构建系统的混乱历史。

首先使用 CMake,但 Erin 虽然 premake 更好,然后 premake 失去了支持,项目卡在 Visual Studio + Xcode 配置文件,然后 premake 项目死而复生,被恢复。他们什么时候会切换到无限便携且永远受支持的 CMake? :-)

共享库

步骤完全相同,但首先清理旧的静态二进制文件:

git clean -xdf :/

然后在 运行 premake5 之前,将以下补丁应用于 Box2D:

diff --git a/Box2D/premake5.lua b/Box2D/premake5.lua
index b937866..f666651 100644
--- a/Box2D/premake5.lua
+++ b/Box2D/premake5.lua
@@ -23,7 +23,7 @@ workspace "Box2D"
        buildoptions { "-std=c++11" }

 project "Box2D"
-   kind "StaticLib"
+   kind "SharedLib"
    language "C++"
    files { "Box2D/**.h", "Box2D/**.cpp" }
    includedirs { "." }

测试台仍像以前一样运行,但如果您移动共享库,它会按预期停止工作。

TODO 清理 system-wide 安装。手动将 .so 和 headers 复制到适当的路径中应该可行......但不是很有趣。

CMake 复活

如此简单,如此美好。

Box2D/Box2D/CMakeLists.txt:

cmake_minimum_required(VERSION 3.0)
set (CMAKE_CXX_STANDARD 11)
file(GLOB_RECURSE SOURCES RELATIVE ${CMAKE_SOURCE_DIR} "Box2D/*.cpp")
include_directories(${CMAKE_SOURCE_DIR})
add_library(Box2D SHARED ${SOURCES})

target_include_directories(Box2D PUBLIC ${CMAKE_SOURCE_DIR})
set(HELLO_SOURCES HelloWorld/HelloWorld.cpp)
add_executable(hello ${HELLO_SOURCES})
target_link_libraries(hello PRIVATE Box2D)

然后:

cd Box2D/Box2D
mkdir build
cd build
cmake ..
make
./hello

目前,我将跟踪 Box2D 作为一个子模块,并将此方法用于我认为的项目,这是一个示例:https://github.com/cirosantilli/sdl-box2d

find编译静态库

如果您不关心 OS 并且不想安装 premake,这也可能有用:

cd Box2D/Box2D/Box2D
find . -iname '*.cpp' | xargs g++ -c -I../
ar rcs libBox2D.a *.o
g++ -I.. ../HelloWorld/HelloWorld.cpp libBox2D.a
./a.out

如果您签出了 Box2D 存储库中的最新提交,您可以通过 运行 在存储库目录中执行此 git 命令来恢复原始 CMake 文件:

git checkout 05ee3c3c22af9ac1e5d88061d0b473f814c8210f^ \
 Box2D/Box2D/Box2DConfig.cmake.in \
 Box2D/Box2D/CMakeLists.txt \
 Box2D/Box2D/UseBox2D.cmake \
 Box2D/CMakeLists.txt \
 Box2D/HelloWorld/CMakeLists.txt \
 Box2D/Testbed/CMakeLists.txt \
 Box2D/glew/CMakeLists.txt \
 Box2D/glfw/CMakeLists.txt

由于 Box2D 自此提交以来已开始使用 C++11 功能,因此您需要将此行添加到 Box2D/CMakeLists.txt:

set (CMAKE_CXX_STANDARD 11)

如果你只想构建核心库,你就完成了;只需 运行 以下命令:

mkdir build
cd build
cmake -D BOX2D_BUILD_EXAMPLES=OFF ../Box2D

测试平台

如果您想要 Testbed,事情会变得更加复杂。 Box2D 的 GLFW 副本的 CMakeLists 似乎已完全损坏。打开Box2D/CMakeLists.txt,找到这两行:

add_subdirectory(glew)
add_subdirectory(glfw)

将它们替换为以下内容。这将导致构建使用您系统版本的库,因此您需要安装它们:

find_package(GLEW REQUIRED)
if (GLEW_FOUND)
  include_directories(${GLEW_INCLUDE_DIRS})
  link_libraries(${GLEW_LIBRARIES})
endif()

find_package(PkgConfig REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
include_directories(${GLFW_INCLUDE_DIRS})

打开 Box2D/Testbed/CMakeLists.txt。在文件顶部的 set(Testbed_Framework_SRCS 下,删除引用 imgui 和 RenderGL3 的 4 行。在该部分添加以下行:

../imgui/imgui.h
../imgui/imgui.cpp
../imgui/imgui_draw.cpp
../imgui/imgui_impl_glfw_gl3.cpp

滚动到底部并将 glewglfw 行替换为:

${GLEW_LIBRARIES}
${GLFW_STATIC_LIBRARIES}

终于替换

file(COPY ../Build/Data DESTINATION ..)

file(COPY ./Data DESTINATION .)

此时,完整的库和测试平台应该是可构建的:

mkdir build
cd build
cmake ../Box2D