Skip to content

Loading…

Fix compiler invocation on multiarch Linux #305

Merged
merged 1 commit into from

4 participants

@liskin

This fixes port compilation for some configurations, notably this one: Debian
with 32-bit userspace, 64-bit kernel and 64-bit erlang packages.

@liskin liskin Fix compiler invocation on multiarch Linux
This fixes port compilation for some configurations, notably this one:
Debian with 32-bit userspace, 64-bit kernel and 64-bit erlang packages.
6fca763
@ferd

Do we have an example of a config/NIF/Port that broke before so this could be tried?

@liskin

Any at all, really. The important part is having gcc:i386 and erlang:amd64 installed.

@ferd

I don't run a Linux and can't say for sure. I'm hesitant to merge in things I cannot try. @tuncer are you able to validate the behaviour?

@tuncer

Unfortunately I don't have the right Linux environment available to test this, but anyone with a Debian or Ubuntu install should be able to verify.

@ferd

I still don't run a linux and still can't say for sure.

@tuncer

@liskin, what happens if you install gcc 32-bit and 64-bit in parallel. Specifically, what determines the default (code generation) mode of cc?

@liskin

Well, on Debian (and other distributions as well, I think) you can't install both versions of gcc in parallel. You can only install libraries in both variants, but not (usually) programs. Therefore, the default code generation mode is determined by the architecture gcc was built for. 32-bit gcc builds 32-bit by default, and 64-bit builds 64-bit by default.

@ferd ferd merged commit fffc745 into rebar:master

1 check passed

Details continuous-integration/travis-ci The Travis CI build passed
@joudinet

I've just upgraded the rebar version in my build system from 2.5.1 to 2.6.0 and recompiling some erlang projects fail with the following error message:
arm-buildroot-linux-uclibcgnueabi-gcc: error: unrecognized command line option ‘-m64’
I suspect this commit to be responsible as I'm cross-compiling to arch from a 64-bit machine. Is there a way to not add such flag?

@liskin

@joudinet What does rebar_utils:get_arch() say on the target platform?

(And does rebar know it's cross-compiling or did you just set CC to something else?)

@joudinet
(ejabberd@buildroot)2> rebar_utils:get_arch().
** exception error: undefined function rebar_utils:get_arch/0

I haven't installed rebar on the target platform, and don't want to. I only install it on the host platform so I can (cross-)compile projects that depend on it.
I use rebar within buildroot, which set CC and other environment variables to something else. Here is the exact call to rebar:

(cd /home/johan/Documents/buildroot/output/build/erlang-p1-tls-b070004; CC="/home/johan/Documents/buildroot/output/host/usr/bin/arm-buildroot-linux-uclibcgnueabi-gcc" CFLAGS="-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64   -Os " LDFLAGS="" ERL_COMPILER_OPTIONS='{i, "/home/johan/Documents/buildroot/output/host/usr/arm-buildroot-linux-uclibcgnueabi/sysroot/usr/share/rebar/deps"}' ERL_EI_LIBDIR=/home/johan/Documents/buildroot/output/host/usr/arm-buildroot-linux-uclibcgnueabi/sysroot/usr/lib/erlang/lib/erl_interface-3.7.20/lib PATH="/home/johan/Documents/buildroot/output/host/bin:/home/johan/Documents/buildroot/output/host/sbin:/home/johan/Documents/buildroot/output/host/usr/bin:/home/johan/Documents/buildroot/output/host/usr/sbin:/home/johan/cov-analysis-linux64-6.6.1/bin:/home/johan/bin:/home/johan/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"  rebar deps_dir=/home/johan/Documents/buildroot/output/host/usr/arm-buildroot-linux-uclibcgnueabi/sysroot/usr/share/rebar/deps compile )
==> erlang-p1-tls-b070004 (compile)
Compiled src/p1_tls_app.erl
Compiled src/p1_sha.erl
Compiled src/p1_tls_sup.erl
Compiled src/p1_tls.erl
Compiling c_src/p1_tls_drv.c
arm-buildroot-linux-uclibcgnueabi-gcc: error: unrecognized command line option ‘-m64’
ERROR: compile failed while processing /home/johan/Documents/buildroot/output/build/erlang-p1-tls-b070004: rebar_abort

What do you mean by does rebar know it's cross-compiling?

@liskin

Well, rebar uses rebar_utils:get_arch() which in turn does

otp_release() ++ "-" ++ erlang:system_info(system_architecture) ++ "-" ++ wordsize()

So if you run rebar like you do, it thinks it builds for your host platform and not for the arm, and adds CFLAGS as if it did build for the host. Apparently it doesn't support crosscompiling as the get_arch function has no way to override it.

In that case I think you'll need a few workarounds. Try putting this in rebar.config:

{port_env, [{"CFLAGS", "$CROSS_CFLAGS"}]}

And set CROSS_CFLAGS instead of CFLAGS in your environment.

@liskin

(and I'm sure there's a solution that may make rebar check if CC is set to a crosscompiler and then use either CFLAGS or CROSS_CFLAGS, but that may require rebar.config.script and I've never worked with that, so I'll leave this to you to figure it out)

@joudinet

I've set ERLANG_ARCH=32 and ERLANG_TARGET=arm-buildroot-linux-uclibcgnueabi but it still add the -m64 flag to CFLAGS :-1:

@joudinet

I've also tried to set CROSS_CFLAGS, without any success.
I don't understand why you add -m64 to CFLAGS for multiarch support. Does multiarch mean 64-bit architectures only? To me, this "fix compiler invocation" commit actually breaks my compiler invocation because I cannot compile for 32-bit architecture any more.
If rebar_utils:get_arch() returns information from the host, why using such information to guess (wrongly) the target options for the compiler?

@liskin

Multiarch more or less means running x86_64 kernel with parts of userspace being 32 bit and other parts being 64 bit. My debian installation has 32 bit gcc and 64 bit erlang, so I need to pass -m64 to my 32 bit gcc when building to generate 64 bit machine code. The same problem would happen if I had 32 bit erlang and 64 bit gcc.

Using rebar_utils:get_arch to guess the target options isn't exactly wrong, it's just that there's no support for cross compilation in rebar and target=host is assumed. You might want to look at #451 for cross compilation support. Or you should be able to reset CFLAGS to whatever you want using port_env.

@joudinet

I see. Since I provide these options to compile several erlang projects, I can't use the port_env option to reset CFLAGS. However, I do like the #451 solution and it is indeed something missing in rebar as well as in several build tools but the autotools. So, I guess I'm going to revert your commit locally, until #451 is available. Thanks for the link.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 20, 2014
  1. @liskin

    Fix compiler invocation on multiarch Linux

    liskin committed
    This fixes port compilation for some configurations, notably this one:
    Debian with 32-bit userspace, 64-bit kernel and 64-bit erlang packages.
Showing with 5 additions and 0 deletions.
  1. +5 −0 src/rebar_port_compiler.erl
View
5 src/rebar_port_compiler.erl
@@ -581,6 +581,11 @@ default_env() ->
{"solaris.*-64$", "CXXFLAGS", "-D_REENTRANT -m64 $CXXFLAGS"},
{"solaris.*-64$", "LDFLAGS", "-m64 $LDFLAGS"},
+ %% Linux specific flags for multiarch
+ {"linux.*-64$", "CFLAGS", "-m64 $CFLAGS"},
+ {"linux.*-64$", "CXXFLAGS", "-m64 $CXXFLAGS"},
+ {"linux.*-64$", "LDFLAGS", "-m64 $LDFLAGS"},
+
%% OS X Leopard flags for 64-bit
{"darwin9.*-64$", "CFLAGS", "-m64 $CFLAGS"},
{"darwin9.*-64$", "CXXFLAGS", "-m64 $CXXFLAGS"},
Something went wrong with that request. Please try again.