Sembra che CMake ExternalProject
assuma sempre la directory radice del progetto esterno come directory di origine. Ma cosa succede se questo non è il caso ?CMake ExternalProject: come specificare il percorso relativo alla radice CMakeLists.txt?
consideri il seguente esempio:
Il progetto esterno utilizza questo layout directory:
libfoo.git <--- ExternalProject assumes this as source dir.
├── ...
└── libfoo <--- However, the actual source directory is this!
├── CMakeLists.txt
└── ...
Nel progetto a seconda libfoo
è configurato in questo modo:
ExternalProject_Add(libfoo
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/EP_libfoo"
GIT_REPOSITORY "<link to remote which hosts libfoo.git>"
GIT_TAG "<some hash>"
)
La compilazione fallisce poi con il seguente messaggio di errore:
$ cmake -H/path/to/source-dir -B/path/to/build-dir
...
$ cmake --build /path/to/build-dir/ --target all
...
CMake Error: The source directory "/path/to/build-dir/EP_libfoo/src/libfoo" does not appear to contain CMakeLists.txt.
...
$
Così, come sottolineato nella struttura delle directory di cui sopra, CMake pensa che la radice del progetto esterno è
/path/to/build-dir/EP_libfoo/src/libfoo
quando, in realtà, è
/path/to/build-dir/EP_libfoo/src/libfoo/libfoo
i miei tentativi di risolvere questo problema:
Purtroppo, cambiando l'argomento
SOURCE_DIR
delExternalProject
ha funzionato con , poiché il valore di questa variabile viene utilizzato come posizione su in cui è clonato il repository git dilibfoo
. Ciò si traduce in un inferno ricorsivo di dipendenza che non può essere rotto.Modifica del layout di directory di
libfoo
in conformità conExternalProject
. Ovviamente, questo potrebbe funzionare ma potrebbe non funzionare per altre librerie di terze parti (di sola lettura) .Abuso della fase di aggiornamento/patch di
ExternalProject
, ad es. specificandoset(EP_LIBFOO_DIR "${CMAKE_CURRENT_BINARY_DIR}/EP_libfoo") ExternalProject_Add(libfoo PREFIX "${EP_LIBFOO_DIR}" GIT_REPOSITORY "<link to remote which hosts libfoo.git>" GIT_TAG "<some hash>" # Copy the content of `<...>/libfoo/libfoo` into `<...>/libfoo`. # Note to self: using symlinks instead copying is too platform-specific. PATCH_COMMAND ${CMAKE_COMMAND} -E copy_directory "${EP_LIBFOO_DIR}/src/libfoo/libfoo" "${EP_LIBFOO_DIR}/src/libfoo" )
Questo funziona ma è maniacale e molto incline a fallire con altri progetti esterni.
Edificio su solution to another problem: aggiungere uno temporaneo
CMakeLists.txt
nella posizione in cui CMake lo assume. Questo file temporaneo include poi laCMakeLists.txt
attuale:set(EP_LIBFOO_DIR "${CMAKE_CURRENT_BINARY_DIR}/EP_libfoo") set(GENERATED_DIR "${CMAKE_BINARY_DIR}/generated") file(MAKE_DIRECTORY ${GENERATED_DIR}) file(WRITE ${GENERATED_DIR}/CMakeLists.txt "cmake_minimum_required(VERSION 3.0)\n" "add_subdirectory(libfoo)\n" ) ExternalProject_Add(libfoo PREFIX "${EP_LIBFOO_DIR}" GIT_REPOSITORY "<link to remote which hosts libfoo.git>" GIT_TAG "<some hash>" # Copy the UPDATE_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/generated/CMakeLists.txt ${EP_LIBFOO_DIR}/src/libfoo )
Questo funziona come bene e si sente meglio rispetto alla soluzione precedente.
Tuttavia, fa un più elegante esistono per fare lo stesso?
La funzione è stata accettata ed è disponibile a partire da CMake 3.7: https://cmake.org/cmake/help/v3.7/module/ExternalProject.html – Matthew