2010-11-09 120 views
25

對於幫助完成整個圖片的每條信息+1。你不需要知道整個答案。我會欣賞拼圖的各個部分。謝謝。如何使用linux amd64,cmake和g ++進行linux x86交叉編譯?

我即將嘗試我的第一次交叉編譯。我搜索到了這個和網頁,發現了許多信息,但我並不總是知道如何將這些信息放在一起,因爲還有一些缺失的部分。

我的主機:linux Kubuntu amd64。
對象:Linux kubuntu x86(32bit)(應該很容易,不是?)
工具:g ++和cmake。

這裏是我找到的信息:

How to compile a 32-bit binary on a 64-bit linux machine with gcc/cmake
提到出口CFLAGS = -m32。這是一塊。

Cross-platform: selecting data types to use 32/64 bit
提及數據類型。我可能不得不在我的代碼中注意這一點。

#ifdef for 32-bit platform
的#ifdef爲32位平臺
指向以下,雖然我也不太清楚但如何使用它:
http://predef.sourceforge.net/prearch.html

http://ww.ubuntuforums.org/showthread.php?t=1377396
我:sudo易於得到安裝G ++ - multilib的

缺失的部分:

理想的情況下,當我做 '做'(用C make),它應該吐出一個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.

有沒有可能?

搜索多了,我發現這一點:「最初的設計似乎並沒有設計任何東西比Linux或Windows的Linux的窗口交叉編譯了。」
http://www.mail-archive.com/[email protected]/msg26265.html

cmake未針對linux amd64至linux x86進行測試。

http://www.cmake.org/Wiki/CMake_Cross_Compiling#FAQ.2FPotential_Problems
「在混合32/64位Linux安裝上,交叉編譯不能用於僅爲32/64位構建。」

??

回答

5

這是我所使用的簡化版本,它也創造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 

然後有一個驅動程序shell腳本來構建它。它需要命令行選項來設置一些額外的選項,並選擇構建一切或只有一個配置。這是它的一部分:

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運行,然後調用構建腳本來創建所有內容。

+0

1感謝您的詳細寫了。我會研究這一切,看看我能做些什麼。 – augustin 2010-11-09 08:36:54

6

該解決方案將允許您在具有多拱支持的系統上以32位爲目標的linux64主機上交叉編譯您的cmake項目。 它使用了一個「假的」cmake工具鏈,因此CMAKE以某種方式「相信」它在32位系統上,所以在你的cmake項目文件中不需要額外的修改,沒有特殊的配置,也沒有特別的設置。

  1. 安裝multilib的支持:

    $sudo apt-get install gcc-multilib 
    
  2. 創建一個 「假」 linux32鏡像工具鏈

首先,我們創建了一個 「假」 i686的編譯器。轉到您的CMakeLists.txt所在的位置並創建一個bin目錄。打開你喜歡的編輯器併爲gcc編譯器創建這個簡單的bash腳本。

#!/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 ++。請記住,設置可執行標誌這一scrips

這種形式也創建符號鏈接到系統Ar的兩種

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

最後創建工具鏈,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 .. 

和你做的!

我會寫一個更完整的指南here,如果你想使用比什麼是工具鏈文件,還有一個更簡單的解決方案(恕我直言)涵蓋一些問題,我有沒有圖書館多LIB兼容

8

由@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位庫等定義路徑,這通常與標準路徑不同。

2

下面是基本的食譜我用所有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。$ {}拱延伸和我從來沒有去想這對於任何我添加的目標。如果你有一堆預編譯的庫,那麼$ {BIN_LIBROOT}很有用,你可以使用它來動態搜索基於目標平臺/ arch的私有庫dirs中的庫。

+0

現在我主要只是在我的64位桌面上開發時才使用它。當我構建最終版本的Linux二進制文件時,我使用模擬將它們構建在CentOS 6 chroot(其中2個,一個32位和一個64位)中。 – Urkle 2013-08-08 16:20:12

4

您只需在運行CMake時將-m32添加到CFLAGSCXXFLAGS。這可以通過環境變量來完成:

$ 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() {}