web-dev-qa-db-fra.com

La bonne façon de forcer une compilation 32 bits à l'aide de CMake

Désolé qu'il y ait beaucoup de questions similaires, mais je trouve que la recherche sur Google pour les requêtes CMake produit toujours des scénarios similaires mais pas les mêmes, des commandes CMake en conflit et ainsi de suite!

J'ai besoin de forcer mon projet à construire des binaires 32 bits car je dois créer un lien avec une bibliothèque qui n'est disponible qu'en 32 bits. J'ai diagnostiqué cela sur la base de messages d'erreur tels que:

/usr/bin/ld: i386 architecture of input file `*external-32bit-lib*' is incompatible with i386:x86-64 output

D'après ce que je comprends, je dois donc utiliser:

set (CMAKE_CXX_FLAGS "-m32")

Cela change les choses - je reçois maintenant plusieurs erreurs comme:

/usr/bin/ld: i386 architecture of input file `*project-output-lib*' is incompatible with i386:x86-64 output

ET obtenez toujours les mêmes erreurs pour la bibliothèque externe. I pensez c'est parce que le -m32 fait gcc générer des binaires 32 bits, mais ld essaie toujours de sortie 64 bits? De plus, Google n'a pas réussi à résoudre ce problème, donc si quelqu'un pouvait vérifier que j'ai raison et donner la bonne façon de le faire, je serais très reconnaissant!

Merci beaucoup!

47
devrobf

Si vous souhaitez compiler et lier pour 32 bits en utilisant cmake, utilisez ceci pour créer des bibliothèques et des binaires:

Création de bibliothèques:

add_library(mylib SHARED my_source.c)
set_target_properties(mylib PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")

création d'exécutables:

add_executable(mybin sources.c)
set_target_properties(mybin PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")

J'espère que cela t'aides,

40
ant2009

Même si cela semble être un travail supplémentaire, je pense qu'une solution appropriée consiste à utiliser le fichier de chaîne d'outils dans ce cas. Quelque chose comme:

# the name of the target operating system
set(CMAKE_SYSTEM_NAME Linux)

# which compilers to use for C and C++
set(CMAKE_C_COMPILER gcc)
set(CMAKE_C_FLAGS -m32)
set(CMAKE_CXX_COMPILER g++)
set(CMAKE_CXX_FLAGS -m32)

# here is the target environment located
set(CMAKE_FIND_ROOT_PATH   /usr/i486-linux-gnu )

# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search
# programs in the Host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

L'utilisation est alors simplement:

$ cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake /path/to/source

La partie importante ici est que l'on est maintenant capable de spécifier un chemin de répertoire racine (CMAKE_FIND_ROOT_PATH) qui devrait être utilisé pour rechercher une bibliothèque tierce. En effet, votre compilateur n'est peut-être pas assez intelligent pour savoir où rechercher une bibliothèque x86 Qt sur un système x86_64.

Avoir un fichier de chaîne d'outils permet d'en spécifier un autre sur une base de compilateur par, et vous devriez pouvoir ajuster l'option lors de la compilation en 32 bits à partir d'un environnement Windows.

De nos jours, c'est un travail supplémentaire car la compilation de 32 bits à partir d'un système d'exploitation Linux x86_64 est à peu près triviale, mais cette solution fonctionnera pour d'autres configurations plus exotiques.

Pour plus d'informations sur le fichier de chaîne d'outils, on peut vérifier par exemple:

17
malat

CMAKE_CXX_FLAGS affecte uniquement le compilateur C++. Vous devez probablement également définir le drapeau du compilateur C:

set (CMAKE_C_FLAGS "-m32")
8
sakra

Il semble que vous n'ayez pas non plus transmis m32 à LFLAGS, ou qu'il existe d'anciens fichiers obj. Assurez-vous de nettoyer d'abord.

Cette question est similaire à la vôtre: cmake, gcc, cuda et -m32

4
Fredrik E

Utilisation TRY_RUN commande par la source suivante.

size.cpp:

#include <cstdlib>

int main( int argc, char** argv )
{
  size_t size = sizeof(void*);
  if ( size == 4 )
    return 0;
  return 1;
}

CMakeLists.txt:

TRY_RUN(RUN_RESULT_VAR COMPILE_RESULT_VAR ${your_temp_dir} size.cpp RUN_OUTPUT_VARIABLE IS_64_SYSTEM)
IF(IS_64_SYSTEM)
  MESSAGE(FATAL_ERROR "64 compiling not allowed!")
ENDIF(IS_64_SYSTEM)

Il fonctionnera sur tous les compilateurs standard.

3
Naszta

J'ai utilisé l'approche de malat et créé un fichier Toolchain.

J'ai un fichier Toolchain qui fonctionne sur certaines distributions Linux, peut-être qu'il vous donnera de l'inspiration. Cela peut fonctionner pour vous tel quel, ou vous pouvez avoir besoin d'autres vilains hacks pour obtenir d'autres scripts cmake sur lesquels vous comptez pour travailler ou avec:

https://github.com/visualboyadvance-m/visualboyadvance-m/blob/master/cmake/Toolchain-cross-m32.cmake

1
Rafael Kitover