話說要在arm開發板的linux系統中運行apache服務器,需要在pc linux系統中交叉編譯Apache源碼,在網上參考了很多資料都是1.3版本的,最后終于找到apache 2移植到arm開發板的方法,現整理如下文。由于開發板的不同,可能這里出現的問題大家不會都遇到,但相信多數問題都已覆蓋。

       一、安裝pcre

       tar -xvzf pcre-8.31.tar.gz

       cd pcre-8.31

       ./configure --prefix=$ARMROOTFS/usr/pcre --host=arm-linux CC=$TOOLCHAIN/arm-linux-gcc 

       make

       make install

       二、安裝apr

       這里特別提醒,先看一下后面的幾點一些要注意的地方,特別是第⑤點

       tar -xvzf apr-1.4.6.tar.gz

       cd apr-1.4.6

       ./configure --prefix=$ARMROOTFS/usr/apr --host=arm-linux CC=$TOOLCHAIN/arm-linux-gcc  ac_cv_file__dev_zero=yes ac_cv_func_setpgrp_void=yes apr_cv_tcp_nodelay_with_cork=yes --cache=arm-linux.cache

       這里簡要說明一下如果不添加某些選項會出現的錯誤提示及一些需要特別注意的地方(這里按照我所記錄的錯誤出現的順序說明,而不是按上面選項的順序):

       ①如果不添加ac_cv_file__dev_zero=yes(注意file和dev之間是兩個下劃線),則會出現錯誤:

       check for /dev/zero... configure:error:cannot check for file existence when cross compile

       ②如果不添加ac_cv_func_setpgrp_void=yes,則會出現錯誤:

       checking whether setpgrp takes no argument... configure: error: cannot check setpgrp when cross compiling

       ③選項--cache=arm-linux.cache中,arm-linux.cache為自己建立編寫的文件(在編譯過程中內容會被修改),在建立時需要自己寫入如下內容(這個選項可能有些開發板不需要):

       apr_cv_process_shared_works=yes

       apr_cv_mutex_robust_shared=yes

       如果不寫入第一項,則會出現錯誤:

       checking for working PROCESS_SHARED locks... configure:error: in `.../apr-1.4.6':

       configure:error: cannot run test program while cross compiling

       See `config.log' for more details

       如果不寫入第二項,則會出現:

       checking for robust cross-process mutex support... configure: error: in `.../apr-1.4.6':

       configure: error: cannot run test program while cross compiling

       See `config.log' for more details

       這些錯誤產生的原因在于這里在configure運行配置的過程中要運行幾個測試程序來檢驗一些配置(個人理解),但在此處指定了編譯時采用的編譯器是交叉編譯鏈,這幾個測試程序都是經過交叉編譯鏈編譯產生的,而在宿主機系統上無法運行這些程序,因此只好自己手動指定這些檢測程序最后運行的結果。

       在以后為開發板配置軟件包時遇到這種錯誤:configure:error:cannot run test program while cross compiling,應該都可以通過這種方法解決。

       那么如果查找出這些表示結果的變量呢?只要在configure文件中搜尋這些錯誤的關鍵字即可,如這里的第一個項,我們可以搜尋:working PROCESS_SHARED locks,然后在configure文件中可以鎖定到如下代碼段:

C++代碼
  1. ...  
  2. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working PROCESS_SHARED locks" >&5    
  3. $as_echo_n "checking for working PROCESS_SHARED locks... " >&6; }    
  4. if ${apr_cv_process_shared_works+:} false; then :    
  5.   $as_echo_n "(cached) " >&6    
  6. else    
  7. ...  

       這里可以看出變量apr_cv_process_shared_works便是與這個程序運行結果關聯的變量。

       ④如果不添加ac_cv_sizeof_struct_iovec=8選項,則會在使用make指令時出現錯誤:

       ./include/apr_want.h:95: error: redefinition of 'struct iovec'

       make[1]: *** [passwd/apr_getpass.lo] 錯誤 1

       ⑤在添加了ac_cv_sizeof_struct_iovec=8選項后,還需要對configure文件進行一下修改,搜索apr_ssize_t可以定位到下面一段代碼:

C++代碼
  1. { $as_echo "$as_me:${as_lineno-$LINENO}: checking which format to use for apr_ssize_t" >&5  
  2. $as_echo_n "checking which format to use for apr_ssize_t... " >&6; }  
  3. if test -n "$ssize_t_fmt"; then  
  4. { $as_echo "$as_me:${as_lineno-$LINENO}: result: %$ssize_t_fmt" >&5  
  5.   $as_echo "%$ssize_t_fmt" >&6; }  
  6. elif test "$ac_cv_sizeof_ssize_t" = "$ac_cv_sizeof_int"; then  
  7.     ssize_t_fmt="d"  
  8.     { $as_echo "$as_me:${as_lineno-$LINENO}: result: %d" >&5  
  9. $as_echo "%d" >&6; }  
  10. elif test "$ac_cv_sizeof_ssize_t" = "$ac_cv_sizeof_long"; then  
  11.     ssize_t_fmt="ld"  
  12.     { $as_echo "$as_me:${as_lineno-$LINENO}: result: %ld" >&5  
  13. $as_echo "%ld" >&6; }  
  14. else  
  15.     as_fn_error $? "could not determine the proper format for apr_ssize_t" "$LINENO" 5  
  16. fi  

       將中間添加一段代碼(紅色標注),修改為:  

       { $as_echo "$as_me:${as_lineno-$LINENO}: checking which format to use for apr_ssize_t" >&5

       $as_echo_n "checking which format to use for apr_ssize_t... " >&6; }

       if test -n "$ssize_t_fmt"; then

              { $as_echo "$as_me:${as_lineno-$LINENO}: result: %$ssize_t_fmt" >&5

       $as_echo "%$ssize_t_fmt" >&6; }

       elif test "$ac_cv_sizeof_ssize_t" = "$ac_cv_sizeof_int"; then

              ssize_t_fmt="d"

              { $as_echo "$as_me:${as_lineno-$LINENO}: result: %d" >&5

        $as_echo "%d" >&6; }

      elif test "$ac_cv_sizeof_ssize_t" = "$ac_cv_sizeof_long"; then

              ssize_t_fmt="ld"

              { $as_echo "$as_me:${as_lineno-$LINENO}: result: %ld" >&5

       $as_echo "%ld" >&6; }

       elif test "$ac_cv_sizeof_ssize_t" = "$ac_cv_sizeof_long_long";then

              ssize_t_fmt="lld"

              { $as_echo "$as_me:${as_lineno-$LINENO}: result: %lld" >&5

       $as_echo "%lld" >&6; }

       else

              as_fn_error $? "could not determine the proper format for apr_ssize_t" "$LINENO" 5

       fi

       搜索apr_size_t可以定位到下面一段代碼:

C++代碼
  1. { $as_echo "$as_me:${as_lineno-$LINENO}: checking which format to use for apr_size_t" >&5  
  2. $as_echo_n "checking which format to use for apr_size_t... " >&6; }  
  3. if test -n "$size_t_fmt"; then  
  4.     { $as_echo "$as_me:${as_lineno-$LINENO}: result: %$size_t_fmt" >&5  
  5. $as_echo "%$size_t_fmt" >&6; }  
  6. elif test "$ac_cv_sizeof_size_t" = "$ac_cv_sizeof_int"; then  
  7.     size_t_fmt="d"  
  8.     { $as_echo "$as_me:${as_lineno-$LINENO}: result: %d" >&5  
  9. $as_echo "%d" >&6; }  
  10. elif test "$ac_cv_sizeof_size_t" = "$ac_cv_sizeof_long"; then  
  11.     size_t_fmt="ld"  
  12.     { $as_echo "$as_me:${as_lineno-$LINENO}: result: %ld" >&5  
  13. $as_echo "%ld" >&6; }  
  14. else  
  15.     as_fn_error $? "could not determine the proper format for apr_size_t" "$LINENO" 5  
  16. fi  

       將中間添加一段代碼(紅色標注),修改為:

       { $as_echo "$as_me:${as_lineno-$LINENO}: checking which format to use for apr_size_t" >&5

       $as_echo_n "checking which format to use for apr_size_t... " >&6; }

       if test -n "$size_t_fmt"; then

              { $as_echo "$as_me:${as_lineno-$LINENO}: result: %$size_t_fmt" >&5

       $as_echo "%$size_t_fmt" >&6; }

       elif test "$ac_cv_sizeof_size_t" = "$ac_cv_sizeof_int"; then

              size_t_fmt="d"

              { $as_echo "$as_me:${as_lineno-$LINENO}: result: %d" >&5

       $as_echo "%d" >&6; }

       elif test "$ac_cv_sizeof_size_t" = "$ac_cv_sizeof_long"; then

              size_t_fmt="ld"

              { $as_echo "$as_me:${as_lineno-$LINENO}: result: %ld" >&5

       $as_echo "%ld" >&6; }

       elif test "$ac_cv_sizeof_size_t" = "$ac_cv_sizeof_long_long"; then

              size_t_fmt="lld"

              { $as_echo "$as_me:${as_lineno-$LINENO}: result: %lld" >&5

       $as_echo "%lld" >&6; }

       else

              as_fn_error $? "could not determine the proper format for apr_size_t" "$LINENO" 5

       fi

       如果什么修改也不做,則會出現錯誤:

       checking which format to use for apr_ssize_t... configure:error:could not determine the proper format for apr_ssize_t

       如果只做了第一個修改,則會出現錯誤:

       checking which format to use for apr_size_t... configure:error:could not determine the proper format for apr_size_t

       這是apr源代碼包本身有的bug,這樣修改后,在最后編譯httpd時,會出現一些warning,大概意思是說參數類型為pid_t的地方,出現的參數類型為long long,但pid_t的類型本身就是unsigned int,因此應該是沒有問題的。

       三、安裝apr-util

       tar -xvzf apr-util-1.4.1.tar.gz

       cd apr-util-1.4.1

      ./configure

      ./configure --prefix=$ARMROOTFS/usr/local/apr-util --with-apr=$ARMROOTFS/usr/local/apr --host=arm-linux CC=$TOOLCHAIN/arm-linux-gcc 

       make

       make install

       四、安裝httpd

       這里提醒一下先看一下后面的幾點要注意的地方,特別是第②點

       tar -xvzf httpd-2.4.3.tar.gz

       cd httpd-2.4.3

       ./configure --prefix=$ARMROOTFS/etc/apache --with-pcre=$ARMROOTFS/usr/local/pcre --with-apr=$ARMROOTFS/usr/local/apr --with-apr-util=$ARMROOTFS/usr/local/apr-util --host=arm-linux CC=$TOOLCHAIN/arm-linux-gcc ap_cv_void_ptr_lt_long=no --enable-so --enable-cgi LDFLAGS=-lpthread --with-mpm=prefork

       make

       make install

       在編譯過程中要注意以下幾點:

       ①如果不添加ap_cv_void_ptr_lt_long=no選項,則會出現錯誤:

       configure: error: Size of "void *" is less than size of "long"

       ②如果不添加--with-mpm=prefork選項,若開發板不兼容thread-safe,則apache會啟動不了,并且logs/error_log中會記錄錯誤:

        [mpm_event:crit] [pid 0:tid 1073875872] (70023)This function has not been implemented on this platform: AH00495: Couldn't create a Thread Safe Pollset. Is it supported on your platform?Also check system or user limits!

       ③在執行過./configure指令后,在為開發板編譯httpd執行make命令前,需要先對宿主機上編譯過一次httpd(即至少執行到make,make install可不執行,宿主機上不最終安裝apache2也是可以的),然后到為開發板編譯httpd的httpd-2.4.3目錄下的server目錄中,修改一下其中的Makefile文件,找到如下行:

       test_char.h: gen_test_char

       ./gen_test_char > test_char.h

       修改為

       test_char.h: gen_test_char

       #./gen_test_char > test_char.h

       $httpd_for_pc/server/gen_test_char > test_char.h

       其中這里的變量httpd_for_pc只是指代為宿主機編譯的httpd軟件包加壓后的文件夾路徑。

       如果不做上面任何修改,則會出現以下錯誤:

       ./gen_test_char > test_char.h

       /bin/bash: ./gen_test_char: 無法執行二進制文件

       原因也是因為宿主機上無法運行使用交叉編譯鏈編譯的程序的緣故。

       如果只修改為:

       test_char.h: gen_test_char

       #./gen_test_char > test_char.h

       而在宿主機上不編譯一次httpd,則會出現以下錯誤:

       util.c: In function 'ap_find_token':

       util.c:1434: error: 'test_char_table' undeclared (first use in this function)

       util.c:1434: error: (Each undeclared identifier is reported only once

       util.c:1434: error: for each function it appears in.)

       util.c:1434: error: 'T_HTTP_TOKEN_STOP' undeclared (first use in this function)

       util.c: In function 'ap_escape_shell_cmd':

       util.c:1498: error: 'test_char_table' undeclared (first use in this function)

       util.c:1498: error: 'T_ESCAPE_SHELL_CMD' undeclared (first use in this function)

       util.c: In function 'ap_escape_path_segment_buffer':

       util.c:1706: error: 'test_char_table' undeclared (first use in this function)

       util.c:1706: error: 'T_ESCAPE_PATH_SEGMENT' undeclared (first use in this function)

       util.c: In function 'ap_os_escape_path':

       util.c:1740: error: 'test_char_table' undeclared (first use in this function)

       util.c:1740: error: 'T_OS_ESCAPE_PATH' undeclared (first use in this function)

       util.c: In function 'ap_escape_urlencoded_buffer':

       util.c:1759: error: 'test_char_table' undeclared (first use in this function)

       util.c:1759: error: 'T_ESCAPE_URLENCODED' undeclared (first use in this function)

       util.c: In function 'ap_escape_logitem':

       util.c:1844: error: 'test_char_table' undeclared (first use in this function)

       util.c:1844: error: 'T_ESCAPE_LOGITEM' undeclared (first use in this function)

       util.c: In function 'ap_escape_errorlog_item':

       util.c:1896: error: 'test_char_table' undeclared (first use in this function)

       util.c:1896: error: 'T_ESCAPE_LOGITEM' undeclared (first use in this function)

       util.c: In function 'ap_append_pid':

       可見./gen_test_char > test_char.h這條語句是為了生成一些宏定義或者全局變量到test_char.h這個頭文件中去,而里面這些宏定義和全局變量又在httpd源程序的中使用到。因此宿主機系統也必須編譯一次httpd才可以完成開發板安裝apache2服務器軟件。

       如果在執行上面的修改前執行過一次make,那么需要執行make clean命令后,再執行make才能編譯通過。

       經過以上步驟后,進入開發板文件系統目錄,修改etc/apache/bin目錄下的apachectl文件,搜索HTTPD,可以找到該變量,將該變量的值修改為:HTTPD='/etc/apache/bin/httpd'。

       為了方便以后在開發板上輸入打開和關閉apache2服務器的指令,可以執行以下命令:

       sudo cp $ARMROOTFS/etc/httpd/bin/apachectl $ARMROOTFS/usr/sbin/

       sudo cp $ARMROOTFS/etc/httpd/bin/apachectl $ARMROOTFS/etc/init.d/

       五、將apache拷貝到arm開發板

       1. 把在 /usr/local/下生成的目錄 apache拷貝到你的開發板根文件系統的 …/usr/local/ 目錄下。

       2. 修改配置http.conf文件。在…/usr/local/apache/conf/ 目錄下,用文本編輯器打開。

       還有注意的是,apache拒絕使用root用戶運行。所以你需要增加一個用戶和用戶組,我們可以使用 http.conf配置文件默認的用戶名和用戶組名,nobody和nobody。具體來說就是在ARM Linux根文件系統上建立/etc/passwd和/etc/group兩個文件,它們的內容可以如下:

       /etc/passwd

       root::0:0:root:/:/bin/ash

       nobody::65534:65533:nobody:/:/bin/ash

       /etc/group

       nobody::65533:

       nogroup::65534:nobody

       root::0:

       users::100

       如果rootfs中有這兩個文件,那么就只需要檢查一下是不是有nobody用戶和nogroup組。

       六、復制共享庫(為宿主機系統編譯安裝apache2不需要進行這一步)

       之后還需要復制一些共享庫到開發板文件系統的/usr/lib目錄下,否則會啟動不了apache2服務器,像以下錯誤:

       ①error while loading shared libraries: libpcre.so.1:cannot open shared object file:No such file for directory

       解決方法:cp $ARMROOTFS/usr/local/pcre/lib/libpcre.so* $ARMROOTFS/usr/lib

       ②error while loading shared libraries: libaprutil-1.so.0:cannot open shared object file:No such file for directory

       解決方法:cp $ARMROOTFS/usr/local/apr-util/lib/libaprutil-1.so* $ARMROOTFS/usr/lib

       ③error while loading shared libraries: libexpat.so.0:cannot open shared object file:No such file for directory

       解決方法:cp $ARMROOTFS/usr/local/apr-util/lib/libexpat.so* $ARMROOTFS/usr/lib

       ④error while loading shared libraries: libapr-1.so.0:cannot open shared object file:No such file for directory

       解決方法:cp $ARMROOTFS/usr/local/apr/lib/libapr-1.so* $ARMROOTFS/usr/lib

       ⑤error while loading shared libraries: libuuid.so.1:cannot open shared object file:No such file for directory(某些開發板可能不會出現這個問題)

       解決方法:需要編譯一次e2fsprogs這個軟件包,使它生成這個共享庫。

       tar -xvzf e2fsprogs-1.42.8.tar.gz

       cd e2fsprogs-1.42.8

       ./configure --prefix=$ARMROOTFS/usr/local/e2fsprogs --host=arm-linux CC=$TOOLCHAIN/arm-linux-gcc --enable-elf-shlibs

       make

       make install(可以不執行這一步)

       之后在軟件包加壓后的e2fsprogs-1.42.8目錄下執行:

       cp lib/libuuid.so* $ARMROOTFS/usr/lib/

       七、啟動apache

        最后,我們就可以進入到開發板進入到apache的bin目錄中,執行命令./apachectl start來啟動apache。

        還可以將 httpd 應用程序拷貝到 /usr/sbin 文件夾下并設置其為開機自啟動。向 /etc/init.d/rc 文件最后添加命令httpd。

除非特別注明,雞啄米文章均為原創
轉載請標明本文地址:http://www.vkzldl.live/software/428.html
2015年9月17日
作者:雞啄米 分類:軟件開發 瀏覽: 評論:0