Как перекрестно компилировать для 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 бит".
??
Ответы
Ответ 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 на основе целевой платформы/арки.