Discussion:
How to cross-compile assembly language routines for different architectures
(too old to reply)
Steve Keller
2021-02-02 09:16:43 UTC
Permalink
How should I write a Makefile so that I can compile one of a number of
source files, depending on the architecture the code is compiled for.

Say, I have a source foo.c and several files implementing a function bar(),
in C and in assembly language for several architectures, e.g. bar.c,
bar-i386.s, bar-amd64.s, and bar-mips.s.

Currently, my Makefile looks similar to this

foo: foo.o bar.o
$(CC) $(LDFLAGS) -o foo foo.o bar.o $(LDLIBS)

ARCH = $(shell uname -m)
ifeq ($(ARCH),x86_64)
bar.o: bar-amd64.o
cp $< $@
else ifeq ($(ARCH),i686)
bar.o: bar-i386.o
cp $< $@
else ifeq ($(ARCH),mips)
bar.o: bar-mips.o
cp $< $@
else
bar.o: bar.c

endif

This works as long as I compile natively but not for cross-compilation. So
my questions is how to write the Makefile so that I can call

make CC=mips-linux-gcc

or on an x86 system

make CC="gcc -m64" or
make CC="gcc -m32"

and have the correct assembly file compiled and linked into the executable.

Steve
James K. Lowden
2021-02-02 17:11:37 UTC
Permalink
On Tue, 2 Feb 2021 10:16:43 +0100
Post by Steve Keller
How should I write a Makefile so that I can compile one of a number of
source files, depending on the architecture the code is compiled for.
Since make transforms input to output by filename pattern, I would
answer your question by distinguising outputs by filename.

Your outputs could be

build/x86_64
build/i686
build/mips

and instead of
Post by Steve Keller
foo: foo.o bar.o
you have

build/x86_64/%.o : %.c
$(CC.x86_64) -o $@ $^

build/i686/%.o : %.c
$(CC.i686) -o $@ $^

build/mips/%.o : %.c
$(CC.mips) -o $@ $^

build/x86_64/foo: build/x86_64/foo.o build/x86_64/bar.o
# etc.

I think the rest follows straightforwardly from there.

--jkl
Kaz Kylheku
2021-02-02 19:58:31 UTC
Permalink
Post by Steve Keller
How should I write a Makefile so that I can compile one of a number of
source files, depending on the architecture the code is compiled for.
Say, I have a source foo.c and several files implementing a function bar(),
in C and in assembly language for several architectures, e.g. bar.c,
bar-i386.s, bar-amd64.s, and bar-mips.s.
Currently, my Makefile looks similar to this
foo: foo.o bar.o
$(CC) $(LDFLAGS) -o foo foo.o bar.o $(LDLIBS)
ARCH = $(shell uname -m)
Inquire the cross-compiler, not uname.

If it is GCC with a GNU linker, this couild be done, among other
possibilities.

Capture the output of this command, and parse it:

$(CC) -Wl,--print-output-format 2> /dev/null

I.e. we ask the linker (indirectly thorugh the compiler invocation)
what is the output format, which produces a string like elf32-i386.
Post by Steve Keller
This works as long as I compile natively but not for cross-compilation. So
my questions is how to write the Makefile so that I can call
make CC=mips-linux-gcc
Well, here is a possible answer. Just take $(basename $(CC)) and parse
that.
Post by Steve Keller
and have the correct assembly file compiled and linked into the executable.
If the amount of assembly language is small, you can put it all in one
file. There are certain benefits in doing so, because the code may
be able to use some shared #define macros.

An example of this is the jmp.S file in my TXR project:

http://www.kylheku.com/cgit/txr/tree/jmp.S

It has i386, i686, arm, aarch64, PPC and MIPS all in one file.
Post by Steve Keller
ifeq ($(ARCH),x86_64)
bar.o: bar-amd64.o
else ifeq ($(ARCH),i686)
bar.o: bar-i386.o
else ifeq ($(ARCH),mips)
bar.o: bar-mips.o
This copy pointless: if you know what .o is needed, then you pull it
into OBJS:

ifeq ($(ARCH),x86_64)
OBJS += bar-amd64.o
else ifeq ...

Or even:

OBJS = foo.o ... bar-$(ARCH).o ...

using an adjusted ARCH which matches your convention, calculated
elsewhere.
--
TXR Programming Language: http://nongnu.org/txr
Cygna: Cygwin Native Application Library: http://kylheku.com/cygnal
Jorgen Grahn
2021-02-03 07:07:20 UTC
Permalink
Post by Steve Keller
How should I write a Makefile so that I can compile one of a number of
source files, depending on the architecture the code is compiled for.
...

In case everything else fails, consider having N different Makefiles.
Most of the time my Makefile stays unchanged, except I may add more
source files, which translates to another object file in a list in the
Makefile. Adding the file in two or three places isn't that bad.

I'd still do what someone else suggested and put everything generated
and target-specific in separate directories: you don't want to do
'make clean' manually whenever you switch targets.

/Jorgen
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Loading...