How to cross compile in linux - c

I have a makefile and if I want to compile it for different compilers what changes do I need in my makefile? One I know is to change CC value that is my compiler. What other changes do I need? For example
my here is my make file:
CC=gcc
CFLAGS=-c -Wall
all: hello
hello: main.o factorial.o hello.o
$(CC) main.o factorial.o hello.o -o hello
main.o: main.cpp
$(CC) $(CFLAGS) main.cpp
factorial.o: factorial.cpp
$(CC) $(CFLAGS) factorial.cpp
hello.o: hello.cpp
$(CC) $(CFLAGS) hello.cpp
clean:
rm -rf *o hello
What changes do I need it to compile it for an other processor?
And how to know the name of compiler linker arch etc. of the processor?

It depends.
If you are already using a compiler that can emit code for different targets, it is a question of setting the proper flags, e.g. imagine CC=süper-cross-compiler and CFLAGS=eye-phone.
If you must switch to another compiler which has compatible flags, you would have to to change your $(CC) variable and probably others, or possibly you set another alias in your shell environment.
There's a Linux port of the GCC windows port MinGW. Some distributions ship it as mingw-gcc; on them, you would CC=mingw-gcc.
In any case and in general, you have to tweak multiple stuffs. It all depends on the exact circumstances.

In make define CC as
CC=$(CROSS)gcc
Invoke make like
CROSS=ppc_8xx- make
CROSS can be arm-linux-gnu- or whatever.

Related

Why am I getting this error Makefile: No rule to make target 'timer.c', needed by 'timer.o'. Stop

My working directory looks like this:
main.c
Makefile
my_memmove.h
my_memmove.c
c-timer-lib
timer.c
timer.h
My makefile looks like this:
CC := gcc
CFLAGS := -std=gnu99 -g -Wall -Wextra -Ic-timer-lib
TARGET := output
output: main.o my_memmove.o timer.o
$(CC) $(CFLAGS) main.o my_memmove.o timer.o -o $(TARGET)
main.o: main.c
gcc -c main.c
my_memmove.o: my_memmove.c my_memmove.h
gcc -c my_memmove.c
timer.o: c-timer-lib/timer.c c-timer-lib/timer.h
gcc -c c-timer-lib/timer.c -o $#
clean:
rm *.o $(TARGET)
I don't understand why I keep getting the "Makefile: No rule to make target 'timer.c', needed by 'timer.o'. Stop." error. I believe that it's because the timer.c and timer.h files can't be found.
So much confusion here! :)
First, this is definitely wrong:
$(CC) $(CFLAGS) -I main.o ...
The -I main.o tells the compiler that it should use main.o as the name of a directory to search for include files. That clearly won't work. You should remove the -I here.
On to your problem: you have to realize that there are two completely different programs at play here: make which figures out how to run commands, and the commands that are being run, in this case the compiler gcc.
The -I option is an option to the compiler so that the compiler knows where to look for header files that are included by your source code with #include.
That option means nothing to make; it doesn't understand that option. It's just some text to pass to the compiler. Make is looking for the source file timer.c and it can't find it because you haven't told make where it is.
You have to write your rule to look in the correct place, like this:
timer.o: c-timer-lib/timer.c c-timer-lib/timer.h
gcc -c c-timer-lib/timer.c -o $#
(you should always use -o $# so that your compile line puts the output file where make expects to find it, which will be put into the $# variable by make before it evaluates your recipe.)
ETA
Also, are you sure that -DUNITS="ms" is right? We can't tell without seeing how UNITS is used in the source, but I suspect you probably need an extra level of quotes here, like -DUNITS='"ms"'
Really, you are trying to do too much in this makefile. Make already knows how to correctly build object files from source files. If you don't force the issue by writing your own rules, then make's built-in rules will do the job for you. Your makefile can be written like this:
CC := gcc
CFLAGS := -std=gnu99 -g -Wall -Wextra -Ic-timer-lib -DUNITS='"ms"'
TARGET := output
$(TARGET): main.o my_memmove.o c-timer-lib/timer.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $^ $(LDLIBS)
my_memmove.o: my_memmove.h
c-timer-lib/timer.o: c-timer-lib/timer.h
clean:
rm *.o $(TARGET)
make doesn't know which headers your source requires so you have to add the prerequisites by hand, although you can add extra rules to allow it to figure that out for itself.

/usr/bin/x86_64-linux-gnu-ld: cannot find?

I study C language in ubuntu 18.04(gcc 7.3)
When the make all command is entered, this error occurrs:
/usr/bin/x86_64-linux-gnu-ld: can not find -lkeccak
The Makefile is as follows.
CC=gcc
CFLAGS=-03 -fomit-frame-pointer -msse2avx -mavx2 -march=native -std=c99
all:
$(CC) $(CFLAGS) -c Lizard.c main.c randombytes.c sha512.c
$(CC) $(CFLAGS) -o Lizard Lizard.o main.o randobytes.o sha512.o -lkeccak
run: all
./Lizard
new:
make clean
make all
./Lizard
Currently the libkeccak.a file is in the same directory as the Makefile and
it is also in the /usr/include directory.
I do not know the solution method at all.
Please, Help me.
The -l option is for linking dynamic libraries (like libkeccak.so). Static libraries are linked into the executable already if they're in one of the "standard" directories, so there's no need to provide the option -lkeccak.
If you want to explicitly tell GCC to link a static library,
gcc -l:/path/to/libkeccak.a

How to make a proper C makefile

so far I have learned this kind of makefile :
finalcode : code.o
gcc -g -ansi -Wall -pedantic code.o -o finalcode
code.o : code.c
gcc -c -ansi -Wall -pedantic code.c -o code.o
I'm interested in learning the better version
all:
clean:
etc..
where can I learn how to write a more "professional" makefile?
thanks in advance!
So you just want the typical "phony" targets? That's simple, make all the first rule (so it's the default) and have it depend on anything you want to have built, e.g.:
all: finalcode
Then, in clean, just write a script to delete whatever should be cleaned, e.g.:
clean:
rm -f *.o
Finally, don't forget to make these rules "phony", so make knows they don't actually create files with these names:
.PHONY: all clean
Done.
As for "professional", that's quite subjective, but I'd start by defining variables for the compiler (CC), flags (CFLAGS), includes and so on and use these. If you are fine with a bit loss of portability, use pattern rules e.g. for creating the object files like
%.o: %.c
$(CC) -c -o$# $(CFLAGS) $(INCLUDES) $<

GCC exiting with an error 1 even with -Wall. No explanation why?

So I tried to recompile one of my projects from a few weeks ago and to my surprise I keep receiving an error one on it. I used MinGW to compile it originally and Eclipse CDT. I have -Wall flag enabled on GCC so I assumed if it was a problem with the code I would have a more useful information than a make error 1 being thrown. As such, I suspect that the issue could lie in how I formatted the make file. Luckily, I did compile the project when I push the commits last time and the binaries are still in the repo. Nevertheless, I would appreciate some help so that I can continue to improve
the project.
Edit: when I do -all, it just refuses to compile.
Here is the makefile. I hope it is a simple as me following some incorrect syntax:
CC=gcc -I../Include -L..\Lib
override CFLAGS+=-Wall -O3 #$(shell pkg-config --cflags fftw3)
#override LDFLAGS+=#$(shell pkg-config --libs fftw3 glib-2.0) -lm
.PHONY: all clean
all: lvdoenc lvdodec
lvdoenc: lvdoenc.o lvdomain.o
$(CC) $(CFLAGS) -o $# $^ $(LDFLAGS) -I../Include -L../Lib -lfftw3
lvdodec: lvdodec.o lvdomain.o
$(CC) $(CFLAGS) -o $# $^ $(LDFLAGS) -I../Include -L../Lib -lfftw3
%.o: %.c
$(CC) -c $(CFLAGS) -o $# $^
lvdoenc.c: lvdocommon.h
lvdodec.c: lvdocommon.h
clean:
rm -f lvdoenc lvdodec lvdomain.o lvdoenc.o lvdodec.o
Here is a link to my repo:
https://github.com/Skylion007/LVDOWin
Update: Using some of the answers I have confirmed that it is GCC that is exiting with an error 1 and I cannot figure out why.
Update2: It's not printing anything to syserr.
Without a transcript of make's output, when you run it, I can't see why GCC should fail silently, but I can see at least two problems with your makefile:
Since you state that you are using MinGW, your target platform must be MS-Windows, on which executable files should be qualified by a .exe extension; thus, your all: lvdoenc lvdodec rule is malformed; it should, at the very least be all: lvdoenc.exe lvdodec.exe[1], (or better, for portability all: lvdoenc$(EXEEXT) lvdodec$(EXEEXT), where you define EXEEXT = .exe for Windows, and leave EXEEXT undefined, or defined to be nothing, for platforms which don't require the extension).
Your two rules lvdoenc.c: lvdocommon.h and lvdodec.c: lvdocommon.h are obviously incorrect; the .c files don't depend on the .h, but their respective .o files do. Thus, these two rules should be lvdoenc.o: lvdocommon.h and lvdodec.o: lvdocommon.h respectively.
[1] Of course, you then also need to correctly refer to these two "goals" respectively, as lvdoenc.exe and lvdodec.exe, (or lvdoenc$(EXEEXT) and lvdodec$(EXEEXT)), consistently, throughout the makefile.
There are a few other constructs, within your makefile, which I consider questionable: CC shouldn't really be defined, with the -I../Include or -L..\Lib, (and why inconsistently / in the former, but \ in the latter? Both should be /). Conventionally, -I ... belongs in CPPFLAGS, and -L ... in LDFLAGS, with both CFLAGS and CPPFLAGS passed to the compiler, and normally all of CFLAGS, CPPFLAGS, and LDFLAGS passed to the compiler driver, when invoking the linker, (although, as others have noted in comments, the -I ... settings are strictly necessary when compiling .c to .o, while the -L ... settings are required only in the linking phase).
the following makefile is more in line with what you need for your project.
However, it does not use:
#$(shell pkg-config --libs fftw3 glib-2.0)
which you will need to re-add.
notice the usage of ':=' when defining macros, so the macro only needs to be evaluated once, rather than every time it is referenced.
the paths for the SHELL macro and the CC macro may need to be modified for your system.
SHELL := /usr/bin/sh
CC := /usr/bin/gcc
#CFLAGS := -c -Wall -Wextra -pedantic -std=c99 -O3 #$(shell pkg-config --cflags fftw3)
CFLAGS := -c -Wall -Wextra -pedantic -std=c99 -O3
# override LDFLAGS+=#$(shell pkg-config --libs fftw3 glib-2.0) -lm
LDFLAGS :=
SRCS := $(wildcard *.c)
ENCOBJS := lvdoenc.o lvdomain.o
DECOBJS := lvdodec.o lvdomain.o
.PHONY: all clean
all: lvdoenc lvdodec
lvdoenc: $(ENCOBJS)
$(CC) $(LDFLAGS) -o $# $(ENCOBJS) -L../Lib -lfftw3 -lm
lvdodec: $(DECOBJS)
$(CC) $(LDFLAGS) -o $# $(DECOBJS) -L../Lib -lfftw3 -lm
%.o:%.c lvdocommon.h
$(CC) -c $(CFLAGS) -c $< -o $# -I../Include
clean:
rm -f lvdoenc lvdodec lvdomain.o lvdoenc.o lvdodec.o
Apparently, all that was the cause was that I had uninstalled the 64bit version of MinGW and tried to switch to the 32bit version of MinGW. Unfortunately, some of the libraries would not compile in the 32bit version so I just used MinGW-w instead to solve this problem. It turns out GCC was not starting due to a linker error, but this error was not proportionating and could not be discovered until I tried to run it from the Windows terminal. I am still in the process of solving it and will update this answer when I have fully solved the issue.
Had the same problem while tried to compile my project with make from MSys. Accidentally problem had been solved, after I added a quotes to gcc input and output files in the makefile. I don't know how it works, but hope that it will help someone else.
So in the TS example code should look like this
%.o: %.c
$(CC) -c $(CFLAGS) -o "$#" "$^"
PS: had no problems with building project from ubuntu terminal though, so maybe it's just a msys problem.

When I use "gcc" in makefile, after making it, I got a "cc" output

For example:
There are 3 source files {main.c test1.c test2.c} in the directory
and a directory file named test3,
and there is a source file named test.c in the directory of test3.
Now I want to create a makefile to compile and link these four source files.
And this is my Makefile:
# Cancel statement "CC=gcc"
src:=$(wildcard *.c) test3.c
obj:=$(patsubst %.c,%.o,$(src))
main:$(obj)
gcc -o main $(obj)
.PHONY:clean
clean:
rm *.o *~
When I called make to compile them, I got a output like this:
cc -c -o main.o main.c
cc -c -o test1.o test1.c
cc -c -o test2.o test2.c
cc -c -o test3.o test3/test3.c
gcc -o main main.o test1.o test2.o test3.o
I know 'cc' is linked to 'gcc' in Linux.
What I don't understand is why did Make call cc to compile these four source files, but call gcc to link the object files?
You changed one rule: the one that links the program main from the object files. And when make did that link, you can see it used gcc.
You didn't do anything to change the built-in rules that make is using to compile the object files, so they use the default (the value of the variable CC) which is cc.
You wrote only the rule to link the object files, and allowed Make to use its default rule to decide how to build the object files from the source files.
GNU Make will expose its rules if you ask it with --print-data-base. In this case, it tells us
%.o: %.c
# recipe to execute (built-in):
$(COMPILE.c) $(OUTPUT_OPTION) $<
and
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
and finally
CC = cc
This explains why Make uses cc to compile your C sources. To change that, simply set CC = gcc. Here's a complete Makefile which does that and also makes best use of Make's built-in rules, to help when you need to extend it:
src := $(wildcard *.c) test3.c
obj := $(patsubst %.c,%.o,$(src))
CC = gcc
main: $(obj)
$(LINK.c) -o $# $^ $(LDLIBS)
.PHONY: clean
clean:
$(RM) *.o *~

Resources