Using Make for compiling C - c

I am trying to learn make to make my compiling easier as I learn C.
I am attempting to do:
gcc -Wall -g 3.c -o 3 -lm
using
CC = gcc
CFLAGS = -Wall -g
clean:
rm -f 3
but I don't know how and where to put -lm in the makefile. I've looked for tutorials online but they haven't specifically addressed the "-lm" option, or if they do it is without little explanation and doesn't work in my situation.

You need a "target" in which to execute the gcc command. Like:
CC = gcc
CFLAGS = -Wall -g
all:
gcc -Wall -g 3.c -o 3 -lm
clean:
rm -f 3
Then you can just replace parts of the "all" command, with your macros; CFLAGS, for example would probably have the "-lm".
It might help if you ran "make -n", that will tell you what make would do if it were to run.

Often you'll see library specific flags in a LIBS variable, e.g.:
CC = gcc
CFLAGS = -Wall -g -I/some/include/directory
LIBS = -lm -L/some/library/directory
all:
$(CC) $(CFLAGS) $(LIBS) 3.c -o 3

The variable you are looking for is called LDLFAGS. From §10.3 of the GNU Make manual:
LDFLAGS
Extra flags to give to compilers when they are supposed to invoke the linker, ‘ld’.
So, simply do:
LDFLAGS += -lm
Hope it helps.

An extremely good tutorial: Make Tutorial: How-To Write A Makefile
and here is a good generic makefile I wrote:
http://pastebin.com/PCk0gNtE
The part that would most interest you would be this section:
# C Preprocessor Flags
CPPFLAGS +=
# compiler flags
CFLAGS += -ansi -Wall -Wextra -pedantic-errors
# libraries to link to ( m == math )
program_LIBRARIES := m
# LDFLAGS is the variable to hold linker flags
LDFLAGS += $(foreach library,$(program_LIBRARIES),-l$(library))

GNU make defines a lot of default rules. For C compilation and linking, those rules are:
n.o is made automatically from n.c with a recipe of the form ‘$(CC) $(CPPFLAGS) $(CFLAGS) -c’.
n is made automatically from n.o by running the linker (usually called ld) via the C compiler. The precise recipe used is ‘$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)’.
So the way to add "-lm" option to the linker is by defining:
LDLIBS = -lm
Then when you run make with your Makefile, you following commands will be run:
gcc -Wall -g -c 3.c
gcc 3.o -o 3 -lm
(note that make will compile your C program in 2 steps, first creating the object file 3.o then linking the object file into the executable 3)
(see http://www.gnu.org/software/make/manual/ for the GNU make manual)

Related

Makefile: "undefined reference to cos"

I have just started learning about makefile files. I created a program that consists of two functions and wanted to use a makefile to put it all together. This is my file:
#Makefile
all: main
main: main.o find_root.o
clang -o main main.o find_root.o
main.o: main.c
clang -c -Wall --pedantic -std=c11 main.c -lm
find_root.o: find_root.c
clang -c -Wall --pedantic -std=c11 find_root.c -lm
clean: rm -f main *.o*
However, when I run this, I get an error - "undefined reference to cos". I am using the cosine functions in my program, but I have already linked the library to the compilation of those two files. I thought about adding "-lm" to the first clang option as well. This led to no errors, but it made a warning instead - saying that "-lm linker is unused". What should I change in my file?
The "-lm" is a linker option but you have only included it in your compilation rule (main.o: main.c). You need to include it in your linker rule (main: main.o find_root.o).
As it stand the -lm option is ignored during compilation and missing during linking.
The linker flags aren't used when compiling, but when linking, so the command for the main rule should have -lm, rather than the command for the *.o files.
Better would be just to set the appropriate variables, and let Make use its built-in rules:
#Makefile
LDLIBS += -lm
CFLAGS += -Wall --pedantic -std=c11
C = clang
all: main
main: main.o find_root.o
$(LINK.c) $^ $(LDLIBS) -o $#
clean:
$(RM) main *.o *~

Compiling multiple C and header files with 1 main

[Files in my directory][1]
Need help compiling in a make file.
So I have this link list assignment i'm doing and the directions were.
stringlist.h is supposed to contain the node and the function prototypes
stringlist.c is supposed to have the functions completed that are defined in stringlist.h. BUT stringlist.c is not supposed to contain main at all. Then, namelist.c is supposed to contain main and just have the I/O and its just supposed to call the command functions that are in stringlist.c.
So to compile this we are supposed to create a make file. Whenever I try to I get an error because main doesn't exit in one of the c files. Throughout the term we compiled code like this "gcc -std=gnu99 -m32 -Wall -g -o file file.c"
But it doesn't work.
How would I create the make file? Been spending hours and can't figure it out.
As stated by Jonathan Leffler, the sample Makefile I provided had a few bad ideas. Here's an improvement:
# compiler:
CC = gcc
# compiler flags:
CFLAGS = -g -Wall
# the build target executable:
TARGET = executable
# object files to build:
OBJ = namelist.o stringlist.o
all: $(TARGET)
$(TARGET): $(OBJ)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJ)
Try this:
OBJ := namelist.c stringlist.c
GCC := gcc -g
CFLAGS := -std=gnu99 -m32 -Wall
compile: $(OBJ)
$(GCC) $(CFLAGS) $(OBJ) -o executable

FLAG=-DNDEBUG is not disabling assert() in C

I have a bunch of assert() functions I used throughout my C files and from reading I have done I should be able to disable the assertions by passing in a command line parameter like so:
make
Doing this does not disable the assertions. However, adding into the code, #define NDEBUG does disable the assertions. I want to disable them from the command line though. Is there a reason why this flag is not working correctly?
I am on a Windows machine.
Here is the makefile:
OPTIONS = -B CFLAGS=-DNDEBUG -ansi -pedantic -Wall -Werror
a.out: myProgram.o StudentImplementation.o ListImplementation.o
gcc $(OPTIONS) myProgram.o StudentImplementation.o ListImplementation.o
myProgram.o: myProgram.c StudentInterface.h StudentType.h ListInterface.h ListType.h
gcc $(OPTIONS) -c myProgram.c
StudentImplementation.o: StudentImplementation.c StudentInterface.h StudentType.h
gcc $(OPTIONS) -c StudentImplementation.c
ListImplementation.o: ListImplementation.c ListInterface.h ListType.h StudentInterface.h StudentType.h
gcc $(OPTIONS) -c ListImplementation.c
clean:
rm *.o a.out
If you have a normal makefile or no makefile, then the command you want is
make -B CFLAGS=-DNDEBUG
There is no FLAG variable in the standard make recipes; each component has its own variable, so CFLAGS is for C, CXXFLAGS is for C++, LDFLAGS is for the linker, and so on.
With the Makefile you provide in the question, you cannot change flags on the make command line. You could use
OPTIONS = -DNDEBUG -ansi -pedantic -Wall -Werror
but that means editing your Makefile every time you want to change the debug setting.
You simply need
OPTIONS = -DNDEBUG -ansi -pedantic...
However a simpler Makefile would look like this
CFLAGS = -DNDEBUG -ansi -pedantic -Wall -Werror -I.
a.out: myProgram.o StudentImplementation.o ListImplementation.o
clean:
rm *.o a.out
According to my Unix makefile experience, the default flag should be CFLAGS, unless of course FLAG is explicitly used in your makefile. However, defining CFLAGS on the command line is not recommended since it is overriding a make variable.
Are there any -DNDEBUG in the compiler call invocations? If not, perhaps the problem lies in the Makefile itself, and you will have to provide its relevant data.

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.

Location of -lpthread in C Makefile

I'm pretty new to Makefiles in C. I am trying to figure out where I would put -lpthread in my makefile so I can implement posix threads in my C program. Below is my Makefile, thanks in advance.
CFLAGS = -g -Wall
LDFLAGS =
CC = gcc
LD = gcc
TARG1 = calc
OBJS1 = calc.o
$(TARG1): $(OBJS1)
$(LD) $(LDFLAGS) $(OBJS1) -o $(TARG1)
clean:
rm -rf $(TARG1) $(OBJS1)
I would recommend not using -l. Instead give GCC -pthread on both the CFLAGS and LDFLAGS variables. This will make sure that preprocessor defines are properly set during the compile and it will link the correct libraries.
This assumes GCC of course. If using Intel icc or LLVM check for the right parameters.

Resources