4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

h2oをraspberry pi用にcross compileする

Last updated at Posted at 2017-03-25

HTTP/2に最適化されたhttpdのh2oは64bit環境前提に作られている(Raspbianは32bit)が、とりあえずやってみた

前提

  • h2oはcmakeに対応しているので、cmakeを利用してcross compileを行う
  • cross compile環境はdocker上に作ったCentOS7環境

cross compilerをインストールしておく
/opt/rpi/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64
環境変数CROSS_COMPILEをセットしておく
export CROSS_COMPILE=arm-linux-gnueabihf-

zlib

build.sh
        ZLIB_VERSION=1.2.11
        if [ ! -d zlib-${ZLIB_VERSION} ]; then
                curl -L http://prdownloads.sourceforge.net/libpng/zlib-${ZLIB_VERSION}.tar.gz?download | tar zx
        fi

        cd zlib-${ZLIB_VERSION}
        CC=${CROSS_COMPILE}gcc ./configure --prefix=${SYSROOT} && make && make install
        cd ..

libressl

libresslは--hostの指定と、CCなどを設定して対応した

libressl_linux-arm.mk
$(DEST)/lib/libssl.a: $(ARCHIVE)
 	if [ ! -e "libressl-$(VERSION)" ] ; then tar xzf "$(ARCHIVE)" ; fi
-	if [ ! -e "libressl-$(VERSION)/Makefile" ] ; then (P=`pwd`/$(DEST); cd libressl-$(VERSION) && ./configure --prefix="$$P" --libdir="$$P/lib" --disable-shared `test "$(UNAME)" = "Darwin" && echo '--disable-asm'`) ; fi
+	if [ ! -e "libressl-$(VERSION)/Makefile" ] ; then (P=`pwd`/$(DEST); cd libressl-$(VERSION) && CC=${CROSS_COMPILE}gcc LD=${CROSS_COMPILE}ld CCLD=$LD AR=${CROSS_COMPILE}ar CXX=${CROSS_COMPILE}g++ CPP=${CROSS_COMPILE}cpp RANLIB=${CROSS_COMPILE}ranlib ./configure --host=arm-linux-gnueabi --prefix="$$P" --libdir="$$P/lib" --disable-shared `test "$(UNAME)" = "Darwin" && echo '--disable-asm'`) ; fi
 	(cd libressl-$(VERSION) && make && make install)

mruby

mrubyのbuildにcrubyを使う。
mruby自体にcross compileの対応がしてあるため、rubyの設定ファイルを書く
mrubyルートディレクトリにあるbuild_conf.rbを参考にしながらMRuby::CrossBuild.newを使う

mruby_config_linux-arm.rb
MRuby::CrossBuild.new('arm-linux-gnueabi') do |conf|
  toolchain :gcc

  conf.cc.command       = ENV['CROSS_COMPILE'] + 'gcc'
  conf.cxx.command      = ENV['CROSS_COMPILE'] + 'g++'
  conf.linker.command   = ENV['CROSS_COMPILE'] + 'gcc'
  conf.archiver.command = ENV['CROSS_COMPILE'] + 'ar'
#  conf.cc.flags << "-m32"
#  conf.linker.flags << "-m32"

  # use mrbgems
  Dir.glob("../mruby-*/mrbgem.rake") do |x|
    g = File.basename File.dirname x
    if g == 'mruby-onig-regexp'
      conf.gem "../deps/#{g}" do |c|
        c.bundle_onigmo
      end
    else
      conf.gem "../deps/#{g}"
    end
  end

  # include all the core GEMs
  conf.gembox 'full-core'

  conf.build_mrbtest_lib_only

  #conf.gem 'examples/mrbgems/c_and_ruby_extension_example'

  conf.test_runner.command = 'env'

end

mruby-file-statのクロスコンパイルに失敗するため、以下のパッチを適用する

mruby-file-stat_cross.patch
diff --git a/deps/mruby-file-stat/mrbgem.rake b/deps/mruby-file-stat/mrbgem.rake
index ff7d076b..133aee1f 100644
--- a/deps/mruby-file-stat/mrbgem.rake
+++ b/deps/mruby-file-stat/mrbgem.rake
@@ -14,12 +14,16 @@ MRuby::Gem::Specification.new('mruby-file-stat') do |spec|
   file config do
     FileUtils.mkdir_p build_dir, :verbose => true
     Dir.chdir build_dir do
+      if build.kind_of? MRuby::CrossBuild
+        host = "--host=#{build.name}"
+      end
+
       if ENV['OS'] == 'Windows_NT'
         _pp 'on Windows', dir
         FileUtils.touch "#{build_dir}/config.h", :verbose => true
       else
         _pp './configure', dir
-        system env, "#{dir}/configure"
+        system env, "#{dir}/configure #{host}"
       end
     end
   end

h2o

cmakeを利用したcross compile。
CMAKE_TOOLCHAIN_FILEを指定し、raspberry pi用のcmakeファイルを作る

linux-arm.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(CMAKE_SYSROOT /opt/rpi/rootfs)
set(CMAKE_STAGING_PREFIX /home/data/target)

set(tools /opt/rpi/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64)
set(CMAKE_C_COMPILER ${tools}/bin/arm-linux-gnueabihf-gcc)
# set(CMAKE_CXX_COMPILER ${tools}/bin/arm-linux-gnueabihf-g++)

set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT} ${CMAKE_STAGING_PREFIX})

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

今まで諸々やってきたことをCMakeLists.txtへのpatchとして作る
アーカイブのパスがhostに依存しているため、cross compile時に切り替えられるようにしておく

cross.patch
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0e95190b..0dbf8384 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -75,7 +75,12 @@ OPTION(WITH_PICOTLS "whether or not to build with picotls" "ON")
 IF (WITH_BUNDLED_SSL)
     SET(BUNDLED_SSL_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/libressl-build/include")
     SET(BUNDLED_SSL_LIBRARIES "${CMAKE_CURRENT_BINARY_DIR}/libressl-build/lib/libssl.a" "${CMAKE_CURRENT_BINARY_DIR}/libressl-build/lib/libcrypto.a")
-    ADD_CUSTOM_TARGET(bundled-ssl make -f ${CMAKE_CURRENT_SOURCE_DIR}/misc/libressl.mk SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}/misc
+    IF (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm")
+        SET(BUNDLED_SSL_CONFIG "libressl_linux-arm.mk")
+    ELSE ()
+        SET(BUNDLED_SSL_CONFIG "libressl.mk")
+    ENDIF ()
+    ADD_CUSTOM_TARGET(bundled-ssl make -f ${CMAKE_CURRENT_SOURCE_DIR}/misc/${BUNDLED_SSL_CONFIG} SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}/misc
         WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
 ELSE (WITH_BUNDLED_SSL)
     IF (NOT OPENSSL_FOUND)
@@ -445,7 +450,12 @@ IF (WITH_MRUBY)
     ELSE ()
         SET(MRUBY_TOOLCHAIN "gcc")
     ENDIF ()
-    ADD_CUSTOM_TARGET(mruby MRUBY_TOOLCHAIN=${MRUBY_TOOLCHAIN} MRUBY_CONFIG=${CMAKE_CURRENT_SOURCE_DIR}/misc/mruby_config.rb MRUBY_BUILD_DIR=${CMAKE_CURRENT_BINARY_DIR}/mruby ruby minirake
+    IF (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm")
+        SET(CMAKE_MRUBY_CONFIG "mruby_config_linux-arm.rb")
+    ELSE ()
+        SET(CMAKE_MRUBY_CONFIG "mruby_config.rb")
+    ENDIF ()
+    ADD_CUSTOM_TARGET(mruby MRUBY_TOOLCHAIN=${MRUBY_TOOLCHAIN} MRUBY_CONFIG=${CMAKE_CURRENT_SOURCE_DIR}/misc/${CMAKE_MRUBY_CONFIG} MRUBY_BUILD_DIR=${CMAKE_CURRENT_BINARY_DIR}/mruby ruby minirake
         WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/deps/mruby)
     LIST(APPEND STANDALONE_SOURCE_FILES
         lib/handler/mruby.c
@@ -473,10 +483,16 @@ ELSE (WITH_BUNDLED_SSL)
 ENDIF (WITH_BUNDLED_SSL)
 IF (WITH_MRUBY)
     TARGET_INCLUDE_DIRECTORIES(h2o BEFORE PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/deps/mruby/include ${CMAKE_CURRENT_SOURCE_DIR}/deps/mruby-input-stream/src)
+    IF (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm")
+        SET(CMAKE_MRUBY_AR_DIR "arm-linux-gnueabi")
+    ELSE ()
+        SET(CMAKE_MRUBY_AR_DIR "host")
+    ENDIF ()
+
     # note: the paths need to be determined before libmruby.flags.mak is generated
     TARGET_LINK_LIBRARIES(h2o
-        "${CMAKE_CURRENT_BINARY_DIR}/mruby/host/lib/libmruby.a"
-        "${CMAKE_CURRENT_BINARY_DIR}/mruby/host/mrbgems/mruby-onig-regexp/onigmo-6.1.1/.libs/libonigmo.a"
+        "${CMAKE_CURRENT_BINARY_DIR}/mruby/${CMAKE_MRUBY_AR_DIR}/lib/libmruby.a"
+        "${CMAKE_CURRENT_BINARY_DIR}/mruby/${CMAKE_MRUBY_AR_DIR}/mrbgems/mruby-onig-regexp/onigmo-6.1.1/.libs/libonigmo.a"
         "m")
     ADD_DEPENDENCIES(h2o mruby)
 ENDIF (WITH_MRUBY)

ビルドスクリプトは以下の通り

build.sh
        if [ ! -d h2o ]; then
                git clone https://github.com/h2o/h2o.git
        fi

        cd h2o
        cp ../libressl_linux-arm.mk misc
        cp ../mruby_config_linux-arm.rb misc
        patch --forward -p1 < ../mruby-file-stat_cross.patch
        patch --forward -p1 < ../cross.patch
        cmake -DWITH_MRUBY=on -DCMAKE_INSTALL_PREFIX=$SYSROOT -DCMAKE_TOOLCHAIN_FILE=`pwd`/../linux-arm.cmake .
        make

今まで書いてきたことは下記のリポジトリにある
h2o cross compile build script
cloneしてmakeする

perlが必要ならyoctoのレシピを参考にすると

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?