Как сделать кросс-компиляцию для linux x86 с linux amd64, cmake и g ++? - PullRequest
26 голосов
/ 09 ноября 2010

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

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

Мой хост: linux Kubuntu amd64.
Цель: linux kubuntu x86 (32 бита) (должно быть легко, нет?)
Инструменты: 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 установить 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; сделать;
Как мне скомпилировать эти библиотеки для целевого хоста (флаги и т. Д.)?

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

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

Спасибо.

приписка

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

Ища больше, я нашел это:
http://www.mail-archive.com/cmake@cmake.org/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-битных версий».

??

Ответы [ 5 ]

8 голосов
/ 05 июля 2012

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

# 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. Это решение работает для меня. Преимущество файла инструментария заключается в том, что вы также можете определить пути для 32-битных библиотек и т. Д., Которые обычно отличаются от стандартных путей.

7 голосов
/ 01 декабря 2011

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

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

    $sudo apt-get install gcc-multilib
    
  2. Создание "фальшивого" набора инструментов linux32

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

#!/bin/sh
/usr/bin/gcc -m32 "$@"

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

#!/bin/sh
/usr/bin/g++ -m32 "$@"

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

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

$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 с файлом цепочки инструментов в качестве аргумента

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

и все готово !!!!!

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

5 голосов
/ 09 ноября 2010

это упрощенная версия того, что я использую, и она создает двоичные файлы 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

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

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, а затем вызвать скрипт сборки, чтобы все сделать.

4 голосов
/ 17 июня 2014

Все, что вам нужно, это добавить -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 () {}
2 голосов
/ 08 августа 2013

Вот основной рецепт, который я все время использую для проектов 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} полезен, если у вас есть несколько предварительно скомпилированных библиотек, которые вы можете использовать для динамического поиска библиотек в ваших личных библиотеках на основе целевой платформы / архива.

...