如何在MacOS下编译hadoop


如何在MacOS下编译hadoop

一、缘由

最近因为需要用C++写一个MapReduce程序,虽然比较简单的办法自然是用Hadoop Streaming在新窗口打开,但这次打算尝试一下Hadoop Pipes在新窗口打开

和Hadoop Streaming不同,Hadoop Pipes用Socket让Java代码和C++通信,我想当然地解决性能会优于Hadoop Streaming采用标准输入输出的方式。

因为我的开发环境是MacOS,IDE用的是CLion在新窗口打开,既然使用上了IDE,那么就想能够用上代码补全这些功能,因此就需要在在MacOS上编译一个hadoop native library。

1.1 本文档使用的环境

  • Hadoop 版本:hadoop-3.1.1

  • MacOS版本:10.15.7

二、安装依赖

首先需要JDK、Maven等基本工具我就不提了。

2.1 一些可以用Homebrew在新窗口打开安装的工具

brew install gcc autoconf automake libtool cmake snappy gzip bzip2 zlib openssl

2.2 安装protobuf 2.5.0

Hadoop用的protobuf还是几年前2.5.0在新窗口打开版本的,在brew上已经没有这个版本了,因此得自己安装一个。

./configure --prefix=/usr/local/Cellar/protobuf/2.5.0
make
make install
# 添加到环境变量
brew link [email protected]

2.3 openssl配置

在编译过程中,Hadoop native library会依赖[email protected],因为MacOS系统也版本一个openssl,但版本不匹配,因此得指定openssl所在的路径等。

话说这里我看到过三种指定openssl的方法,三种方法我都罗列一下,同时也表明是哪种是在我这里亲测有效的:

方法一:修改源码中的CMakeLists.txt(亲测有效)

修改./hadoop-tools/hadoop-pipes/src/CMakeLists.txt,在其中加入如下几行:

if (APPLE)
    # This is a bug in CMake that causes it to prefer the system version over
    # the one in the specified ROOT folder.
    set(OPENSSL_ROOT_DIR ${OPENSSL_ROOT_DIR} /usr/local/opt/[email protected]/)
    set(OPENSSL_CRYPTO_LIBRARY ${OPENSSL_ROOT_DIR}/lib/libcrypto.dylib CACHE FILEPATH "" FORCE)
    set(OPENSSL_SSL_LIBRARY ${OPENSSL_ROOT_DIR}/lib/libssl.dylib CACHE FILEPATH "" FORCE)
endif()
find_package(OpenSSL REQUIRED)

方法二:通过编译参数来指定

默认的编译参数是:

mvn package -Pdist,native -DskipTests -Dtar -Dmaven.javadoc.skip

可以通过-Dopenssl.prefix来指定openssl的路径:

mvn package -Pdist,native -DskipTests -Dtar -Dmaven.javadoc.skip -Dopenssl.prefix=/usr/local/opt/[email protected]

方法三:通过环境变量来指定

export OPENSSL_ROOT_DIR="/usr/local/opt/[email protected]"
export OPENSSL_INCLUDE_DIR="$OPENSSL_ROOT_DIR/include"
export LDFLAGS="-L${OPENSSL_ROOT_DIR}/lib"
export CPPFLAGS="-I${OPENSSL_ROOT_DIR}/include"
export PKG_CONFIG_PATH="${OPENSSL_ROOT_DIR}/lib/pkgconfig" 

三、过程中可能出现的一些错误的解决办法

3.1 constexpr错误

在编译时,发现constexpr一个错误,它是C++11的关键字,解决办法需要修改:hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-nativetask/src/CMakeLists.txt,在include(HadoopJNI)后面加上:

include(CheckFunctionExists)
include(CheckIncludeFiles)
include(CheckCXXCompilerFlag) 
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) 
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) 
if(COMPILER_SUPPORTS_CXX11) 
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 
elseif(COMPILER_SUPPORTS_CXX0X) 
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") 
else() 
    message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") 
endif()

3.2 "%"PRId64、"%"PRIu64错误

hadoop-mapreduce-client-nativetask/src/main/native中所有的*.cc中出现的"%"PRId64"%"PRIu64,需要改成引号和P之间要加空格,否则c++11编译不过。

另外,我试过,这个问题在Linux下编译也会出现。

四、编译

4.1 编译命令

mvn package -Pdist,native -DskipTests -Dtar -Dmaven.javadoc.skip

4.2 拷贝编译好的文件到$HADOOP_HOME

如果编译成功,则可以将输出文件拷贝到$HADOOP_HOME(这个环境变量自行设置)目录下

cp -rp hadoop-dist/target/hadoop-3.1.1/lib $HADOOP_HOME

五、参考