diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index a4dec060..74ee3643 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -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 @@ -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" diff --git a/CMakeLists.txt b/CMakeLists.txt index 833c5cce..f9ffc9e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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( external_proj) @@ -69,12 +82,25 @@ 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 @@ -82,7 +108,6 @@ 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=") if(NOT "${CMAKE_TOOLCHAIN_FILE}" STREQUAL "") @@ -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 + "/${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 diff --git a/CMakePresets.json b/CMakePresets.json index 019632d5..de8ed6dd 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -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" } ] -} \ No newline at end of file +} diff --git a/INSTALL.md b/INSTALL.md index f814175a..e7ee47f5 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -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 diff --git a/Makefile b/Makefile index 4486fb59..0b6ba2e0 100644 --- a/Makefile +++ b/Makefile @@ -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 @@ -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 diff --git a/clients/qt/CMakeLists.txt b/clients/qt/CMakeLists.txt index 5ea9473f..a543a721 100644 --- a/clients/qt/CMakeLists.txt +++ b/clients/qt/CMakeLists.txt @@ -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 @@ -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}) diff --git a/cmake/modules/BuildODE.cmake b/cmake/modules/BuildODE.cmake new file mode 100644 index 00000000..41aa54f7 --- /dev/null +++ b/cmake/modules/BuildODE.cmake @@ -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= + -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= + 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 + "/${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") diff --git a/cmake/modules/BuildProtobuf.cmake b/cmake/modules/BuildProtobuf.cmake new file mode 100644 index 00000000..dcc584b3 --- /dev/null +++ b/cmake/modules/BuildProtobuf.cmake @@ -0,0 +1,87 @@ +# *************************************************************************** +# * Copyright 2017 Michael Eischer * +# * Robotics Erlangen e.V. * +# * http://www.robotics-erlangen.de/ * +# * info@robotics-erlangen.de * +# * * +# * 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 . * +# *************************************************************************** + +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= + -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 + "/${PROTOBUF_SUBPATH}" + "/${LIBPROTOC_SUBPATH}" + "/${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}") diff --git a/cmake/modules/EnvHelper.cmake b/cmake/modules/EnvHelper.cmake new file mode 100644 index 00000000..f5339c5f --- /dev/null +++ b/cmake/modules/EnvHelper.cmake @@ -0,0 +1,31 @@ +# *************************************************************************** +# * Copyright 2017 Michael Eischer * +# * Robotics Erlangen e.V. * +# * http://www.robotics-erlangen.de/ * +# * info@robotics-erlangen.de * +# * * +# * 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 . * +# *************************************************************************** + +macro(sanitize_env) + # remove "." from path to avoid searching the build_dir/bin folder + set(ORIG_PATH $ENV{PATH}) + set(MOD_PATH $ENV{PATH}) + list(REMOVE_ITEM MOD_PATH .) + set(ENV{PATH} ${MOD_PATH}) +endmacro() + +macro(restore_env) + set(ENV{PATH} ${ORIG_PATH}) +endmacro() diff --git a/cmake/modules/FindOrBuildProtobuf.cmake b/cmake/modules/FindOrBuildProtobuf.cmake new file mode 100644 index 00000000..4db92e07 --- /dev/null +++ b/cmake/modules/FindOrBuildProtobuf.cmake @@ -0,0 +1,11 @@ +# sanitize environment before find_package, because otherwise it also looks in the directory created for the ExternalProject +include(EnvHelper) +sanitize_env() +find_package(Protobuf 3.3.0) +restore_env() + +# protobuf versions >= 3.21 are incompatible with how the project is setup and cause weird errors +# so we build protobuf ourselves +if(NOT Protobuf_FOUND OR Protobuf_VERSION VERSION_GREATER_EQUAL 3.21) + include(BuildProtobuf) +endif() diff --git a/vcpkg.json b/vcpkg.json index d82168ff..89c2f3c8 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -2,8 +2,8 @@ "name": "grsim", "version-string": "0.0.1", "dependencies": [ - "qt5", + "qt5-base", "ode", "protobuf" ] -} \ No newline at end of file +}