==> Environment
==> Dependencies
$ crystal build server.cr --cross-compile --target "x86_64-unknown-linux-gnu"
cc server.o -o server -rdynamic -lz `pkg-config --libs libssl || printf %s '-lssl -lcrypto'` `pkg-config --libs libcrypto || printf %s '-lcrypto'` -lpcre -lm -lgc -lpthread /usr/local/Cellar/crystal-lang/0.18.7/src/ext/libcrystal.a -levent -lrt -ldl -L/usr/lib -L/usr/local/lib
$ cc server.o -o server -rdynamic -lz `pkg-config --libs libssl || printf %s '-lssl -lcrypto'` `pkg-config --libs libcrypto || printf %s '-lcrypto'` -lpcre -lm -lgc -lpthread /usr/local/Cellar/crystal-lang/0.18.7/src/ext/libcrystal.a -levent -lrt -ldl -L/usr/lib -L/usr/local/lib -v
Apple LLVM version 7.3.0 (clang-703.0.29)
Target: x86_64-apple-darwin15.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld" -demangle -export_dynamic -dynamic -arch x86_64 -macosx_version_min 10.11.0 -o server -L/usr/lib -L/usr/local/lib server.o -lz -lssl -lcrypto -lz -lcrypto -lz -lpcre -lm -lgc -lpthread /usr/local/Cellar/crystal-lang/0.18.7/src/ext/libcrystal.a -levent -lrt -ldl -lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/7.3.0/lib/darwin/libclang_rt.osx.a
ld: library not found for -lrt
clang: error: linker command failed with exit code 1 (use -v to see invocation)
You're supposed to run the linking command on the target system.
In fact, i want do something with binary file and add it to dockerfile to keep image to tiny. if linking the command on the target system(maybe also install required libraries) that it will be large. Is there has any way to running it on the same os system?
For example: https://github.com/emilevauge/whoamI
Well you need the libraries compiled for the target platform. If you link against static versions you do not need to install the libraries in the image. If you link against dynamic versions you still need to install them in the image.
thanks a lot.
Is any plan in the future will support like this feature for crystal?
It cross comiple and running passed on Ubuntu (with docker crystallang/crystal), but it cant running on the other linux distribution, like alpine or docker base image scratch:
# alpine linux 3.4
$ cat Docfile
FROM alpine:3.4
COPY server.linux /
COPY server.release /
ENTRYPOINT ["/server.linux"]
EXPOSE 8080
$ docker run -it --rm icyleaf/http
ash: ./server.linux: not found
# scratch
$ cat Docfile
FROM scratch
COPY server.linux /
COPY server.release /
ENTRYPOINT ["/server.linux"]
EXPOSE 8080
$ docker run -it --rm icyleaf/http
standard_init_linux.go:175: exec user process caused "no such file or directory"
`server.linux` is built with cross-compile and target "x86_64-unkown-linux-gnu"
`server.release` is buit in release mode
It likely links against libraries not present in those images, you can see which ones with ldd.
Alpine has a specific libc (musl). You must compile your binary statically, or better have it compiled under Alpine Linux (statically or not).
Oh, and if you cross-compile: you must use the x86_64-unknown-linux-musl target.
@jhass thanks, i asked my friend who knows well about compile, and i also used ldd to check link library, in alpine is missing to link library libgcc and ld-linux. The first was solved by apk add libgcc-dev, the last is still working on.
@ysbaddaden
i tried it on ubuntu but fail:
root@b69d6d745edf:/app# crystal build server.cr --cross-compile --target "x86_64-unkonwn-linux-musl" -o server.alpine
Deprecation: The build command was renamed to compile and will be removed in a future version.
cc server.alpine.o -o server.alpine -rdynamic -L/usr/lib -L/usr/local/lib -lz `pkg-config --libs libssl || printf %s '-lssl -lcrypto'` `pkg-config --libs libcrypto || printf %s '-lcrypto'` -lpcre -lm -lgc -lpthread /opt/crystal/src/ext/libcrystal.a -levent -lrt
root@b69d6d745edf:/app# cc server.alpine.o -o server.alpine -rdynamic -L/usr/lib -L/usr/local/lib -lz `pkg-config --libs libssl || printf %s '-lssl -lcrypto'` `pkg-config --libs libcrypto || printf %s '-lcrypto'` -lpcre -lm -lgc -lpthread /opt/crystal/src/ext/libcrystal.a -levent -lrt
/usr/bin/ld: server.alpine.o: undefined reference to symbol 'dladdr@@GLIBC_2.2.5'
//lib/x86_64-linux-gnu/libdl.so.2: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
BTW, how to compile with statically?
Static compilation has been attempted numerous times, and it almost never actually works out.
There's one thing to know: Go's standard library is implemented entirely in Go. This is probably possible because Go has many, many years now, and has Google behind it. Statically linking everything in Crystal is not possible because we link against libc and other libraries. Cross compilation was introduced in the language mainly to be able to port the compiler to other platforms, not as a general tool to use by anyone.
The best thing to do is to install Crystal on the target platform and compile your program there.
If you want to statically link a binary from Ubuntu (or Alpine) so it can be run on any Linux distribution (to some extent), please avoid cross compilation, and merely build your application from Ubuntu with Crystal directly. You'll save yourself a lot of hassle, especially if you're not fluent with libraries and linking:
crystal build --link-flags="-static" server.cr
@asterite I've been capable to statically link Crystal itself and I statically link Shards, so there is little reason static linking won't work —unless you're on OSX that doesn't support full static linking, or there is a bug, like #1269.
yes, the best way which install crystal on your target system ,then complile program there, i build Go-lang program just do it. 哈哈
I imagine more people will be wanting to use Crystal on Alpine. Maybe it would be good to add the install steps to https://crystal-lang.org/docs/installation/index.html ?
Most helpful comment
If you want to statically link a binary from Ubuntu (or Alpine) so it can be run on any Linux distribution (to some extent), please avoid cross compilation, and merely build your application from Ubuntu with Crystal directly. You'll save yourself a lot of hassle, especially if you're not fluent with libraries and linking:
@asterite I've been capable to statically link Crystal itself and I statically link Shards, so there is little reason static linking won't work —unless you're on OSX that doesn't support full static linking, or there is a bug, like #1269.