我想构建用Haskell编写的共享对象(node.js addon)。
编译命令:
cabal exec -- \
ghc -cpp -pgmc gcc -optc-std=c++0x -optP-lpthread -O2 -threaded \
-shared -no-hs-main -fPIC -o myaddon.node \
-I. -I/usr/include/node/ -L. -lstdc++ -lpthread -lHSrts-ghc7.8.3 \
hsbracket.c node.cc myaddon.hs
据我所知,所有Haskell库都应该使用-fPIC选项编译:
/usr/bin/ld: /usr/lib/ghc-7.8.3/binary-0.7.1.0/libHSbinary-0.7.1.0.a(Get__14.o): relocation R_X86_64_32S against `.text' can not be used when making a shared object; recompile with -fPIC
这是否意味着基本库是在没有-fPIC选项的情况下编译的,我应该自己编译所有内容(通过黑客入侵cabal bootstrap.sh脚本)?
编辑(1月4日):
helloWorld.hs:
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign.C
hsHelloWorld = newCString "Hello from Haskell"
foreign export ccall "hsHelloWorld" hsHelloWorld :: IO CString
main = return ()
nodehs.cc:
#include <node.h>
#include <v8.h>
#include <nodehs_stub.h>
using namespace v8;
Handle<Value> wrapHelloWorld(const Arguments& args) {
HandleScope scope;
return scope.Close(String::New( (char *)hsHelloWorld() ));
}
void Init(Handle<Object> exports) {
exports->Set( String::NewSymbol("helloWorld"),
FunctionTemplate::New(wrapHelloWorld)->GetFunction());
}
NODE_MODULE(nodehs, Init)
hsbracket.c(非常标准):
#include <HsFFI.h>
static void my_enter(void) __attribute__((constructor));
static void my_enter(void) {
static char *argv[] = { "nodehs.node", 0 }, **argv_ = argv;
static int argc = 1;
hs_init(&argc, &argv_);
}
static void my_exit(void) __attribute__((destructor));
static void my_exit(void) { hs_exit(); }
编译命令:
ghc -shared -fPIC -o nodehs.node -I. -L. -lstdc++ -lHSrts-ghc7.8.4 \
-I/node-v0.10.35/src/ \
-I/node-v0.10.35/deps/v8/include/ \
-I/node-v0.10.35/deps/uv/include \
nodehs.cc hsbracket.c helloWorld.hs
结果:
/ usr / bin / ld:/usr/local/lib/ghc-7.8.4/base-4.7.0.2/libHSbase-4.7.0.2.a(Base__114.o):针对`stg_bh_upd_frame_info&#39;重新定位R_X86_64_32S制作共享对象时不能使用;用-fPIC重新编译 /usr/local/lib/ghc-7.8.4/base-4.7.0.2/libHSbase-4.7.0.2.a:无法读取符号:错误值 collect2:错误:ld返回1退出状态
使用-dynamic
一切正常,但动态链接所有haskell库。
如何将haskell库静态编译到插件中?
对于完全相同的环境和测试,我添加了Dockerfile(docker build -t compile-node . && docker run -v /home/me/nodehs:/src:rw compile-node
)
FROM debian:wheezy
RUN apt-get update && apt-get -y upgrade
RUN apt-get -y install make curl bzip2 unzip gzip libgmp-dev zlib1g-dev
RUN curl -s http://nodejs.org/dist/v0.10.35/node-v0.10.35.tar.gz | tar xz
RUN curl -s http://downloads.haskell.org/~ghc/7.8.4/ghc-7.8.4-x86_64-unknown-linux-deb7.tar.bz2 | tar xj
RUN curl -s http://hackage.haskell.org/package/cabal-install-1.18.0.5/cabal-install-1.18.0.5.tar.gz | tar xz
RUN curl -sL https://deb.nodesource.com/setup | bash -
RUN apt-get install -y nodejs
RUN cd ghc-* && ./configure && make install
ENV EXTRA_BUILD_OPTIONS "--enable-executable-dynamic --enable-shared --ghc-options='-fPIC --dynamic-too'"
RUN cd cabal-* && ./bootstrap.sh --global
RUN cabal update
WORKDIR /src/
# first ghc command is needed to make helloWorld_stub.h
CMD ghc helloWorld.hs && \
ghc -shared -fPIC -o nodehs.node \
-I. -I/node-v0.10.35/src/ -I/node-v0.10.35/deps/v8/include/ -I/node-v0.10.35/deps/uv/include \
-L. -lstdc++ -lHSrts-ghc7.8.4 \
nodehs.cc hsbracket.c helloWorld.hs \
&& node -e "console.log(require('./nodehs.node').helloWorld())'"