C makefile errors - c

I have a custom header file example.h which has prototypes for a few functions. There is a .C file example.c that I implemented which "includes" (#include "example.h") and has the implementations of the functions that has prototype in example.h. Now, I have another function test.c that calls the functions that are prototyped in example.h and defined in example.c.
My make file is as follows
test: test.o
gcc -o test -g test.o
test.o: test.c example.c example.h
gcc -g -c -Wall test.c
gcc -g -c -Wall example.c
clean:
rm -f *.o test
I get following message for the functions that are defined in example.c
Undefined first referenced
symbol in file
function1 test.o
function2 test.o
function3 test.o
function4 test.o
ld: fatal: Symbol referencing errors. No output written to test
collect2: ld returned 1 exit status
* Error code 1
make: Fatal error: Command failed for target `test'
Any help is most appreciated.

%.o: %.c
gcc -c -g -o $# $^
test: test.o example.o
gcc -o -g $# $^
%.o: %.c This means any *.o file should be builded from its equivalen from c files.
example test.o should be builded from test.c and example.o should be builded from example.c

First of all, you must include the example.o file when generating the executable file : gcc -o test example.o test.o. Then, the dependencies you wrote for target test.o are incorrect. You should split it like this :
test: test.o example.o
gcc -o test test.o example.o
test.o: test.c
gcc -c -Wall test.c
example.o: example.c
gcc -c -Wall example.c
Then, consider the use of variables to store the names of your object files, the flags you want to pass to the linker/compiler etc... This would make your life much easier.

test.o: test.c example.c example.h
gcc -g -c -Wall test.c
gcc -g -c -Wall example.c
as per your code test.o target is calling test.c example.c example.h target which i am not able to see.

Related

Make two c programs in one makefile

Is it possible to make two files in a single makefile? Essentially a program and a programtest. I have seen other answers, but their syntax went completely over my head. Right now my Makefile only makes one of the programs, and I cant figure out how to have it make both
Would it be possible for someone to provide a template for how a Makefile would be structured to compile two programs?
all: main test
test: objects/Math.o objects/Stack.o objects/Queue.o objects/myUnitTesting.o objects/test.o
gcc objects/test.o objects/Math.o objects/Stack.o objects/Queue.o objects/myUnitTesting -o test
main: objects/Stack.o objects/Queue.o objects/Math.o objects/Point.o objects/main.o
gcc objects/main.o objects/Stack.o objects/Queue.o objects/Point.o objects/Math.o -o main
objects/test.o: test.c
gcc -g -Wall -O -c -o objects/test.o test.c
objects/main.o: main.c
gcc -g -Wall -O -c -o objects/main.o main.c
objects/myUnitTesting.o: cs/myUnitTesting.c
gcc -g -Wall -O -c -o objects/myUnitTesting cs/myUnitTesting.c
objects/Math.o: cs/Math.c
gcc -g -Wall -O -c -o objects/Math.o cs/Math.c
objects/Stack.o: cs/Stack.c
gcc -g -Wall -O -c -o objects/Stack.o cs/Stack.c
objects/Queue.o: cs/Queue.c
gcc -g -Wall -O -c -o objects/Queue.o cs/Queue.c
objects/Point.o: cs/Point.c
gcc -g -Wall -O -c -o objects/Point.o cs/Point.c
clean:
rm -f objects/*o main
Then you only need to type:
make all
and it is going to compile your main.c and test.c files
You can multiple exes in one makefile, here is sample for building 2,
you need to do make all to build
prog1: prog1.o
gcc prog1.o -o prog1 2>>compile.log 1>&2
prog2: prog2.o
gcc prog2.o -o prog2 2>>compile.log 1>&2
all: prog1 prog2
.c.o:
gcc -o $# -c $*.c 2>>compile.log 1>&2
Here is a scenario where 2 targets are main1 and main2.
TARGET1 = main1
TARGET2 = main2
$(TARGET1): main1.o
gcc main1.o -o $#
$(TARGET2): main2.o
gcc main2.o -o $#
%.o: %.c
gcc -c $< -o $#
run1: $(TARGET1)
./$(TARGET1)
run2: $(TARGET2)
./$(TARGET2)
all: $(TARGET1) $(TARGET2)
./$(TARGET1)
./$(TARGET2)
Remember that the indentation is a <tab> character, not space characters.
The following command will compile and run main1 executable.
make run1
The following command will compile and run main2 executable.
make run2
The following command will compile and run main1 executable followed by main2 executable.
make all
It is possible.
Here is a simpler version of the Makefile:
all: program programtest
program:
gcc -o program program.c
programtest:
gcc -o programtest programtest.c
Then you just have to type make:
$ make
gcc -o program program.c
gcc -o programtest programtest.c

Error when trying link jsoncpp and include it in a CUDA project: undefined reference to `Json::Value::Value(Json::ValueType)'

When I try and #include "json/json.h" in a .cu file, then run make, I get the following error:
nvcc -o sound main.o process.o -L /usr/lib -lopencv_core -lopencv_imgproc -lopencv_highgui -O3 -arch=sm_20 -Xcompiler -Wall -Xcompiler -Wextra -m64
/usr/local/cuda/bin/crt/link.stub:90:13: warning: ‘void __cudaRegisterLinkedBinary(const __fatBinC_Wrapper_t*, void (*)(void**), void*)’ defined but not used [-Wunused-function]
process.o: In function `count_tracks()':
tmpxft_00006061_00000000-3_process.cudafe1.cpp:(.text+0x75): undefined reference to `Json::Value::Value(Json::ValueType)'
tmpxft_00006061_00000000-3_process.cudafe1.cpp:(.text+0x7d): undefined reference to `Json::Value::~Value()'
collect2: ld returned 1 exit status
make: *** [student] Error 1
in reference to when I try and create a Json::Value. I've tried moving around where I link JsonCpp library, and I wasn't having this problem #including jsoncpp and creating a Json::Value in the main.cpp of the project. It just doesn't seem to be working correctly when in a .cu file.
Here is the pertinent stuff from my Makefile, which I got from Udacity's CUDA course and modified to fit my needs:
NVCC=nvcc
CXX = g++
LDFLAGS = -L ~/parallelcomputing/soundcloud/jsoncpp/build/debug/lib -ljsoncpp
INC = -I ~/parallelcomputing/soundcloud/jsoncpp/include
OPENCV_LIBPATH=/usr/lib
OPENCV_INCLUDEPATH=/usr/include
OPENCV_LIBS=-lopencv_core -lopencv_imgproc -lopencv_highgui
CUDA_INCLUDEPATH=/usr/local/cuda/include
NVCC_OPTS=-O3 -arch=sm_20 -Xcompiler -Wall -Xcompiler -Wextra -m64
GCC_OPTS=-O3 -Wall -Wextra -m64
student: main.o process.o Makefile
$(NVCC) -o sound main.o process.o -L $(OPENCV_LIBPATH) $(OPENCV_LIBS) $(NVCC_OPTS)
main.o: main.cpp
g++ -c main.cpp $(GCC_OPTS) $(LDFLAGS) $(INC) -I $(CUDA_INCLUDEPATH) -I $(OPENCV_INCLUDEPATH)
process.o: process.cu
nvcc -c process.cu $(NVCC_OPTS) $(LDFLAGS) $(INC)
clean:
rm -f *.o *.png hw
You've got LDFLAGS defined in your makefile, but you're not using it in the link phase that I can see.
As a result, -ljsoncpp doesn't show up in the link command you posted, that is showing the error.
Add LDFLAGS to your link phase:
student: main.o process.o Makefile
$(NVCC) -o sound main.o process.o $(LDFLAGS) -L $(OPENCV_LIBPATH) $(OPENCV_LIBS) $(NVCC_OPTS)
(And while we're cleaning up your makefile, LDFLAGS contains link specification, and is not relevant in, and can be safely deleted from, the subsequent compile targets.)
EDIT:
Since that is not working, but you say the link is successful with a .cpp file, try linking the executable with g++ instead of nvcc:
LDFLAGS2=-L/usr/local/cuda/lib64 -lcudart
student: main.o process.o Makefile
$(CXX) -o sound main.o process.o $(LDFLAGS) $(LDFLAGS2) -L $(OPENCV_LIBPATH) $(OPENCV_LIBS)

function in one shared library calling a function in another shared library

I have a shared library say libfile2.so (which contains print2() function definition). Now I create a libfile1.so (which contains print1() function definition which in turn calls print2() function in libfile2.so). Now I create a main.c file which contains main() function which calls print1() by dynamically linking libfile1.so.
But I am getting the following error:
./libfile1.so: undefined reference to `print2'**
The following are the commands that I am using:
gcc -c -fpic file1.c
gcc -shared -o libfile1.so file1.o
gcc -c -fpic file2.c
gcc -shared -o libfile2.so file2.o
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
gcc -I. -L. -o main main.c -lfile1
If you have called only print1 in your main.c. Then set the path of the libfile2.so in the LD_LIBRARY_PATH. Because it will try to find the dependencies of libfile1.so while linking with main.c.
gcc -o file1.o -c file.c
gcc -o file2.o -c file.c
gcc -o libfile2.so file2.o -shared
gcc -o libfile1.so file1.o -L. -lfile2 -shared
gcc -o main.o -c main.c
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
gcc -o main.exe main.o -L. -lfile1
If you have called both print1 and print2 in main.c then link both libfile1.so and libfile2.so like below.
gcc -o main.o -c main.c
gcc -o main.exe main.o -L$YOUR_LIB_PATH -lfile1 -lfile2
Because all the symbol used in main.c needs to be resolved while generating executable.

How to write makefile to compile with -S and -c?

I have a source file test.c and its header test.h, a file main.c and the makefile.
I want to set up my makefile so that it (1) compiles test.c to build an executable test.o,
and (2) compiles test.c to print the assembly code to test.s using -S flag.
I have tried to set up the makefile as I thought would be correct, but this of course doesn't actually run the last test.s line.
FLAGS = -c -Wall
CC = gcc
ASM = -S
all : optimize
optimize: main.o test.o
$(CC) main.o test.o -o optimize
main.o: main.c test.h
$(CC) $(FLAGS) main.c
test.o: test.h test.c
$(CC) $(FLAGS) test.c
test.s: test.h test.c
$(CC) $(ASM) -Wall test.c
Can anyone tell me how I should have structured this differently, to create both test.s and test.o?
I tried to change the optimize: line and the following one to:
optimize: main.o test.o test.s
$(CC) main.o test.o test.s -o optimize
but the linker gave an error multiple definition of 'test'.
Simply add test.s to the line that starts with optimize:.
What this does is add the rule test.s to the dependencies of the optimize line.
You could also add it to the all line, as suggested by Vaughn Cato.
It's important to know that there is a difference between the rule test.s and the file test.s
You can put anything you want as the name of the rule, but by convention you normally just use the filename.
Here's an example Makefile that will do what you want. I put the dep under all so you can just make asm and I also changed the rule name to asm for clarity.
FLAGS = -c -Wall
CC = gcc
ASM = -S
all : optimize asm
optimize: main.o test.o
$(CC) main.o test.o -o optimize
main.o: main.c test.h
$(CC) $(FLAGS) main.c
test.o: test.h test.c
$(CC) $(FLAGS) test.c
asm: test.h test.c
$(CC) $(ASM) -Wall test.c -o test.s
Finally, because you seem a bit shaky on how Makefiles work, (I don't blame you honestly), I suggest reading this tutorial: http://mrbook.org/tutorials/make/

-lm Not linking math library in makefile

I know this error has been beaten to death, but I cannot seem to get it to work. I have linked my makefile below:
all: gensine info cs229towav
encode.o: encode.h encode.c
gcc -c encode.c
write.o: write.c write.h
gcc -c write.c
gensine.o: encode.c gensine.h gensine.c helper.c write.c
gcc -c gensine.c -lm
helper.o: helper.c helper.h
gcc -c helper.c
read.o: read.h read.c
gcc -c read.c
info.o:read.c info.h info.c decode.c
gcc -c info.c
decode.o: decode.c decode.h helper.c
gcc -c decode.c
cs229towav.o: write.c read.c cs229towav.c cs229towav.h helper.c decode.c encode.c
gcc -c cs229towav.c -lm
gensine: encode.o gensine.o write.o helper.o
gcc -o gensine encode.o gensine.o write.o helper.o -lm
info: read.o info.o decode.o helper.o
gcc read.o info.o decode.o helper.o
cs229towav: write.o read.o cs229towav.o decode.o encode.o helper.o
gcc -o write.o read.o cs229towav.o decode.o encode.o helper.o -lm
Clean:
rm -rf *o gensine info cs229towav
When I run a command such as "make gensine" I am returned with the following result:
>cc gensine.c -o gensine
/tmp/ccojm09X.o: In function `encodeCsFormat':
gensine.c:(.text+0x4b1): undefined reference to `sin'
/tmp/ccojm09X.o: In function `encodeWavFormat':
gensine.c:(.text+0xa39): undefined reference to `sin'
collect2: error: ld returned 1 exit status
After reading this is says undefined reference to sin, which is with the math library. Those functions listed are in the "encode.c" file which are included in the "gensine.c" file.
The command in the makefile:
gcc -o gensine encode.o gensine.o write.o helper.o -lm
does not match the command you printed at the end:
cc gensine.c -o gensine
Notice also that there is no -lm
Note that make knows how to make object files so you don't need most of the makefile. Try this (remember to indent with TABs):
.PHONY : all clean
all = gensine info
CFLAGS =-Wall
LIBS = -lm
gensine: encode.o gensine.o write.o helper.o
gcc -o $# $^ $(LIBS)
info: read.o info.o decode.o helper.o
gcc -o $# $^ $(LIBS)
cs229towav: write.o read.o cs229towav.o decode.o encode.o helper.o
gcc -o $# $^ $(LIBS)
clean:
rm -rf *.o gensine info cs229towav
Edit:
Boddie, note that your confusion arose because you thought the makefile was a script - ie. that you were running your script named make when you typed make gensine. In fact make is a command like gcc somewhere else in the filesystem (on Linux etc, type which make to see where it is). The make command expects to find an input file containing build rules called makefile or Makefile in the current directory. If it doesn't find that file it uses some built-in rules instead - hence the cc gensine.c -o gensine which is nowhere in your makefile. If you want to, you can tell make the name of the makefile (so that it doesn't use the default names) with the -f switch, as #DanielFischer described in the comments.

Resources