跳转到内容

如何在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。

  • Hadoop 版本:hadoop-3.1.1

  • MacOS版本:10.15.7

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

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

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

Terminal window
./configure --prefix=/usr/local/Cellar/protobuf/2.5.0
make
make install
# 添加到环境变量

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

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

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

Section titled “方法一:修改源码中的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)

默认的编译参数是:

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

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

Terminal window
mvn package -Pdist,native -DskipTests -Dtar -Dmaven.javadoc.skip -Dopenssl.prefix=/usr/local/opt/[email protected]
Terminal window
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"

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

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

在编译时,发现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()

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

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

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

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

Section titled “4.2 拷贝编译好的文件到$HADOOP_HOME”

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

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