Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Installing an ExternalProject with CMake

I have the following code in one of my CMakeLists.txt:

FIND_PACKAGE(sphinxbase)
if (${SPHINXBASE_FOUND})
    INCLUDE_DIRECTORIES(${SPHINXBASE_INCLUDE_DIR}/sphinxbase/)
else ()
    ExternalProject_Add(
        sphinxbase
        GIT_REPOSITORY      "https://github.com/cmusphinx/sphinxbase.git"
        GIT_TAG             "e34b1c632392276101ed16e8a05862e43f038a7c"
        SOURCE_DIR          ${CMAKE_CURRENT_SOURCE_DIR}/lib/sphinxbase
        CONFIGURE_COMMAND   ${CMAKE_CURRENT_SOURCE_DIR}/lib/sphinxbase/autogen.sh
        BUILD_COMMAND       ${MAKE}
        UPDATE_COMMAND      ""
        INSTALL_COMMAND     ""
        BUILD_IN_SOURCE     ON
        LOG_DOWNLOAD        ON
        LOG_UPDATE          ON
        LOG_CONFIGURE       ON
        LOG_BUILD           ON
        LOG_TEST            ON
        LOG_INSTALL         ON
    )
    ExternalProject_Get_Property(sphinxbase SOURCE_DIR)
    ExternalProject_Get_Property(sphinxbase BINARY_DIR)
    SET(SPHINXBASE_SOURCE_DIR ${SOURCE_DIR})
    SET(SPHINXBASE_BINARY_DIR ${BINARY_DIR})
    SET(SPHINXBASE_LIBRARIES ${SPHINXBASE_BINARY_DIR}/src/libsphinxbase/.libs/libsphinxbase.a)
    INCLUDE_DIRECTORIES(${SPHINXBASE_SOURCE_DIR}/include)
endif ()
SET(DEPENDENCIES ${DEPENDENCIES} sphinxbase)
SET(LIBS ${LIBS} ${SPHINXBASE_LIBRARIES})

In addition to the TARGET that I'm trying to install, how would I go about installing this ExternalProject? Right now I'm trying to do it like this:

install(TARGETS ${LIBS}
        LIBRARY DESTINATION lib
        ARCHIVE DESTINATION lib
        OPTIONAL
        )

install(TARGETS ${PROJECT_NAME}
        RUNTIME DESTINATION bin
        )

But I'm getting the following error thrown at me:

CMake Error at CMakeLists.txt:197 (install):
  install TARGETS given target
  "/Users/syb0rg/Dropbox/Development/Khronos/Khronos/lib/sphinxbase/src/libsphinxbase/.libs/libsphinxbase.a"
  which does not exist in this directory.

Any suggestions?

like image 276
syb0rg Avatar asked Mar 11 '16 07:03

syb0rg


1 Answers

Command flow install(TARGETS) installs targets, which are created with add_executable or add_library commands. For install concrete files, you need to use command flow install(FILES).

Instead of installing selected files from subproject's build directory, you may install subproject as is. For that you can use

make DESTDIR=<...> install

command as INSTALL option of ExeternalProject_Add. This command will install whole subproject into directory given as DESTDIR parameter for make (more information about this parameter can be found here).

Then you may use install(DIRECTORY) command for install all subproject's files at once:

# It is better to use binary directory for download or build 3d-party project 
set(sphinxbase_SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/lib/sphinxbase)
# This will be used as DESTDIR on subproject's `make install`.
set(sphinxbase_DESTDIR ${CMAKE_CURRENT_BINARY_DIR}/lib/sphinxbase_install)

ExternalProject_Add(
    sphinxbase
    GIT_REPOSITORY      "https://github.com/cmusphinx/sphinxbase.git"
    GIT_TAG             "e34b1c632392276101ed16e8a05862e43f038a7c"
    SOURCE_DIR          ${sphinxbase_SOURCE_DIR}
    # Specify installation prefix for configure.sh (autogen.sh).
    CONFIGURE_COMMAND   ./autogen.sh --prefix=${CMAKE_INSTALL_PREFIX}
    BUILD_COMMAND       ${MAKE}
    UPDATE_COMMAND      ""
    # Fake installation: copy installed files into DESTDIR.
    INSTALL_COMMAND     make DESTDIR=${sphinxbase_DESTDIR} install
    ...
)
# Actually install subproject.
install(
    DIRECTORY ${sphinxbase_DESTDIR}/
    DESTINATION "/"
    USE_SOURCE_PERMISSIONS # Remain permissions (rwx) for installed files
)

Note, that root directory is used as DESTINATION. This is because files under sphinxbase_DESTDIR directory already located in accordance to CMAKE_INSTALL_PREFIX, which is passed as --prefix option to configure.sh (autogen.sh in the given case).

If you know, that subprojects installs its files only under installation prefix (given by --prefix), you can make main project installation more packaging-friendly:

install(
    DIRECTORY ${sphinxbase_DESTDIR}/${CMAKE_INSTALL_PREFIX}/
    DESTINATION "."
    USE_SOURCE_PERMISSIONS
)

Because now relative path is used for DESTINATION option, the project will correctly support packaging. For example, make DESTDIR=<...> install will work for main project too.


Note, that even if ExternalProject_Add is used for build CMake subproject, targets created in this subroject are not seen by the main project.

like image 140
Tsyvarev Avatar answered Sep 28 '22 17:09

Tsyvarev