This repository has been archived by the owner. It is now read-only.

Fix compiler invocation on multiarch Linux #305

Merged
merged 1 commit into from Jan 30, 2015

Conversation

Projects
None yet
4 participants
@liskin
Contributor

liskin commented Jun 20, 2014

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

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.
@ferd

This comment has been minimized.

Show comment
Hide comment
@ferd

ferd Jun 23, 2014

Contributor

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

Contributor

ferd commented Jun 23, 2014

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

@liskin

This comment has been minimized.

Show comment
Hide comment
@liskin

liskin Jun 23, 2014

Contributor

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

Contributor

liskin commented Jun 23, 2014

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

@ferd

This comment has been minimized.

Show comment
Hide comment
@ferd

ferd Sep 11, 2014

Contributor

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?

Contributor

ferd commented Sep 11, 2014

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

This comment has been minimized.

Show comment
Hide comment
@tuncer

tuncer Sep 18, 2014

Contributor

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.

Contributor

tuncer commented Sep 18, 2014

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.

@tuncer

This comment has been minimized.

Show comment
Hide comment
@tuncer

tuncer Dec 21, 2014

Contributor
Contributor

tuncer commented Dec 21, 2014

@ferd

This comment has been minimized.

Show comment
Hide comment
@ferd

ferd Dec 21, 2014

Contributor

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

Contributor

ferd commented Dec 21, 2014

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

@tuncer

This comment has been minimized.

Show comment
Hide comment
@tuncer

tuncer Dec 22, 2014

Contributor

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

Contributor

tuncer commented Dec 22, 2014

@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

This comment has been minimized.

Show comment
Hide comment
@liskin

liskin Jan 29, 2015

Contributor

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.

Contributor

liskin commented Jan 29, 2015

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 added a commit that referenced this pull request Jan 30, 2015

Merge pull request #305 from liskin/linux-multiarch-64
Fix compiler invocation on multiarch Linux

@ferd ferd merged commit fffc745 into rebar:master Jan 30, 2015

1 check passed

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

This comment has been minimized.

Show comment
Hide comment
@joudinet

joudinet Jun 26, 2015

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?

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

This comment has been minimized.

Show comment
Hide comment
@liskin

liskin Jun 26, 2015

Contributor

@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?)

Contributor

liskin commented Jun 26, 2015

@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

This comment has been minimized.

Show comment
Hide comment
@joudinet

joudinet Jun 26, 2015

(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?

(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

This comment has been minimized.

Show comment
Hide comment
@liskin

liskin Jun 26, 2015

Contributor

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.

Contributor

liskin commented Jun 26, 2015

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

This comment has been minimized.

Show comment
Hide comment
@liskin

liskin Jun 26, 2015

Contributor

(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)

Contributor

liskin commented Jun 26, 2015

(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

This comment has been minimized.

Show comment
Hide comment
@joudinet

joudinet Jun 26, 2015

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

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

@joudinet

This comment has been minimized.

Show comment
Hide comment
@joudinet

joudinet Jun 26, 2015

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?

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

This comment has been minimized.

Show comment
Hide comment
@liskin

liskin Jun 26, 2015

Contributor

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.

Contributor

liskin commented Jun 26, 2015

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

This comment has been minimized.

Show comment
Hide comment
@joudinet

joudinet Jun 29, 2015

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.

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 subscribe to this conversation on GitHub. Already have an account? Sign in.