Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to modify Makefile to support cross compilation?

I have the following Makefile:

CC=g++

top_srcdir=$(SRC_DIR)/cpp/src/

INCLUDES:= -I $(top_srcdir) -I $(top_srcdir)command_classes -I $(top_srcdir)platform -I $(top_srcdir)value_classes
LIBS:= -lopenzwave -lpthread -ludev
LDFLAGS += -L$(SRC_DIR) -Wl,-R$(SRC_DIR) '-Wl,-R$$ORIGIN'

all:    ozw

ozw: Main.cpp
    $(CC) $(INCLUDES) -c Main.cpp -o ozw-power-on-off.o
    $(CC) $(LIBS) $(LDFLAGS) ozw-power-on-off.o -o ozw-power-on-off.out

clean:
    rm -rf *.o *.out

I execute it with the following command:

  make ARCH=$TARGET_ARCH \
       CROSS_COMPILE=$TARGET_PREFIX \
       SRC_DIR=$ROOT/$PKG_BUILD

But it ignores ARCH and CROSS_COMPILE values. I tried to replace $(CC) with $(MAKE) and added -$(MAKEFLAGS), but it was saying Nothing to be done for 'Main.cpp'.

How can I fix it and add cross compilation support?

like image 332
LA_ Avatar asked Jun 16 '16 18:06

LA_


2 Answers

The things you are passing to make (e.g. ARCH=$TARGET_ARCH) are really just Makefile variables. make doesn't know at all that they are related to cross-compilation (this is just something that you associate in your brain). E.g.

 $ cat Makefile
 ARCH=pdp-11
 foo:
    @echo arch: $ARCH
 $ make
 arch: pdp-11
 $ make ARCH=le-corbusier
 arch: le-corbusier

The standard way to do cross-compilation is to just override the compiler/linker. E.g. the following would cross-compile for i686-w64-mingw32:

  $ cat Makefile
  .PHONY: ozw
  owz: ozw-power-on-off.out
  ozw-power-on-off.o: Main.cpp
      $(CXX) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS) -c $^ -o $@
  ozw-power-on-off.out: ozw-power-on-off.o
      $(CXX) -o $@ $(LDFLAGS) $^ $(LIBS)

  $ make CXX=i686-w64-mingw32-g++

a few notes

Your makefile has a number of issues...

variable names

CC is the standard variable for the C-Compiler; for a C++-compiler use CXX

linking order matters

Modern linkers will discard unused symbols, leading to possible linker errors if you don't get the order right. Therefore you should puts the $(LIBS) variable at the very end of your linker-invocation

declare dependencies

The power of make really is in the ability to resolve dependencies (finding out which parts of the build tree need to be recompiled when a few files have changed). For this to work you need to write rules that encode these dependencies - rather than conjure arbitrary target names and force to rebuild everything.

like image 92
umläute Avatar answered Sep 21 '22 11:09

umläute


A possible example of something I would try is below assuming $ARCH get's mapped to "arm" in this trivial example. I haven't tested it, but have done something similar before.

CC=g++
CC-arm=arm-g++

ozw: Main.cpp
    $(CC-$(ARCH)) $(INCLUDES) -c Main.cpp -o ozw-power-on-off.o
    $(CC-$(ARCH)) $(LIBS) $(LDFLAGS) ozw-power-on-off.o -o ozw-power-on-off.out

edit: This assumes that the tool chain exists in your path. edit: Might also modify it such that CC=$(PREFIX)-g++ it all depends on what you how what you pass into it maps against your tool chains naming convention.

like image 32
Aumnayan Avatar answered Sep 21 '22 11:09

Aumnayan