web-dev-qa-db-ja.com

Linux AMD64、cmake、およびg ++を使用してLinux x86をクロスコンパイルする方法

全体像の完成に役立つ情報の各部分に+1。答え全体を知る必要はありません。パズルの個々のピースも同様に高く評価します。ありがとう。

最初のクロスコンパイルを試みます。 SOとWebの両方を検索したところ、多くの情報が見つかりましたが、欠けている部分がまだあるため、それらをまとめる方法が常にわかりません。

私のホスト:linux Kubuntu AMD64。
ターゲット:Linux kubuntu x86(32ビット)(簡単なはずです)
ツール:g ++およびcmake。

これが私が見つけた情報です:

gcc/cmakeを使用して64ビットのLinuxマシンで32ビットのバイナリをコンパイルする方法
メンションはCFLAGS = -m32をエクスポートしますそれはワンピースです。

クロスプラットフォーム:32/64ビットを使用するデータ型の選択
メンションデータタイプ。私はコード内でそれに注意を払う必要があるかもしれません。

2ビットプラットフォームの場合は#ifdef
32ビットプラットフォームの#ifdef
以下へのリンクですが、その使用方法はまだはっきりしていません。
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)

2番目の実行可能ファイルを作成するためにフラグ-m32を導入するにはどうすればよいですか?

実行可能ファイルを1つだけ(たとえば、テストとデバッグ用に)作成したいのですが、cmakeにどちらか一方または両方のバイナリを作成するように指示するにはどうすればよいですか?

また、私がいくつかのサードパーティライブラリを使用していることもわかります。これは、ターゲットホスト用にこれらの各バイナリもコンパイルする必要があることを意味しますか? cmakeを使用するものと、cmakeを使用するものがあります。作る;
ターゲットホスト用にこれらのライブラリをコンパイルするにはどうすればよいですか(使用するフラグなど)?

注:動的にリンクされたライブラリは既にコンパイルされ、ターゲットコンピューターにインストールされているため、この手順について心配する必要はないかもしれません...わからない:これは欠けている部分の1つです...

必要なのは、一種のチュートリアル、または少なくともいくつかの欠けている部分です。この投稿を更新して、達成したこととその方法について詳しく説明します。

ありがとう。

追伸.

まったく可能ですか?

もっと検索して、私はこれを見つけました:
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ビットのみをビルドすることはできません。」

??

27
augustin

ツールチェーンファイルを使用する場合は、@ auledoomで提案されているものよりも簡単な解決策(IMHO)があります。シェルラッパースクリプトを記述する必要はまったくありません。これをツールチェーンファイルに追加するだけです。

# 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ビットライブラリなどのパスも定義できることです。これは、通常の標準パスとは異なります。

8
yngve

このソリューションでは、マルチアーチサポートのあるシステムで、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 "$@"

ご覧のとおり、システムコンパイラを呼び出して-mフラグを追加するだけです。これをi686-linux-gnu-gccとして保存します。 g ++コンパイラーについても同じことを行います

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

それをi686-linux-gnu-g ++として保存します。このスクリプトに実行可能フラグを設定することを忘れないでください

この形式でシステムarバイナリへのシンボリックリンクも作成します

$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 ..

そしてあなたの完了!!!!!

より完全なガイドを書きます ここ 、これはマルチライブラリに準拠していないライブラリで私が抱えているいくつかの問題をカバーしています

7
auledoom

これは私が使用しているものの簡易バージョンであり、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ファイルに分割されており、1つのファイルで多数の実行可能ファイルを構築するには、構築するすべての異なる構成を含むマスター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

次に、それをすべてビルドするためのドライバーシェルスクリプトがあります。コマンドラインオプションを使用していくつかの追加オプションを設定し、すべてをビルドするか、1つの構成のみをビルドするかを選択します。以下がその一部です。

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自体に任意の数のターゲットを定義し、それらをすべて1つのファイルでビルドすることが可能かどうかはわかりません。)このファイルのジェネレーターを作成するには、少し時間がかかりますが、それが完了すると、すべてのI必要なのは、ジェネレーターをソースのあるディレクトリにポイントし、irを実行してから、ビルドスクリプトを呼び出してすべてを作成することです。

5
stijn

必要なのは、CMakeの実行時にCFLAGSCXXFLAGS-m32を追加することだけです。これは環境変数を介して行うことができます:

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

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}は、多数のプリコンパイル済みライブラリがある場合に便利です。これを使用すると、ターゲットプラットフォーム/ Archに基づいてプライベートライブラリディレクトリ内のライブラリを動的に検索できます。

2
Urkle