Подтвердить что ты не робот

Как перекрестно компилировать для linux x86 с linux amd64, cmake и g++?

+1 для каждой части информации, которая помогает завершить всю картину. Вам не нужно знать весь ответ. Я по достоинству оценю отдельные части головоломки. Спасибо.

Я собираюсь попробовать свою первую кросс-компиляцию. Я искал как SO, так и сеть и нашел много информации, но я не всегда знаю, как собрать эти штуки, потому что все еще есть некоторые недостающие части.

Мой хост: linux Kubuntu amd64.
Цель: linux kubuntu x86 (32bit) (должно быть легко, нет?)
Инструменты: g++ и cmake.

Вот информация, которую я нашел:

Как скомпилировать 32-битный двоичный файл на 64-битной Linux-машине с gcc/cmake
упоминает экспорт CFLAGS = -m32. Это одна часть.

Кросс-платформенная: выбор типов данных для использования 32/64 бит
упоминает типы данных. Возможно, мне придется обратить внимание на это в моем коде.

#ifdef для 32-разрядной платформы
 #ifdef для 32-разрядной платформы
ссылки на следующее, хотя я еще не уверен, как его использовать:
http://predef.sourceforge.net/prearch.html

http://ww.ubuntuforums.org/showthread.php?t=1377396
Я сделал: sudo apt-get install g++ - multilib

недостающие части:

В идеале, когда я делаю "make" (с cmake), он должен выплюнуть как двоичный файл amd64, так и x86.

Часть моего CMakeLists.txt выглядит так:

add_definitions(-Wall -pthread)
add_executable (../run.amd64 user.cpp time.cpp init.cpp utils.cpp main.cpp)
target_link_libraries(../run.amd64 cppcms dbixx config++ ctemplate)

Как мне добавить флаг -m32 для создания второго исполняемого файла?

Должен ли я сделать только один исполняемый файл (например, для тестирования и отладки), как сообщить cmake для создания одного или обоих двоичных файлов?

Кроме того, вы можете видеть, что я использую некоторые сторонние библиотеки, некоторые из которых мне пришлось скомпилировать. Означает ли это, что мне нужно скомпилировать каждый из этих двоичных файлов для целевого хоста? Некоторые используют cmake, а некоторые используют:./configure; сделать;
Как мне сделать компиляцию этих библиотек для целевого хоста (флаги для использования и т.д.)?

Примечание: динамически связанные библиотеки уже скомпилированы и установлены на целевом компьютере, поэтому, возможно, мне не нужно беспокоиться об этом шаге... Я не уверен: это одна из моих недостающих частей...

Мне нужен учебник или, по крайней мере, некоторые недостающие части. Я обновлю это сообщение с более подробной информацией о том, что я достиг и как.

Спасибо.

P.S.

Возможно ли вообще?

Поиск больше, я нашел это:
http://www.mail-archive.com/[email protected]/msg26265.html
"Оригинальный дизайн, похоже, не предназначен для чего-то большего, чем перекрестные компиляции windows-linux или linux-windows".
cmake НЕ тестируется на linux amd64 до linux x86.

http://www.cmake.org/Wiki/CMake_Cross_Compiling#FAQ.2FPotential_Problems
"В смешанных 32/64 бит установках Linux кросс-компиляция не может использоваться для сборки только для 32/64 бит".

??

4b9b3361

Ответ 1

Если вы хотите использовать файл toolchain, есть более простое решение (IMHO), чем предлагаемое @auledoom. Вам вообще не нужно писать сценарии оболочки оболочки, просто поместите это в файл toolchain:

# 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 -m32)
set(CMAKE_CXX_COMPILER g++ -m32)

Это сделает его "переменной списка" в cmake. Это решение работает для меня. Преимущество файла toolchain заключается в том, что вы также можете определять пути для 32-битных библиотек и т.д., Которые обычно отличаются от стандартных путей.

Ответ 2

Это решение позволит вам перекрестно скомпилировать ваш проект cmake на целевом элементе 32bits для Linux-хоста на системах с поддержкой нескольких архивов. Он использует "поддельную" инструментальную комбинацию cmake, поэтому CMAKE каким-то образом "верит" ее в 32-битную систему, поэтому никаких дополнительных изменений в ваших файлах проекта cmake не требуется, нет специальных конфигураций, нет специальных настроек (почти все).

  • Установите поддержку multilib:

    $sudo apt-get install gcc-multilib
    
  • Создайте "поддельную" инструментальную цепочку linux32

Сначала мы создаем "поддельный" компилятор i686. Перейдите туда, где находится ваш CMakeLists.txt и создайте каталог bin. Откройте ваш предпочтительный редактор и создайте этот простой bash script для компилятора gcc.

#!/bin/sh
/usr/bin/gcc -m32 "[email protected]"

Как вы видите, он просто обращается к системному компилятору с добавлением флага -m. Сохраните это как i686-linux-gnu-gcc. Сделайте то же самое для компилятора g++

#!/bin/sh
/usr/bin/g++ -m32 "[email protected]"

Сохраните его как i686-linux-gnu-g++. Не забудьте установить исполняемые флаги на этих скриптах

Создайте также символическую ссылку на двоичную систему system в этой форме

$ln /usr/bin/ar i686-linux-gnu-ar

Наконец, создайте файл toolchain-linux32.cmake

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

# Which compilers to use for C and C++
set(CMAKE_C_COMPILER ${CMAKE_SOURCE_DIR}/bin/i686-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER ${CMAKE_SOURCE_DIR}/bin/i686-linux-gnu-g++)

и создайте каталог сборки и вызовите cmake с помощью файла toolchain в качестве аргумента

$mkdir build && cd build
$cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain-linux32.cmake ..

и ваше дело!!!!!

Я напишу более полное руководство здесь, в котором описаны некоторые проблемы, которые у меня есть с библиотеками, не совместимыми с несколькими lib

Ответ 3

это упрощенная версия того, что я использую, и она создает двоичные файлы x86:

set( TargetName myExe )
set( SOURCES a.cpp b.cpp )
add_executable( ${TargetName} ${SOURCES} )
target_link_libraries( ${TargetName} m pthread stdc++ )
set_target_properties( ${TargetName} PROPERTIES COMPILE_FLAGS -m32 LINK_FLAGS -m32 )

Кроме того, вы будете использовать add_definitions для установки флагов компилятора типа -W -Ox -Dxxx и т.д.

Все приведенные выше строки фактически разделены на отдельные файлы cmake и, чтобы получить один файл для создания нескольких исполняемых файлов, я генерирую мастер файл cmake, содержащий все различные конфигурации, которые я хочу построить:

project( myProject )
set( SOURCES a.cpp b.cpp )
if( ${ConfigurationType} strequal "Debugx86" )
  include( debugopts.cmake )
  include( x86.cmake )
  include( executable.cmake )
  ...
elseif( ${ConfigurationType} strequal "Releasex64" )
  include( debugopts.cmake )
  include( x86.cmake )
  include( executable.cmake )
  ...
etc

Затем есть оболочка драйвера script, чтобы собрать все. Для установки дополнительных опций требуются параметры командной строки и вы можете выбрать все или только одну конфигурацию. Вот его часть:

if [ "$myConfig" = "all" -o "$myConfig" = "Debugx86" ]; then
  mkdir -p project_Debugx86
  cd project_Debugx86
  cmkake "$sourceDir" "$cmakeOpts" -DConfigurationType="Debugx86"
  make clean
  make "$makeopts"
fi
if [ "$myConfig" = "all" -o "$myConfig" = "Releasex64" ]; then
  mkdir -p project_Releasex64
  cd project_Releasex64
  cmkake "$sourceDir" "$cmakeOpts" -DConfigurationType="Releasex64
  make clean
  make "$makeopts"
fi

Хотя это не совсем то, о чем вы просите, оно работает безупречно и делает то же самое. (Не уверен, возможно ли в cmake определить любое количество целей в самом cmake и объединить их в один файл.) Для написания генератора для этих файлов требуется некоторое время, но как только это будет сделано, все, что я делаю необходимо указать генератор в каталог с источниками, запустить ir, а затем вызвать сборку script, чтобы сделать все.

Ответ 4

Все, что вам нужно, это добавить -m32 в CFLAGS и CXXFLAGS при запуске CMake. Это можно сделать с помощью переменных среды:

$ CFLAGS=-m32 CXXFLAGS=-m32 cmake .

или путем установки соответствующих переменных CMake:

$ cmake -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32 .

Это можно легко протестировать с помощью простого проекта CMake:

$ uname -m
x86_64
$ CFLAGS=-m32 CXXFLAGS=-m32 cmake .
-- The C compiler identification is GNU 4.8.1
-- The CXX compiler identification is GNU 4.8.1
....
$ make 
Scanning dependencies of target foo
[100%] Building CXX object CMakeFiles/foo.dir/foo.cc.o
Linking CXX executable foo
[100%] Built target foo
$ file foo
foo: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x5b1871446c92cbdcbf905583e16189f68f3bf5f2, not stripped

где CMakeLists.txt - тривиальный файл CMake:

project(TEST)
add_executable(foo foo.cc)

и foo.cc выглядит следующим образом:

int main () {}

Ответ 5

Вот основной рецепт, который я использую все время для проектов cmake.

OPTION(FORCE32 "Force a 32bit compile on 64bit" OFF)
IF(FORCE32)
    if(APPLE)
        SET(CMAKE_OSX_ARCHITECTURES "i386")
    else()
        SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
        SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
    endif()
ENDIF()

IF(APPLE)
    set(BIN_LIBROOT "macosx")
ELSE()
    if(CMAKE_SIZEOF_VOID_P MATCHES "8" AND NOT(FORCE32) )
        set(BIN_LIBROOT "linux64")
        set(CMAKE_EXECUTABLE_SUFFIX ".bin.x86_64")
        set(BIN_RPATH "\$ORIGIN/lib64")
    else()
        set(BIN_LIBROOT "linux")
        set(CMAKE_EXECUTABLE_SUFFIX ".bin.x86")
        set(BIN_RPATH "\$ORIGIN/lib")
    endif()

    set(CMAKE_SKIP_BUILD_RPATH TRUE)
    set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
    set(CMAKE_INSTALL_RPATH ${BIN_RPATH})
    set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
ENDIF()

Тогда у каждой цели автоматически есть расширение .bin. ${arch}, и я никогда не должен думать об этом для любых целей, которые я добавляю. ${BIN_LIBROOT} полезен, если у вас есть куча предварительно скомпилированных библиотек, так как вы можете использовать это для динамического поиска libs в ваших личных lib dirs на основе целевой платформы/арки.