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
Include ceres-solver as fetchcontent directory #451
Comments
You do not need to use |
I read through the FindEigen.cmake module in ceres, and was able to found a solution as follows:
The thing here is that for !1 and !4, I do not need them because when including as subdir, the eigen and ceres CMakeLists.txt will create correct targets already, i.e., Setting Eigen3_DIR as you suggested (while setting EIGEN_PREFER_EXPORTED_EIGEN_CMAKE_CONFIGURATION=OFF), instead of setting EIGEN_INCLUDE_DIR_HINTS, does not work here, because the To sum up, I've found the solution to the question that I raised this issue for, which is to fetchcontent eigen and ceres, and build ceres using the fetched eigen build. In the mean time, I believe the FindEigen.cmake module could be better tweaked to allow this to be achieved more intuitively. One possible change would be adding some logic involves Eigen3_DIR or exported target (e.g., if (TARGET Eigen3::Eigen) before the find_path call. |
You should not need to do anything beyond setting Your mistake appears to be that you are assuming that you do not need to set Eigen3_DIR. The targets will be present if you use add_subdirectory(), but as per the docs of FetchContent you are not expecting to modify the fetched projects which means they will still invoke find_package() calls, which you will need to correctly configure the variables for in order that they detect the versions that you want. |
Upon closer investigate, I found that the reason that Eigen3_DIR did not work for me is due to a bug from Eigen: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1386 . In short, I am setting up the Eigen package via FetchContent, which basically first clones the eigen source code to However, as described in the bug report above, the configured Eigen3Config.cmake assumes that this file is to be used for installed Eigen3, not the exported Eigen3 build tree. Setting Eigen3_DIR to build/_deps/eigen-build does instruct ceres correctly locate this Eigen3Config.cmake file, but the EIGEN_INCLUDE_DIR is set to a wrong value, which does not point to the correct directory, in this case, In the bug report, it points to a pull request that suppose to fix this issue, but the pull request is not merged for some reason yet. Although I haven't check if it does fix my problem. I am not sure about the exact meaning of your second point, but I agree with you that, if the XXXConfig.cmake file is correctly written to handle both case of exported build tree and installed package, then setting XXX_DIR and use find_package(XXX NO_MODULE NO_DEFAULT_PATH) would be the safest bet. Back to this issue, I think for now, I am OK with my current solution (or hack) of bypassing find_package(Eigen) in ceres CMakeLists.txt by setting |
Forgot to mention, for the manual solution to work, I still need to make the change to ceres-src/internal/ceres/CMakeLists.txt .
I think this change is not bounded to the find_package stuff we discussed, but rather a generic treatment of both exported build tree and installed package, just the same as what is done to minglog. |
OK, after some more fiddling, I guess the thing to fix here in ceres is that it uses the legacy EIGEN_FOUND and EIGEN_INCLUDE_DIR machinery even when find_package(Eigen3) runs correctly and provide the imported target Eigen3::Eigen. In fact, if you look into Eigen source code: https://bitbucket.org/eigen/eigen/src/24d29254152d3b0818a05073f456898b39963fa0/cmake/Eigen3Config.cmake.in?at=default&fileviewer=file-view-default It is advertised that those variables should not be used. If using the Eigen3::Eigen target, we can completely remove that Any possibility that this got fixed soon? |
This has come quite a long way now since 33dd469 has been merged. Thanks @NeroBurner. With a preinstalled version Eigen, this should now work. The last hitch is when you try to use FetchContent with both Eigen and ceres-solver. Both define an
This minimal cmake_minimum_required(VERSION 3.5)
project(FetchCeres)
include(FetchContent)
FetchContent_Declare(eigen
GIT_REPOSITORY "https://github.com/eigenteam/eigen-git-mirror.git"
GIT_TAG cf794d3b741a6278df169e58461f8529f43bce5d # tag: 3.3.7
)
FetchContent_MakeAvailable(eigen)
FetchContent_Declare(ceres
URL https://github.com/ceres-solver/ceres-solver/archive/edb8322bdabef336db290be1cc557145b6d4bf80.tar.gz
URL_HASH SHA256=94de33593ec654481f29e74691373229f72e538ae69794aece2c6875678fbbc4
)
set(Eigen3_DIR ${eigen_BINARY_DIR})
# if ceres would set CMP0077 to NEW this could be a simple set(MINIGLOG ON) and not be overridden
set(MINIGLOG ON CACHE INTERNAL "" FORCE)
FetchContent_MakeAvailable(ceres) The above snippet also brings up the following error, but I think this needs to be addressed in Eigen.
|
Some shameless self promotion: using Hunter as package manager one just needs Edit: link to minimal example project: https://github.com/NeroBurner/hunter_ceres_example |
That example requires Eigen to be found in the system though doesn't? Have you tried getting Eigen with Hunter too? |
Eigen is also provided by Hunter. Hunter uses a modified ceres-solver project. Currently on the hunter-1.14.0 branch is used by Hunter. There all dependencies are required from Hunter, see this commit for the actual Eigen package request Some of the changes (Eigen3Config, gflagsConfig, explicit PRIVATE/PUBLIC linking) are already upstream, so less modifications for me to keep track of starting with ceres-solver |
Ah... I see. I guess that works because Hunter will build and "install" Eigen and forget about any of the target it created. Whereas |
Ceres-solver provides a custom uninstall target to ease the removal of installed files from the system. This clashes with other projects, that too provide an uninstall target (like Eigen3). Related issue: ceres-solver#451 (comment) Change-Id: Id153830ae20a880d23c7468acb39f55f48a2129a
@Ram-Z Could you try if this commit would fix the last roadblock for just set the cmake-arg |
This does indeed fix the duplicate target name issue. Had to add the following patch to Eigen to fix the diff --git a/cmake/Eigen3Config.cmake.in b/cmake/Eigen3Config.cmake.in
index c5c546887..a79b31ce5 100644
--- a/cmake/Eigen3Config.cmake.in
+++ b/cmake/Eigen3Config.cmake.in
@@ -3,6 +3,10 @@
@PACKAGE_INIT@
+if(Eigen3_FOUND OR EIGEN3_FOUND)
+ return()
+endif()
+
include ("${CMAKE_CURRENT_LIST_DIR}/Eigen3Targets.cmake")
# Legacy variables, do *not* use. May be removed in the future. Then I also had to But with these changes I managed to use FetchContent on both Eigen and ceres successfully. I'm not entirely sure what the best practices for CMakeConfig files are. Should they return early if the target they are providing has already been found? |
I think both changes would be valuable contributions to upstream Eigen3. The Eigen team recently moved to gitlab: https://gitlab.com/libeigen/eigen |
I'll submit a patch.
…On Dec 16, 2019 at 8:10, NeroBurner wrote:
I think both changes would be valuable contributions to upstream Eigen3.
The Eigen team recently moved to gitlab: https://gitlab.com/libeigen/eigen
--
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
#451 (comment)
|
Already patched upstream, just not released yet. cmake_minimum_required(VERSION 3.5)
project(FetchCeres)
include(FetchContent)
file(DOWNLOAD
https://gitlab.com/libeigen/eigen/commit/2cbd9dd49806d686a40841b6d888a83c816efccf.patch
${CMAKE_CURRENT_BINARY_DIR}/support-include.patch
)
FetchContent_Declare(eigen
GIT_REPOSITORY https://gitlab.com/libeigen/eigen
GIT_TAG 21ae2afd4edaa1b69782c67a54182d34efe43f9c # tag: 3.3.7
PATCH_COMMAND patch -p1 -i ${CMAKE_CURRENT_BINARY_DIR}/support-include.patch
)
FetchContent_MakeAvailable(eigen)
file(DOWNLOAD
https://github.com/NeroBurner/ceres-solver/commit/8bcf51f1e00e36293aa4f7fb8eac8ffbb0933457.patch
${CMAKE_CURRENT_BINARY_DIR}/no-uninstall.patch
)
FetchContent_Declare(ceres
URL https://github.com/ceres-solver/ceres-solver/archive/edb8322bdabef336db290be1cc557145b6d4bf80.tar.gz
URL_HASH SHA256=94de33593ec654481f29e74691373229f72e538ae69794aece2c6875678fbbc4
PATCH_COMMAND patch -p1 -i ${CMAKE_CURRENT_BINARY_DIR}/no-uninstall.patch
)
# if ceres would set CMP0077 to NEW this could be a simple set(MINIGLOG ON) and not be overridden
set(PROVIDE_UNINSTALL_TARGET OFF CACHE INTERNAL "" FORCE)
set(MINIGLOG ON CACHE INTERNAL "" FORCE)
FetchContent_MakeAvailable(ceres) This works now. Thanks. |
Ceres-solver provides a custom uninstall target to ease the removal of installed files from the system. This clashes with other projects, that too provide an uninstall target (like Eigen3). Related issue: #451 (comment) Change-Id: Id153830ae20a880d23c7468acb39f55f48a2129a
Finally got back to this again and with the patch to ceres below, I'm happy that ceres can be integrated well using FetchContent. --- CMakeLists.txt 2020-01-08 18:25:03.380697208 +0000
+++ CMakeLists.txt.new 2020-01-08 18:24:56.050634096 +0000
@@ -31,6 +31,10 @@
cmake_minimum_required(VERSION 3.5)
cmake_policy(VERSION 3.5)
+if(POLICY CMP0077)
+ # do not overwrite normal variables with option()
+ cmake_policy(SET CMP0077 NEW)
+endif()
# Set the C++ version (must be >= C++11) when compiling Ceres.
# The CMP0077 policy allows cmake_minimum_required(VERSION 3.5)
project(FetchCeres)
include(FetchContent)
FetchContent_Declare(eigen
GIT_REPOSITORY https://gitlab.com/libeigen/eigen
GIT_TAG 9623c0c4b9f40e74ba6ba551f86831616bdd488c
)
FetchContent_MakeAvailable(eigen)
FetchContent_Declare(ceres
URL https://github.com/ceres-solver/ceres-solver/archive/a60136b7aa2c1ab97558a74b271eee16ca1365c4.tar.gz
URL_HASH SHA256=94de33593ec654481f29e74691373229f72e538ae69794aece2c6875678fbbc4
# patch from above
PATCH_COMMAND patch -p0 -i ${CMAKE_CURRENT_BINARY_DIR}/ceres-cmp0077.patch
)
set(PROVIDE_UNINSTALL_TARGET OFF)
set(MINIGLOG ON)
FetchContent_MakeAvailable(ceres) |
I guess it's worth mentionning that instead of setting |
I've figured out that you can So no changes are required anymore in Eigen or Ceres. cmake_minimum_required(VERSION 3.5)
project(FetchCeres)
include(FetchContent)
FetchContent_Declare(eigen
GIT_REPOSITORY https://gitlab.com/libeigen/eigen
GIT_TAG 9623c0c4b9f40e74ba6ba551f86831616bdd488c
)
FetchContent_MakeAvailable(eigen)
FetchContent_Declare(ceres
URL https://github.com/ceres-solver/ceres-solver/archive/a60136b7aa2c1ab97558a74b271eee16ca1365c4.tar.gz
URL_HASH SHA256=94de33593ec654481f29e74691373229f72e538ae69794aece2c6875678fbbc4
)
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(PROVIDE_UNINSTALL_TARGET OFF)
set(MINIGLOG ON)
FetchContent_MakeAvailable(ceres) I'm not OP, but in my opinion this can now be closed. Thank you all very much. |
Thank you. |
Hi,
I am trying to use ceres-solver (the master branch)with the development HEAD of Eigen, both are included as FetchContent projects:
In general, this works, but there are places that do not work and/or confusing to me.
Any help is greatly appreciated. Thank you!
The text was updated successfully, but these errors were encountered: