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.
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.
¿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
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.
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:
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 ...
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á:
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.).
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.
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:
CMakeLists.txt
para 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.make install
ruta 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.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 elspec
archivo Fedora .CMakeLists.txt
archivo 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.Respuestas:
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,
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.
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.
fuente
/usr .
La parte ": RUTA" en la respuesta aceptada puede omitirse. Esta sintaxis puede ser más memorable:
... como se usa en las respuestas aquí .
fuente
:PATH
No es un error .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:
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/alternatives
travé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:
usted correría:
Tenga en cuenta que, como señala user7498341, esto no es apropiado para los casos en los que realmente debería usar PREFIX.
fuente
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 install
que 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".cmake --build build --target install -- DESTDIR=/usr
tener en cuenta: esto también debería funcionar con el generador Ninja (las reglas parecen contener$ENV{DESTDIR}
)La forma en que construyo los proyectos CMake multiplataforma es la siguiente:
./project-root/build/stage
, la ruta siempre se considera relativa al directorio actual si no es absoluta).
con el sistema de construcción configurado en la línea anterior. Ejecutará elinstall
destino que también construye todos los objetivos dependientes necesarios si es necesario construirlos y luego copia los archivos en elCMAKE_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 .cmake --build
comando 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 ...
fuente
cmake -G "<generator>" -DCMAKE_INSTALL_PREFIX=stage ..
make -j $(nproc)
, para especificar el número de hilos de compilación, hacercmake --build . --target=install --config=Release -- -j 8
para el generador de Makefile ocmake --build . --target=install --config=Release -- /m:8
para el generador de Visual Studio con 8 hilos. En realidad, puede pasar cualquier parámetro de la línea de comandos después de--
-j
no es una bandera para cmake, todas las banderas que vienen después--
pasan al sistema de compilación subyacente ...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:
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á:
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.).
fuente
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í:Configurar fase:
Fases de construcción e instalación
Al seguir este enfoque, el generador se puede cambiar fácilmente (por ejemplo,
-GNinja
para Ninja ) sin tener que recordar ningún comando específico del generador.fuente
--config
argumento?Comenzando con CMake 3.15, la forma correcta de lograr esto sería usar:
Documentación oficial
fuente