Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Protobuf and ODE as ExternalProjects to cmake to fix platform compatibility issues #182

Merged
merged 9 commits into from
Feb 24, 2024
17 changes: 13 additions & 4 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: "Install dependencies"
run: brew tap robotology/formulae && brew install cmake pkg-config qt@5 protobuf@21 robotology/formulae/ode
run: brew tap robotology/formulae && brew install cmake pkg-config qt@5
- name: "Build"
run: make
# for some reason qt5 is not correctly in the path and this will break whenever the location of it changes
# 5.15.11 is for macos-12 and 5.15.12 is for macos-13
run: PATH=/usr/local/Cellar/qt@5/5.15.11/lib/cmake/Qt5:/usr/local/Cellar/qt@5/5.15.12/lib/cmake/Qt5:$PATH && make

build-windows:
runs-on: windows-latest
Expand All @@ -46,9 +48,16 @@ jobs:
vcpkgGitCommitId: 8eb57355a4ffb410a2e94c07b4dca2dffbee8e50
vcpkgDirectory: c:/vcpkg # folder must reside in c:\ otherwise qt wont install due to long path errors


- name: Run CMake and run vcpkg to build packages
uses: lukka/run-cmake@v10
with:
configurePreset: "windows-default"
# this preset is needed to actually install the vcpkg dependencies
configurePreset: "ninja-multi-vcpkg"
configPresetAdditionalArgs: "[-DVCPKG_TARGET_TRIPLET=x64-windows]"
buildPreset: "ninja-multi-vcpkg"
buildPresetAdditionalArgs: "['--config Release']"
env:
# [OPTIONAL] Define the vcpkg's triplet you want to enforce, otherwise the default one
# for the hosting system will be automatically choosen (x64 is the default on all
# platforms, e.g. `x64-osx`).
VCPKG_DEFAULT_TRIPLET: "x64-windows"
67 changes: 54 additions & 13 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ include(${PROJECT_SOURCE_DIR}/cmake/Utils.cmake)
standard_config()
standard_paths(${PROJECT_SOURCE_DIR} bin lib)

# policy regarding how to handle generated stuff, OLD behavior would ignore generated files
# (which includes the generated protobuf cpp files)
if (POLICY CMP0071)
cmake_policy(SET CMP0071 NEW)
endif()

# policy regarding when to rebuild stuff when external projects downloaded with URL changes
if (POLICY CMP0135)
cmake_policy(SET CMP0135 NEW)
endif()

include(GNUInstallDirs)

set(app ${CMAKE_PROJECT_NAME})
# create the target before the sources list is known so that we can call
# add_dependencies(<target> external_proj)
Expand Down Expand Up @@ -69,20 +82,32 @@ find_package(Qt5 COMPONENTS Core Widgets OpenGL Network REQUIRED)
list(APPEND libs Qt5::Core Qt5::Widgets Qt5::OpenGL Qt5::Network)

# ODE
if(WIN32)
find_package(ODE CONFIG REQUIRED)
list(APPEND libs ODE::ODE)
if(BUILD_ODE)
include(BuildODE)
add_dependencies(${app} ode_external)
else()
find_package(ODE REQUIRED)
list(APPEND libs ode::ode)
if(WIN32)
find_package(ODE CONFIG)
set(ODE_LIB_NAME ODE::ODE)
else()
find_package(ODE)
set(ODE_LIB_NAME ode::ode)
endif()

if(ODE_FOUND)
list(APPEND libs ${ODE_LIB_NAME})
else()
# if ODE could not be found just build it
include(BuildODE)
add_dependencies(${app} ode_external)
endif()
endif()

# VarTypes
find_package(VarTypes)

if(NOT VARTYPES_FOUND)
include(ExternalProject)
set(VARTYPES_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/vartypes_install")

set(VARTYPES_CMAKE_ARGS "-DVARTYPES_BUILD_STATIC=ON;-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>")
if(NOT "${CMAKE_TOOLCHAIN_FILE}" STREQUAL "")
Expand All @@ -92,23 +117,39 @@ if(NOT VARTYPES_FOUND)
ExternalProject_Add(vartypes_external
GIT_REPOSITORY https://github.com/jpfeltracco/vartypes
GIT_TAG origin/jpfeltracco/build_static
INSTALL_DIR "${VARTYPES_INSTALL_DIR}"
CMAKE_ARGS "${VARTYPES_CMAKE_ARGS}"
STEP_TARGETS install
)
set(VARTYPES_LIB_SUBPATH "${CMAKE_INSTALL_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}vartypes${CMAKE_STATIC_LIBRARY_SUFFIX}")

# the byproducts are available after the install step
ExternalProject_Add_Step(vartypes_external out
DEPENDEES install
BYPRODUCTS
"<INSTALL_DIR>/${VARTYPES_LIB_SUBPATH}"
)

add_dependencies(${app} vartypes_external)

ExternalProject_Get_Property(vartypes_external install_dir)
add_dependencies(${app} vartypes_external)

set(VARTYPES_INCLUDE_DIRS "${VARTYPES_INSTALL_DIR}/include")
set(VARTYPE_LIB_NAME ${CMAKE_STATIC_LIBRARY_PREFIX}vartypes${CMAKE_STATIC_LIBRARY_SUFFIX})
set(VARTYPES_LIBRARIES "${VARTYPES_INSTALL_DIR}/lib/${VARTYPE_LIB_NAME}")
set(VARTYPES_INCLUDE_DIRS "${install_dir}/include")
set(VARTYPES_LIBRARIES "${install_dir}/${VARTYPES_LIB_SUBPATH}")
endif()

target_include_directories(${app} PRIVATE ${VARTYPES_INCLUDE_DIRS})
list(APPEND libs ${VARTYPES_LIBRARIES})

# Protobuf
find_package(Protobuf REQUIRED)
include_directories(${PROTOBUF_INCLUDE_DIRS})
list(APPEND libs ${PROTOBUF_LIBRARIES})
include(FindOrBuildProtobuf)

if(TARGET protobuf_external)
add_dependencies(${app} protobuf_external)
endif()

include_directories(${Protobuf_INCLUDE_DIRS})
list(APPEND libs ${Protobuf_LIBRARIES})

set (Protobuf_IMPORT_DIRS ${Protobuf_INCLUDE_DIR})
protobuf_generate_cpp(PROTO_CPP PROTO_H
Expand Down
28 changes: 27 additions & 1 deletion CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,32 @@
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}"
}
},
{
"name": "ninja-multi-vcpkg",
"displayName": "Windows x64 Release vcpkg",
"generator": "Ninja Multi-Config",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"architecture": {
"value": "x64",
"strategy": "external"
},
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": {
"type": "FILEPATH",
"value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
},
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}"
}
}
],
"buildPresets": [
{
"name": "ninja-multi-vcpkg",
"configurePreset": "ninja-multi-vcpkg",
"displayName": "Build ninja-multi-vcpkg",
"description": "Build ninja-multi-vcpkg Configurations"
}
]
}
}
6 changes: 5 additions & 1 deletion INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,11 @@ $ sudo make install
grSim will be — by default — installed on the `/usr/local` directory.


if you face any problem regarding of updating the grsim version, you can try removing the `grsim.xml`.
## Troubleshooting

If you face any problem regarding of updating the grsim version, you can try removing the `grsim.xml`.
If grSim crashes almost instantly with some ODE error the issue might by your ODE version.
Try adding -DBUILD_ODE=TRUE to build ODE from source instead of using the system dependency.

## Notes on the performance

Expand Down
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ BUILDDIR=build
BUILDTYPE=Release
#BUILDTYPE=Debug

BUILD_ODE=OFF

.PHONY: all build mkbuilddir cmake dist package deb install clean clean-all

all: build
Expand All @@ -22,7 +24,7 @@ mkbuilddir:
[ -d $(BUILDDIR) ] || mkdir $(BUILDDIR)

cmake: CMakeLists.txt
cd $(BUILDDIR) && cmake -DCMAKE_BUILD_TYPE=$(BUILDTYPE) ..
cd $(BUILDDIR) && cmake -DCMAKE_BUILD_TYPE=$(BUILDTYPE) -DBUILD_ODE=$(BUILD_ODE) ..

dist: package

Expand Down
25 changes: 22 additions & 3 deletions clients/qt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,30 @@ set(CMAKE_AUTOMOC ON)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

# policy regarding how to handle generated stuff, OLD behavior would ignore generated files
# (which includes the generated protobuf cpp files)
if (POLICY CMP0071)
cmake_policy(SET CMP0071 NEW)
endif()

# policy regarding when to rebuild stuff when external projects downloaded with URL changes
if (POLICY CMP0135)
cmake_policy(SET CMP0135 NEW)
endif()

set(libs)

find_package(Qt5 COMPONENTS Core Widgets Network REQUIRED)
list(APPEND libs Qt5::Core Qt5::Widgets Qt5::Network)

# if find_package was already executed and we already included BuildProtobuf find_package fails,
# so we only want to do execute find_package if protobuf was not found yet
if(NOT Protobuf_FOUND)
include(FindOrBuildProtobuf)
endif()

find_package(Protobuf REQUIRED)
include_directories(${PROTOBUF_INCLUDE_DIRS})
list(APPEND libs ${PROTOBUF_LIBRARIES})
include_directories(${Protobuf_INCLUDE_DIRS})
list(APPEND libs ${Protobuf_LIBRARIES})

protobuf_generate_cpp(PROTO_CPP PROTO_H
../../src/proto/grSim_Replacement.proto
Expand All @@ -30,5 +45,9 @@ add_executable(${app} MACOSX_BUNDLE
mainwindow.h
)

if(TARGET protobuf_external)
add_dependencies(${app} protobuf_external)
endif()

target_link_libraries(${app} ${libs})

34 changes: 34 additions & 0 deletions cmake/modules/BuildODE.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# build ODE, because some versions of it cause grSim to segfault somewhere
# could be because in some packages the double precision is turned off
include(ExternalProject)

ExternalProject_Add(ode_external
GIT_REPOSITORY https://bitbucket.org/odedevs/ode.git
GIT_TAG 0.16.4
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
-DCMAKE_TOOLCHAIN_FILE:PATH=${CMAKE_TOOLCHAIN_FILE}
-DCMAKE_C_COMPILER:PATH=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER:PATH=${CMAKE_CXX_COMPILER}
-DCMAKE_MAKE_PROGRAM:PATH=${CMAKE_MAKE_PROGRAM}
# necessary, because it does not build the static libs if this is ON
-DBUILD_SHARED_LIBS=OFF
# if this is OFF grSim just dies instantly and INSTALL.md says it should be ON
-DODE_DOUBLE_PRECISION=ON
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
STEP_TARGETS install
)

set(ODE_LIB_SUBPATH "${CMAKE_INSTALL_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}ode${CMAKE_STATIC_LIBRARY_SUFFIX}")

# the byproducts are available after the install step
ExternalProject_Add_Step(ode_external out
DEPENDEES install
BYPRODUCTS
"<INSTALL_DIR>/${ODE_LIB_SUBPATH}"
)

ExternalProject_Get_Property(ode_external install_dir)
set(ODE_LIBRARY "${install_dir}/${ODE_LIB_SUBPATH}")
list(APPEND libs ${ODE_LIBRARY})
target_include_directories(${app} PRIVATE "${install_dir}/include")
87 changes: 87 additions & 0 deletions cmake/modules/BuildProtobuf.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# ***************************************************************************
# * Copyright 2017 Michael Eischer *
# * Robotics Erlangen e.V. *
# * http://www.robotics-erlangen.de/ *
# * [email protected] *
# * *
# * This program is free software: you can redistribute it and/or modify *
# * it under the terms of the GNU General Public License as published by *
# * the Free Software Foundation, either version 3 of the License, or *
# * any later version. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU General Public License for more details. *
# * *
# * You should have received a copy of the GNU General Public License *
# * along with this program. If not, see <http://www.gnu.org/licenses/>. *
# ***************************************************************************

include(ExternalProject)

set(PROTOBUF_CMAKE_ARGS )

ExternalProject_Add(protobuf_external
# URL is the same as in the ER-Force framework,
# because ER-Force needs it and has an incentive to keep the link stable
URL http://www.robotics-erlangen.de/downloads/libraries/protobuf-cpp-3.6.1.tar.gz
URL_HASH SHA256=b3732e471a9bb7950f090fd0457ebd2536a9ba0891b7f3785919c654fe2a2529
SOURCE_SUBDIR cmake
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
-DCMAKE_TOOLCHAIN_FILE:PATH=${CMAKE_TOOLCHAIN_FILE}
-DCMAKE_C_COMPILER:PATH=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER:PATH=${CMAKE_CXX_COMPILER}
-DCMAKE_MAKE_PROGRAM:PATH=${CMAKE_MAKE_PROGRAM}
# the tests fail to build :-(
-Dprotobuf_BUILD_TESTS:BOOL=OFF
STEP_TARGETS install
)

set(PROTOBUF_SUBPATH "${CMAKE_INSTALL_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}protobuf${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(LIBPROTOC_SUBPATH "${CMAKE_INSTALL_LIBDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}protoc${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(PROTOC_SUBPATH "bin/protoc${CMAKE_EXECUTABLE_SUFFIX}")

# the byproducts are available after the install step
ExternalProject_Add_Step(protobuf_external out
DEPENDEES install
BYPRODUCTS
"<INSTALL_DIR>/${PROTOBUF_SUBPATH}"
"<INSTALL_DIR>/${LIBPROTOC_SUBPATH}"
"<INSTALL_DIR>/${PROTOC_SUBPATH}"
)

ExternalProject_Get_Property(protobuf_external install_dir)
set_target_properties(protobuf_external PROPERTIES EXCLUDE_FROM_ALL true)

# override all necessary variables originally set by find_package
# if FORCE is not set cmake does not allow us to override the variables, for some unknown reason
set(Protobuf_FOUND true CACHE BOOL "" FORCE)
set(Protobuf_VERSION "3.6.1" CACHE STRING "" FORCE)
set(Protobuf_INCLUDE_DIR "${install_dir}/include" CACHE PATH "" FORCE)
set(Protobuf_INCLUDE_DIRS "${Protobuf_INCLUDE_DIR}" CACHE PATH "" FORCE)
set(Protobuf_LIBRARY "${install_dir}/${PROTOBUF_SUBPATH}" CACHE PATH "" FORCE)
set(Protobuf_LIBRARIES "${Protobuf_LIBRARY}" CACHE PATH "" FORCE)
set(Protobuf_LIBRARY_DEBUG "${install_dir}/${PROTOBUF_SUBPATH}" CACHE PATH "" FORCE)
set(Protobuf_LIBRARY_RELEASE "${install_dir}/${PROTOBUF_SUBPATH}" CACHE PATH "" FORCE)
set(Protobuf_LITE_LIBRARY_DEBUG "${install_dir}/${PROTOBUF_SUBPATH}" CACHE PATH "" FORCE)
set(Protobuf_LITE_LIBRARY_RELEASE "${install_dir}/${PROTOBUF_SUBPATH}" CACHE PATH "" FORCE)
set(Protobuf_PROTOC_EXECUTABLE "${install_dir}/${PROTOC_SUBPATH}" CACHE PATH "" FORCE)
set(Protobuf_PROTOC_LIBRARY_DEBUG "${install_dir}/${LIBPROTOC_SUBPATH}" CACHE PATH "" FORCE)
set(Protobuf_PROTOC_LIBRARY_RELEASE "${install_dir}/${LIBPROTOC_SUBPATH}" CACHE PATH "" FORCE)
# this is a dependency for the protobuf_generate_cpp custom command
# if this is not set the generate command sometimes get executed before protoc is compiled
set(protobuf_generate_DEPENDENCIES protobuf_external CACHE STRING "" FORCE)

# compatibility with cmake 3.10
if(NOT TARGET protobuf::protoc)
# avoid error if target was already created for an older version
add_executable(protobuf::protoc IMPORTED)
endif()
# override the protobuf::protoc path used by the protobuf_generate_cpp macro
set_target_properties(protobuf::protoc PROPERTIES
IMPORTED_LOCATION "${Protobuf_PROTOC_EXECUTABLE}"
)

message(STATUS "Building protobuf ${Protobuf_VERSION}")
Loading
Loading