Trouble using makefile with multiple files in C - c

Starting to get my head around makefiles for my C programs, but having some trouble when trying to include multiple files. Ignoring the fact that the program below is incomplete (in terms of functionality but not compilation), I'm trying to get this program compiling and running using a make file.
Here is my make file:
main: main.o IntList.o
gcc -o main main.o IntList.o
main.o: main.c
gcc -c -ansi -pedantic -Wall main.c
IntList.o: IntList.c IntList.h
gcc -c -ansi -pedantic -Wall Intlist.c
And here is the error I am receiving:
gcc -c -ansi -pedantic -Wall Intlist.c
gcc -o main main.o IntList.o
ld: duplicate symbol _getNewInt in IntList.o and main.o
collect2: ld returned 1 exit status
make: *** [main] Error 1
The code for the program is below. I'm not sure whether it's the make file or my includes in the program files that are causing problems (or both!)
Any help would be great. Cheers.
Edit: Any tips to steer me in the right direction in terms of modularization would be much appreciated as I'm not sure if I am doing this the best way.
IntList.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Constants */
#define MAX_INTS 10
/* Signed ints can have a maximum of 10 digits. We make the length 11 to
* allow for the sign in negative numbers */
#define MAX_INPUT_LENGTH 11
#define EXTRA_SPACES 2
/* Typedefs / Structs */
typedef struct {
int list[MAX_INTS];
int noInts;
} IntList;
/* Proto Types */
int insertIntToList(int *list);
void shiftList(int offset);
void displayList();
IntList.c
#include "IntList.h"
int getNewInt(int *list)
{
int valid = 0, inputInt;
char inputString[MAX_INPUT_LENGTH + EXTRA_SPACES];
while(!valid)
{
printf("Input an int: ");
valid = 1;
if((fgets(inputString, MAX_INPUT_LENGTH + EXTRA_SPACES, stdin)) != NULL)
{
sscanf(inputString, "%d", &inputInt);
/* Check first that the input string is not too long */
if(inputString[strlen(inputString) - 1] != '\n')
{
printf("\nError: Too many characters entered \n");
valid = 0;
}
printf("\nThe Int: %d", inputInt);
printf("\n");
}
}
}
void shiftList(int offset)
{
}
void displayList()
{
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include "IntList.c"
int main(void)
{
int intList[10];
getNewInt(intList);
return EXIT_SUCCESS;
}

Don't include the .c file in main, include the .h file. Otherwise the code in IntList.c gets compiled both into the IntList.o and the main.o, so you'll get duplicate symbols.
Use this in main.c instead of IntList.c:
#include "IntList.h"

#include "IntList.c"
should be:
#include "IntList.h"
Also (though nothing to do with your problem) I would recommend not using mixed case in the names of source files, as it can lead to portability problems and hard to diagnose "no such file" errors - use all lower case, like the standard library headers do.

Don't #include "IntList.c" into main.c

You should not have:
#include "IntList.c"
in your main program, it should be:
#include "IntList.h"
By including the C file, you create a getNewInt in both your main and IntList object files, which is why you're getting the duplicate definition error when you try to link them together.

main.c should include "IntList.h", not "IntList.c".
If you include IntList.c, the functions in IntList.c will be implemented both in IntList.o and in main.o, which would produce the "duplicate symbol" error you're seeing.

As others have mentioned, you include .h files, not .c files
Also when you compile, you only compile .c files so you should remove any references to .h files in your Makefile

Related

Undefined Reference to (FUNCTIONNAME) in C [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 9 months ago.
I'm attempting to make a custom header in C for user input. Whenever I try to use it, it throws the error:
"Undefined Reference to (FUNCTION_NAME)"
It's in the same folder as all the other header files and vscode doesn't have a problem finding the header file. Both the .h and .c are in the same folder.
Here is the code in the header, c file, and program I'm using:
SGGINPUT.h
#ifndef SGGINPUT
#define SGGINPUT
#include <stdio.h>
char SGGchar();
#endif
SGGINPUT.c
#include <stdio.h>
#include "SGGINPUT.h"
char SGGchar() {
char c;
printf("Enter Char: ");
scanf("%c",&c);
printf("\n");
return c;
}
test.c
#include <stdio.h>
#include "SGGINPUT.h"
int main() {
char c = SGGchar();
printf("%c",c);
}
Try:
gcc -c SGGINPUT.h SGGINPUT.c
A result file will be an obj file:
SGGINPUT.o
Next compile it this way:
gcc -g SGGINPUT.o test.c -o "Output_name"
Plus you don't really need to include <stdio.h> in your header, you are just declaring your functions there and nothing more.
My solution was:
gcc -c test.c
gcc -c 'C:\msys64\mingw64\include\SGGINPUT.c'
gcc -o test test.o SGGINPUT.o
And then run the executable.
So this solution works if I were to make o files in the same directory as test.c, but I really want it to function like <stdio.h> or any other default header.

How to fix 'undefined reference' when compiling in C?

I'm trying to compile a C program linking two previously created object files but keep getting an 'undefined reference' error.
I'm using Visual Code to write the code and Ubuntu on Windows to compile using a makefile. The two C files, task5.c and reverse.c which have been made into object files both contain #include reverse.h statements which contains the prototypes for the functions in reverse.c.
task5.c
#include <stdio.h>
#include "ctap.h"
#include "reverse.h"
TESTS {
const char *a = "Family";
char *b = reverse(a);
//test 1
ok(string_length(a) == string_length(b), "Strings are the same size");
//test 2
is("ylimaF", b, "Strings match");
}
reverse.c
#include <stdio.h>
#include <stdlib.h>
#include "reverse.h"
char *reverse(const char *str) {
//code
}
int string_length(const char *str) {
//code
}
reverse.h
char *reverse(const char *str);
int string_length(const char *str);
makefile
linked:
gcc -o linked task5.o reverse.o
task5.o
gcc -c -o task5.o task5.c
reverse.o
gcc -c -o reverse.o reverse.c
When I run the command make linked I expect it to be made and return nothing.
But when I run that command I get this error:
cc task5.o -o linked
task5.o: In function `ctap_tests':
task5.c:(.text+0x1abe): undefined reference to `reverse'
task5.c:(.text+0x1ace): undefined reference to `string_length'
task5.c:(.text+0x1adc): undefined reference to `string_length'
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'linked' failed
make: *** [task5] Error 1
According to this GNU make documentation, the GNU make program will try to use GNUMakefile, makefile or Makefile.
The make program will not try makefile.mk, which means that e.g. make linked will use no makefile and only the default rules.
You can solve this by either renaming your makefile as Makefile (the most common) or makefile; Or by using the -f option to specify the makefile
$ make -f makefile.mk linked

Compiling header files in ubuntu. What do I type in terminal?

I'm pretty sure this is a simple question but I've searched online for about half an hour.
I have 3 files:
02_01.c
#include <stdio.h> // Notice the library included in the header of this file
#include <stdlib.h>
#include "myLibrary.h" // Notice that myLibrary.h uses different include syntax
#define MAX_LENGTH 21.8
#define WORK_WEEK 5
int main(void) {
function1();
return EXIT_SUCCESS;
}
myLibrary.c
void function1(void){
puts("It works :)");
}
void function2(void){
//This function does nothing as well
}
myLibrary.h
#ifndef MYLIBRARY_H_
#define MYLIBRARY_H_
void function1(void);
void function2(void);
#endif /* MYLIBRARY_H_ */
First, I navigate to my working directory.
Normally in a file with no local headers I would type:
gcc -o 02_01 02_01.c
./02_01
and it would work.
I've tried a variety of things like:
gcc -o 02_01 02_01.c myLibrary.c
which gives me an error "implicit declaration of function 'puts'
gcc -o myLibrary myLibrary.c which also gives the same error.
What should I be typing in the terminal in ubuntu?
So I'm assuming that the puts() function in myLibrary.c is not connected to 02_01.c which is where I include stdio.h.
You must include required headers in every file, where you using included functions. In your case, you must include #include <stdio.h> in beginning of your myLibrary.c file.
Also, you probably want to build .a library and link with it later.
So, finally:
Compile lib:
gcc -c -o mylib myLibrary.c
Make static lib:
ar rcs libMyLib.a mylib
Compile app and link together:
gcc -o 02_01 02_01.c -L. -lMyLib

gcc compile multiple files

I have these five source
main.c src_print1.c src_print2.c header_print1.h header_print2.h
the contents are simple and are as following for respective files:
main.c
#include "header_print1.h"
#include "header_print2.h"
int main(int argc, char** argv) {
print1();
print2();
return 0;
}
header_print1.h
#ifndef PRINT_1
#define PRINT_1
#include <stdio.h>
#include <stdlib.h>
void print1();
#endif
header_print2.h
#ifndef PRINT_2
#define PRINT_2
#include <stdio.h>
#include <stdlib.h>
void print2();
#endif
src_print1.c
#include "header_print1.h"
void print1() {
printf("Hello 1\n");
}
src_print2.c
#include "header_print2.h"
void print2() {
printf("Hello 2\n");
}
Using gcc I have tried to compile using the following command line:
gcc -I ./ -o test -c main.c src_print1.c src_print2.c
Everything is in the same folder.
The error I get is:
gcc: cannot specify -o with -c or -S with multiple files
I looked up at gcc manual, but actually I don't understand what to do in this case, since usually I use IDE and not the command line.
IMHO, if you rewrite your compilation statement like
gcc -I./ -o test main.c src_print1.c src_print2.c
You'll be good to go. There is no need for -c flag [NOTE] when you're specifying the output binary using -o.
Also, as mentioned here, all the files are in same directory, you can even shorten the statement as
gcc -o test main.c src_print1.c src_print2.c
Suggestion: While the above change(s) will do the job, this is not considered an elegant way of doing so. Please consider creating a makefile which will make your life easier.
[Note]:
Regarding the -c option, as per the online gcc manual, (emphasis mine)
-c
Compile or assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the form of an object file for each source file.
So, it should be clear by now, why you got the error.

C language prototype creation

I have this block of code. I have to move the given function display_name() into another .c file, compile it, and find the error that was caused due to the migration of the function and correct it by creating a header file with a prototype. How can I do it?
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char student[]="Rasmus Lerdorf";
void display_name()
{
printf("Student Name : %s",student);
}
int main()
{
display_name();
}
these are the changes i made but again i still get an error in the main.cpp. it doesnt allow me to include the displayname.h file.
displayname.h
void display_name(void);
displayname.cpp
#include <stdio.h>
#include "displayname.h"
char student[] = "Rasmus Lerdorf";
void display_name()
{
printf("Student Name : %s", student);
}
main.cpp
#include <stdio.h>
#include "displayname.h"
int main()
{
display_name();
}
errors are:
3 IntelliSense: identifier "display_name" is undefined c:\Users\konstantinos\Desktop\main\main.cpp 7 2 Cproject
2 IntelliSense: cannot open source file "displayname.h" c:\Users\konstantinos\Desktop\main\main.cpp 2 1 Cproject
Error 1 error C1083: Cannot open include file: 'displayname.h': No such file or directory c:\users\konstantinos\desktop\main\main.cpp 2 1 Cproject
Prototype functions work like this: for each set of functions that you write (except main) you need a definition and an implementation. Definitions are usually stored in header files (extension .h) whereas implementations are stored in source files (extension .c).
Here is an example of how you could arrange your code to solve your problem.
Definition: display.h
// This file contains the definitions of the functions which you want to call from another file
void display_name(void);
Implementation: display.c
#include "display.h"
#include <stdio.h>
static char student[]="Rasmus Lerdorf";
void display_name()
{ printf("Student Name : %s",student);
}
With both the definition defined and the desired implemented, now you can call the function from your main source file.
Implementation: main.c
#include "display.h"
#include <stdio.h>
int main()
{
display_name();
}
This is how you link together a prototype of a function and the implementation of a function. You can expand this by adding more prototypes to display.h, implementing those prototyped functions in display.c, and then calling them throughout your code.
To build, both of these .c files must be included in your build phase. If you build from the command line, you need to do something like this (I'm assuming that your compiler is gcc):
cc display.c main.c -o program
Hope this helps.
Your header file, let's call it displayname.h should contain the declaration:
void display_name(void);
It's usually also best to create an include guard, which avoids causing problems if a header is included more than once:
#ifndef DISPLAYNAME_H
#define DISPLAYNAME_H
void display_name(void);
#endif /* DISPLAYNAME_H */
Then, in your displayname.c, you would include that header plus any others needed by the function, and define your constant and the function:
#include <stdio.h>
#include "displayname.h"
char student[]="Rasmus Lerdorf";
void display_name()
{
printf("Student Name : %s",student);
}
And in your main.c, you would also include that header:
#include "displayname.h"
int main()
{
display_name();
return 0;
}
I don't know what compiler you are using, but if you're on a Unix-like system (Linux, Mac OS X, or something like msys or Cygwin under Windows), you would compile and link them as follows (you can replace cc with your specific compiler, such as gcc or clang, though on most systems cc should exist and point to the default compiler for that system):
cc -c -o displayname.o displayname.c
cc -c -o main.o main.c
cc -o myprogram main.o displayname.o
You could also abbreviate this as:
cc -o myprogram main.c displayname.c
I also recommend, when you are learning, to use the -Wall -Wextra -Werror flags, to give you as many warnings as possible, and not allow compilation to proceed if there are any warnings. To make this more convenient, so you don't have to type the whole command every time, you can define a simple Makefile; the following uses GNU make syntax, if you don't have GNU make let me know and I'll edit it to use a more portable syntax:
CFLAGS=-Wall -Wextra -Werror
myprogram: main.o displayname.o
cc -o $# $^
%.o: %.c
cc -c $(CFLAGS) -o $# $<
main.o: displayname.h
displayname.o: displayname.h
If you have this set up, you can just type make and it will recompile everything that it needs to.
edit: I see now from your comments that you are using Visual Studio, so the above tips on how to compile and link using cc and make are not relevant to you. It has been too long since I have used Visual Studio to walk you through that myself, but Microsoft has a reasonable walkthrough of how to create and build a project that you can follow. The tutorial is for C++, but it should work similarly for C, just keep in mind that files should be named .c if they are written in C, and only .cpp if they are written in C++.
i did what you said! i created the 3 specific files displayname.h for the prototype , displayname.cpp in which the function display_name() stays and main.cpp in which i call the function display_name(). the problem again is that when i include the file displayname.h in the displayname.cpp it works fine, but when i include it in the main.cpp i have an underline error in the include. what is wrong?

Resources