• How to cross-compile assembly language routines for different architect

    From Steve Keller@21:1/5 to All on Tue Feb 2 10:16:43 2021
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James K. Lowden@21:1/5 to Steve Keller on Tue Feb 2 12:11:37 2021
    On Tue, 2 Feb 2021 10:16:43 +0100
    Steve Keller <keller.steve@gmx.de> wrote:

    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

    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Steve Keller on Tue Feb 2 19:58:31 2021
    On 2021-02-02, Steve Keller <keller.steve@gmx.de> wrote:
    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.

    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.

    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.

    Another idea:

    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 $< $@

    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jorgen Grahn@21:1/5 to Steve Keller on Wed Feb 3 07:07:20 2021
    On Tue, 2021-02-02, Steve Keller wrote:
    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 .

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)