1

I have tried to use QHull and libqhullcpp as an external project in CMake, but I was not successful.

So far I've used these commands which is a modified version of this:

include(ExternalProject)
ExternalProject_add(qhull
        GIT_REPOSITORY "https://github.com/qhull/qhull.git"
        GIT_TAG "2019.1"
        GIT_PROGRESS TRUE
        SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/qhull
        BINARY_DIR ${CMAKE_BINARY_DIR}/thirdparty-build/qhull
        CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/thirdparty-install"
        CMAKE_CACHE_ARGS "-DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=true"
        )


### qhullstatic reentrant library
add_library(libqhullstatic_r STATIC IMPORTED)
set_property(TARGET libqhullstatic_r PROPERTY IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/thirdparty-build/qhull/${CMAKE_STATIC_LIBRARY_PREFIX}qhullstatic_r${CMAKE_STATIC_LIBRARY_SUFFIX})
set_property(TARGET libqhullstatic_r PROPERTY IMPORTED_LOCATION_DEBUG ${CMAKE_BINARY_DIR}/thirdparty-build/qhull/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}qhullstatic_r${CMAKE_STATIC_LIBRARY_SUFFIX})
set_property(TARGET libqhullstatic_r PROPERTY IMPORTED_LOCATION_RELEASE ${CMAKE_BINARY_DIR}/thirdparty-build/qhull/Release/${CMAKE_STATIC_LIBRARY_PREFIX}qhullstatic_r${CMAKE_STATIC_LIBRARY_SUFFIX})
add_dependencies(libqhullstatic_r qhull)
### qhullcpp library
add_library(libqhullcpp STATIC IMPORTED)
set_property(TARGET libqhullcpp PROPERTY IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/thirdparty-build/qhull/${CMAKE_STATIC_LIBRARY_PREFIX}qhullcpp${CMAKE_STATIC_LIBRARY_SUFFIX})
set_property(TARGET libqhullcpp PROPERTY IMPORTED_LOCATION_DEBUG ${CMAKE_BINARY_DIR}/thirdparty-build/qhull/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}qhullcpp${CMAKE_STATIC_LIBRARY_SUFFIX})
set_property(TARGET libqhullcpp PROPERTY IMPORTED_LOCATION_RELEASE ${CMAKE_BINARY_DIR}/thirdparty-build/qhull/Release/${CMAKE_STATIC_LIBRARY_PREFIX}qhullcpp${CMAKE_STATIC_LIBRARY_SUFFIX})
set_property(TARGET libqhullcpp PROPERTY INTERFACE_LINK_LIBRARIES libqhullstatic_r)
add_dependencies(libqhullcpp qhull)

add_executable(${PROJECT_NAME} src/main.cpp)
target_link_libraries(${PROJECT_NAME} ${libqhullcpp})

My project cannot find any file of the Qhull code and if I add

#include <libqhullcpp/Qhull.h> 
orgQhull::Qhull qhull;

to my project it will throw this compile error:

CMakeFiles/MyProject.dir/src/main.cpp.o: In function `main':
~/MyProject/src/main.cpp:108: undefined reference to `orgQhull::Qhull::Qhull()'
~/MyProject/src/main.cpp:108: undefined reference to `orgQhull::Qhull::~Qhull()'
~/MyProject/src/main.cpp:108: undefined reference to `orgQhull::Qhull::~Qhull()'
collect2: error: ld returned 1 exit status
CMakeFiles/MyProject.dir/build.make:83: recipe for target 'MyProject' failed
make[3]: *** [MyProject] Error 1
CMakeFiles/Makefile2:104: recipe for target 'CMakeFiles/MyProject.dir/all' failed
make[2]: *** [CMakeFiles/MyProject.dir/all] Error 2
CMakeFiles/Makefile2:111: recipe for target 'CMakeFiles/MyProject.dir/rule' failed
make[1]: *** [CMakeFiles/MyProject.dir/rule] Error 2
Makefile:131: recipe for target 'MyProject' failed
make: *** [MyProject] Error 2
Sina Masnadi
  • 1,516
  • 17
  • 28
  • 1
    "My project cannot find any file of the Qhull code." - Don't understand that problem description. Could you be more specific? E.g. show the error message. – Tsyvarev Apr 08 '20 at 06:53
  • @Tsyvarev That means if I add #include to my project it will throw this error " error: ‘Qhull’ was not declared in this scope" – Sina Masnadi Apr 08 '20 at 15:07
  • 1
    Please, show **complete error message**. Currently it is unclear whether the error is detected in the Qhull header file or in your source file. The only thing which is clear that header `libqhullcpp/Qhull.h` has been **found**, opposite to what you state in the question post. (A missed header leads to the different error message). So `CMakeLists.txt` is probably correct but the problem is in **your code**, which you forgot to include to the question post. – Tsyvarev Apr 08 '20 at 15:24
  • About importance of complete error message see e.g. this question on meta: https://meta.stackoverflow.com/q/359146/3440745 – Tsyvarev Apr 08 '20 at 15:32
  • @Tsyvarev I updated the question with the complete error message and the test case. You are right, it finds the Qhull file, it throws more errors. – Sina Masnadi Apr 08 '20 at 15:35
  • Nice. So with complete error message it is easy to track the problem: in `target_link_libraries` call you link with `${libqhullcpp}`, which **dereferences** non-existent **variable** `libqhullcpp`. For link with the library **target**, created by `add_library(libqhullcpp STATIC IMPORTED)`, you need to specify **name** of the target: `target_link_libraries(${PROJECT_NAME} libqhullcpp)`. In CMake **variables** and **targets** are different things which cannot be interchanged. – Tsyvarev Apr 08 '20 at 15:41
  • @Tsyvarev Thanks! If I use target_link_libraries(${PROJECT_NAME} libqhullcpp) I'll get the following compile error: make[3]: *** No rule to make target 'thirdparty-build/qhull/Debug/libqhullcpp.a', needed by 'MyProject'. Stop. CMakeFiles/Makefile2:104: recipe for target 'CMakeFiles/MyProject.dir/all' failed make[2]: *** [CMakeFiles/MyProject.dir/all] Error 2 CMakeFiles/Makefile2:111: recipe for target 'CMakeFiles/MyProject.dir/rule' failed make[1]: *** [CMakeFiles/MyProject.dir/rule] Error 2 Makefile:131: recipe for target 'MyProject' failed make: *** [MyProject] Error 2 – Sina Masnadi Apr 08 '20 at 15:46
  • 1
    So it cannot find library files you specified as `IMPORTED_LOCATION`. Probably, you have specified these locations wrong. Find corresponded files produced by building `qhull` project and compare their paths with the locations you have specified. – Tsyvarev Apr 08 '20 at 15:53
  • @Tsyvarev Thanks to your help I found out that qhull debug/release directory was not created with this configuration and removing the IMPORTED_LOCATION_DEBUG and IMPORTED_LOCATION_RELEASE fixed the problem. – Sina Masnadi Apr 09 '20 at 19:54

1 Answers1

2

I've modified your CMakeLists.txt file and done some optimization, so you don't build in source. My tree gives this:

--QHull
|   |--CMakeLists.txt
|   |--CMakeLists.txt.in
|   |--src
|       |--main.cpp
|--build

with CMakeLists.txt:

cmake_minimum_required(VERSION 3.0)
project(TestQHull)

configure_file(CMakeLists.txt.in qhull-download/CMakeLists.txt)

execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
    WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/qhull-download"
)
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
    WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/qhull-download"
)

add_subdirectory("${CMAKE_BINARY_DIR}/qhull-src"
                 "${CMAKE_BINARY_DIR}/qhull-build"
)

include_directories(${CMAKE_BINARY_DIR}/qhull-src/src)
link_directories(${CMAKE_BINARY_DIR}/qhull-build)

### qhullstatic reentrant library
add_library(libqhullstatic_r STATIC IMPORTED)
set_property(TARGET libqhullstatic_r PROPERTY IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/qhull-build/${CMAKE_STATIC_LIBRARY_PREFIX}qhullstatic_r${CMAKE_STATIC_LIBRARY_SUFFIX})
add_dependencies(libqhullstatic_r qhull)
### qhullcpp library
add_library(libqhullcpp STATIC IMPORTED)
set_property(TARGET libqhullcpp PROPERTY IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/qhull-build/${CMAKE_STATIC_LIBRARY_PREFIX}qhullcpp${CMAKE_STATIC_LIBRARY_SUFFIX})
set_property(TARGET libqhullcpp PROPERTY INTERFACE_LINK_LIBRARIES libqhullstatic_r)
add_dependencies(libqhullcpp qhull)

add_executable(${PROJECT_NAME} src/main.cpp)
target_link_libraries(${PROJECT_NAME} libqhullstatic_r libqhullcpp)

and

CMakeLists.txt.in contents this:

cmake_minimum_required(VERSION 3.0)
project(qhull-download NONE)

include(ExternalProject)

ExternalProject_add(qhull
    GIT_REPOSITORY https://github.com/qhull/qhull.git
    GIT_TAG 2019.1
    GIT_PROGRESS TRUE
    SOURCE_DIR ${CMAKE_BINARY_DIR}/qhull-src
    BINARY_DIR ${CMAKE_BINARY_DIR}/qhull-build
    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}
    CMAKE_CACHE_ARGS ""
    CONFIGURE_COMMAND ""
    BUILD_COMMAND ""
    INSTALL_COMMAND ""
    TEST_COMMAND ""
)

If you cd build && cmake ../QHull, it'll download and start building qhull for you.

The only drawback: the ExternalProjects keep the ${CMAKE_SOURCE_DIR}\QHull\src as INCLUDE_DIRECTORIES instead of the needed ${CMAKE_BINARY_DIR}\qhull-src\src.

As I couldn't fix this, my work-around is to replace -I${CMAKE_SOURCE_DIR}\QHull\src with -I${CMAKE_SOURCE_DIR}\QHull\src in the generator script (e.g. build.ninja in my case) after cmake configure step.

After that, I was able to build my own example main.cpp.

dboy
  • 1,004
  • 2
  • 16
  • 24