¿Cuál es el equivalente de CMake de 'configure --prefix = DIR && make all install'?

386

Hago cmake . && make all install. Esto funciona, pero se instala en /usr/local.

Necesito instalar en un prefijo diferente (por ejemplo, a /usr).

¿Cuál es la línea de comando cmakey makepara instalar en /usrlugar de /usr/local?

Andrei
fuente
1
Esta es una gran pregunta para cambiar el directorio de instalación sobre la marcha, pero ¿por qué es una necesidad aparentemente tan común? Desde mi punto de vista, la respuesta debería ser NO utilizar una opción de línea de comando, en su lugar edite la base CMakeLists.txtpara que pueda configurarla y olvidarla. No estoy diciendo que no haya un caso de uso común para cambiar el directorio de instalación sobre la marcha, claramente lo está juzgando por el número de votos, soy bastante nuevo en CMake y tengo curiosidad cuando surge este problema.
CivFan
8
@CivFan es para atender a los usuarios que desean construir e instalar el proyecto en una ubicación particular, pero no son las mismas personas que los desarrolladores / mantenedores del proyecto.
David Röthlisberger
44
@CivFan Entonces, como mantenedor, no es raro que pruebe mi make installruta temporal para asegurarme de que todo lo que necesita ser instalado se haya instalado en la ubicación correcta sin estropear mi máquina de desarrollo. Solo un ejemplo. Otro caso es la compilación cruzada para otra arquitectura.
Daniel
55
@CivFan: Necesito esto porque quiero construir un paquete RPM. Si tuviera que cambiar el CMakeLists.txt, entonces necesito parchear la fuente original. Solo tener una opción de línea de comando me permite obtener las rutas directamente en el specarchivo Fedora .
Martin Ueding
1
@CivFan (y otros que leen esto) Para su información, en general se considera una mala idea editar el CMakeLists.txtarchivo si solo está compilando e instalando software; el "consumidor" preferido es anular / configurar variables desde la línea de comandos o el archivo de caché inicial, etc. forma de configurar las opciones.
Ryan Pavlik

Respuestas:

444

Puede pasar cualquier variable CMake en la línea de comando, o editar las variables en caché usando ccmake / cmake-gui. En la línea de comando,

cmake -DCMAKE_INSTALL_PREFIX: RUTA = / usr. && hacer que todo se instale

Configuraría el proyecto, construiría todos los objetivos e instalaría el prefijo / usr. El tipo (PATH) no es estrictamente necesario, pero causaría que cmake-gui basado en Qt presente el diálogo de selección de directorio.

Algunas adiciones menores como comentarios dejan en claro que proporcionar una equivalencia simple no es suficiente para algunos. La mejor práctica sería utilizar un directorio de compilación externo, es decir, no la fuente directamente. También para usar una sintaxis CMake más genérica que abstraiga el generador.

mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX: PATH = / usr .. && cmake --build. --target install --config Release

Puede ver que se alarga bastante, y ya no es directamente equivalente, pero está más cerca de las mejores prácticas en una forma bastante concisa ... El --config solo lo usan generadores de configuraciones múltiples (es decir, MSVC), ignorado por otros.

Marcus D. Hanwell
fuente
21
¿Se pregunta qué es: PATH? Es útil para cmake-gui, ya que ayuda a elegir el widget para esa variable. Ver documento en linux.die.net/man/1/cmake-gui (sección de configuración)
albfan
2
Proporcionan sugerencias para la GUI de CMake como se indicó, todo en CMake es efectivamente una cadena, pero configurar RUTA, FILEPATH, STRING, BOOL, etc. ayuda a la GUI a presentar un widget más apropiado.
Marcus D. Hanwell
13
También puede usar: "cmake --build --target install". en lugar de hacer.
RobertJMaynard
2
¿Cuál es el punto para after / usr? /usr .
bodacydo
55
@bodacydo ubicación de la carpeta con CMakeLists.txt que estamos generando.
Kamiccolo
48

La parte ": RUTA" en la respuesta aceptada puede omitirse. Esta sintaxis puede ser más memorable:

cmake -DCMAKE_INSTALL_PREFIX=/usr . && make all install

... como se usa en las respuestas aquí .

user2023370
fuente
77
:PATHNo es un error .
kirbyfan64sos
29

Tenga en cuenta que tanto en CMake como en Autotools no siempre tiene que establecer la ruta de instalación en el momento de la configuración. Puede usar DESTDIR en el momento de la instalación (consulte también aquí ) como en:

make DESTDIR=<installhere> install

Vea también esta pregunta que explica la sutil diferencia entre DESTDIR y PREFIX.

Esto está destinado a instalaciones por etapas y para permitir el almacenamiento de programas en una ubicación diferente de donde se ejecutan, por ejemplo, a /etc/alternativestravés de enlaces simbólicos.

Sin embargo, si su paquete es reubicable y no necesita ninguna ruta codificada (prefijo) establecida a través de la etapa de configuración, puede omitirlo. Entonces en lugar de:

cmake -DCMAKE_INSTALL_PREFIX=/usr . && make all install

usted correría:

cmake . && make DESTDIR=/usr all install

Tenga en cuenta que, como señala user7498341, esto no es apropiado para los casos en los que realmente debería usar PREFIX.

Bruce Adams
fuente
99
Me gusta mostrar el uso de DESTDIR. Pero en realidad esto está mal. Debe consultar los documentos de cmake cmake.org/cmake/help/v3.0/variable/CMAKE_INSTALL_PREFIX.html ... make DESTDIR=/home/john installque instalará el software en cuestión utilizando el prefijo de instalación, por ejemplo, "/ usr / local" antepuesto con el valor DESTDIR que finalmente da "/ home / john / usr / local".
Joakim
1
No creo que sea contradictorio. Si su paquete es reubicable, no necesita CMAKE_INSTALL_PREFIX, o más bien puede elegir cualquiera de los métodos. Si no es así, porque CMAKE_INSTALL_PREFIX se horneará en algún lugar en el momento de la compilación.
Bruce Adams el
si sabe que su generador es Makefile ... Prefiero cmake --build build --target install -- DESTDIR=/usrtener en cuenta: esto también debería funcionar con el generador Ninja (las reglas parecen contener $ENV{DESTDIR})
Mizux
@Joakim tanto como me gustaría usar CMAKE_INSTALL_PREFIX, al hacerlo, incorporó la ruta de instalación en los archivos compilados. Resulta que simplemente estaba creando un paquete .rpm, por lo que no funcionaría. DESTDIR funcionó a las mil maravillas para poner las cosas en buildroot.
Sr. Redstoner
18

La forma en que construyo los proyectos CMake multiplataforma es la siguiente:

/project-root> mkdir build
/project-root> cd build
/project-root/build> cmake -G "<generator>" -DCMAKE_INSTALL_PREFIX=stage ..
/project-root/build> cmake --build . --target=install --config=Release
  • Las dos primeras líneas crean el directorio de compilación fuera de la fuente
  • La tercera línea genera el sistema de compilación que especifica dónde colocar el resultado de la instalación (que siempre coloco ./project-root/build/stage, la ruta siempre se considera relativa al directorio actual si no es absoluta)
  • La cuarta línea construye el proyecto configurado .con el sistema de construcción configurado en la línea anterior. Ejecutará el installdestino que también construye todos los objetivos dependientes necesarios si es necesario construirlos y luego copia los archivos en el CMAKE_INSTALL_PREFIX(que en este caso es ./project-root/build/stage. Para compilaciones de configuración múltiple, como en Visual Studio, también puede especificar la configuración con La --config <config>bandera opcional .
  • La buena parte cuando se usa el cmake --buildcomando es que funciona para todos los generadores (es decir, makefiles y Visual Studio) sin necesidad de comandos diferentes.

Luego uso los archivos instalados para crear paquetes o incluirlos en otros proyectos ...

toeb
fuente
Gracias por la explicación paso a paso! OMI esta es la única manera, de lo contrario todo el punto de cmake (independencia de la plataforma) se desecha ...
helmesjo
1
¿olvidó incluir la ruta a las fuentes (../) en la línea 3? Por cierto, esta debería ser la respuesta aceptada.
Slava
1
La línea 3 debería sercmake -G "<generator>" -DCMAKE_INSTALL_PREFIX=stage ..
codenamezero
1
Como nota adicional, pragmáticamente, las personas usan make -j $(nproc), para especificar el número de hilos de compilación, hacer cmake --build . --target=install --config=Release -- -j 8para el generador de Makefile o cmake --build . --target=install --config=Release -- /m:8para el generador de Visual Studio con 8 hilos. En realidad, puede pasar cualquier parámetro de la línea de comandos después de--
Cloud
1
@MrRedstoner -jno es una bandera para cmake, todas las banderas que vienen después --pasan al sistema de compilación subyacente ...
Nube
4

En cuanto a la respuesta de Bruce Adams:

Tu respuesta crea confusión peligrosa. DESTDIR está diseñado para instalaciones fuera del árbol raíz. Permite ver lo que se instalaría en el árbol raíz si no se especifica DESTDIR. PREFIX es el directorio base en el que se basa la instalación real.

Por ejemplo, PREFIX = / usr / local indica que el destino final de un paquete es / usr / local. El uso de DESTDIR = $ HOME instalará los archivos como si $ HOME fuera la raíz (/). Si, por ejemplo, DESTDIR, fuera / tmp / destdir, se podría ver qué afectaría 'make install'. En ese espíritu, DESTDIR nunca debería afectar a los objetos construidos.

Un segmento de archivo MAKE para explicarlo:

install:
    cp program $DESTDIR$PREFIX/bin/program

Los programas deben suponer que PREFIX es el directorio base del directorio final (es decir, de producción). La posibilidad de vincular un programa instalado en DESTDIR = / something solo significa que el programa no accede a los archivos basados ​​en PREFIX ya que simplemente no funcionaría. cat (1) es un programa que (en su forma más simple) puede ejecutarse desde cualquier lugar. Aquí hay un ejemplo que no lo hará:

prog.pseudo.in:
    open("@prefix@/share/prog.db")
    ...

prog:
    sed -e "s/@prefix@/$PREFIX/" prog.pseudo.in > prog.pseudo
    compile prog.pseudo

install:
    cp prog $DESTDIR$PREFIX/bin/prog
    cp prog.db $DESTDIR$PREFIX/share/prog.db

Si trató de ejecutar prog desde otro lugar que no sea $ PREFIX / bin / prog, nunca se encontrará prog.db, ya que no está en su ubicación esperada.

Finalmente, / etc / alternative realmente no funciona de esta manera. Hay enlaces simbólicos a los programas instalados en el árbol raíz (por ejemplo, vi -> / usr / bin / nvi, vi -> / usr / bin / vim, etc.).

usuario7498341
fuente
1
Esta respuesta podría colocarse mejor como una respuesta a stackoverflow.com/questions/11307465/destdir-and-prefix-of-make
Bruce Adams
2

Se considera una mala práctica invocar el generador real (por ejemplo, a través de make) si se usa CMake . Es muy recomendable hacerlo así:

  1. Configurar fase:

    cmake -Hfoo -B_builds/foo/debug -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_DEBUG_POSTFIX=d -DCMAKE_INSTALL_PREFIX=/usr
    
  2. Fases de construcción e instalación

    cmake --build _builds/foo/debug --config Debug --target install
    

Al seguir este enfoque, el generador se puede cambiar fácilmente (por ejemplo, -GNinjapara Ninja ) sin tener que recordar ningún comando específico del generador.

Florian Wolters
fuente
1
La respuesta podría haber sido mejor si se proporcionara una explicación de todos los argumentos utilizados y por qué se utilizan. En particular, ¿cuál es el punto del --configargumento?
Dmitry Kabanov
2

Comenzando con CMake 3.15, la forma correcta de lograr esto sería usar:

cmake --install <dir> --prefix "/usr"

Documentación oficial

ExaltadoBagel
fuente