I have the following code:
main.c
#include "checksum.h"
void main()
{
char *Buf ="GPGGA204502.005106.9813N11402.2921W1090.91065.02M-16.27M";
checksum(Buf);
}
checksum.c
#include <stdio.h>
#include <string.h>
checksum(char *Buff)
{
int i;
unsigned char XOR;
unsigned long iLen = strlen(Buff);
printf("Calculating checksum...\n");
for (XOR = 0, i = 0; i < iLen; i++)
XOR ^= (unsigned char)Buff[i];
printf("%X \n",XOR);
}
checksum.h
#ifndef CHECKSUM_H_INCLUDED
#define CHECKSUM_H_INCLUDED
void checksum(char *Buff);
#endif
When compiling I get the following error:
/tmp/ccFQS7Ih.o: In function `main':
main.c:(.text+0x18): undefined reference to `checksum'
collect2: ld returned 1 exit status
I can't figure out what the problem is?
You are compiling only one file not both. More precisely, you are not linking the files together.
I don't know your compiler, but with gcc, it would be something like this:
gcc -c main.c <-- compile only
gcc -c checksum.c <-- compile only
gcc main.o checksum.o <-- link the two
Edit: To automate this process, take a look at the make program which reads Makefiles.
You could also try
gcc -o program.out main.c checksum.c which will compile and link both files together
I think: in checksum.c, you should include checksum.h.
Related
test.c
#include <stdio.h>
#include <stdlib.h>
#include "dslib.h"
//#include "stack.c"
int main()
{
stack myStack;
char buffer[1024];
stack_init(&myStack, 6);
int i;
for(i = 0; i < myStack.max; i++){
stack_push(&myStack, (i+1)*2);
}
printf("Hello\n");
return 0;
stack.c
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "dslib.h"
//#define stack_init main
void stack_init(stack *s, int capacity)
{
// struct stack_t *s = (struct stack_t*)malloc(sizeof(struct stack_t));
s->max = capacity;
s->count = -1;
s->data = (int*)malloc(capacity * sizeof(int));
//return s;
}
int stack_size(stack *s)
{
return s->count;
}
int stack_pop(stack *s)
{
if(s->count == 0){
return -1;
}
s->count--;
int pop = s->data[s->count];
s->data[s->count] = 0;
return pop;
}
void stack_push(stack *s, int e)
{
if(s->count != s->max){
s->data[s->count] = e;
s->count++;
}
}
void stack_deallocate(stack *s)
{
free(s->data);
}
dslib.h
#ifndef DSLIB_H
#define DSLIB_H
#include <stdio.h>
#include <stdlib.h>
typedef struct stack
{
int count; // the number of integer values currently stored in the stack
int *data; // this pointer will be initialized inside stack_init(). Also, the actual size of
//the allocated memory will be determined by “capacity’ value that is given as one of the
//parameters to stack_init()
int max; // the total number of integer values that can be stored in this stack
}stack;
void stack_init(stack* s, int capacity);
int stack_size(stack *s);
int stack_pop(stack *s);
void stack_push(stack *s, int e);
void stack_deallocate(stack *s);
#endif
Makefile
cc=gcc
file: test.o stack.o file.o
gcc -o file test.o stack.o file.o
file.o: file.c
gcc -o file.o file.c
test.o: test.c
gcc -o test.o test.c
stack.o: stack.c
gcc -o stack.o stack.c
When I execute make, it emits this:
gcc -o test.o test.c
/tmp/ccJMitGw.o: In function `main':
test.c:(.text+0x2a): undefined reference to `stack_init'
test.c:(.text+0x53): undefined reference to `stack_push'
collect2: error: ld returned 1 exit status
Makefile:10: recipe for target 'test.o' failed
make: *** [test.o] Error 1
gcc -o test.o test.c
This attempts to compile and link test.c into an executable with the unusual name of test.o. That obviously fails because test.c is not a complete program by itself.
To just compile and assemble a source file into an object file, you need to use the -c option:
gcc -c -o test.o test.c
And the same for the other compilation rules of your makefile.
There is a slight inconsistency in gcc's behavior here: it looks at the extension of the input files to help it decide what to do (.c files get compiled as C, .cpp files are compiled as C++, .s files are only assembled, etc) but it doesn't look at the extension of the output file. You have to use a separate option.
My answer is intended to follow on Nate's. Mine's a bit too complicated to put into a comment.
The default file production rules should work just fine for your Makefile unless on your platform the defaults are different. On mine, this is all I need to make the executable:
file: test.o stack.o
gcc -o file test.o stack.o
You didn't include file.c but the code you posted doesn't depend upon file.c.
It's highly recommended to use pre-defined rules whenever possible and to define new rules where they can be applied more than once. The only time you truly need specific rules is when multiple rules cannot be refactored to a smaller set of rules.
PS I'd never want to create an executable named for something that already exists.
Create a header file for the stack.c file and include it in your main file instead of stack.c
stack.h
#ifndef STACK_H
#define STACK_H
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "dslib.h"
void stack_init (stack * s, int capacity);
int stack_size (stack * s);
int stack_pop (stack * s);
void stack_push (stack * s, int e);
void stack_deallocate (stack * s);
#endif
stack.c
#include "stack.h"
/* code */
test.c
#include "stack.h"
/* code */
I'm writing my first makefile. I wanted to link 2 files together. test.c and main.c. test.c includes a test.h as well as a header file, conio.h.
So far I've tried adding the header file to the paths returned after the failing make command, as well as adding the path to the header file in the command itself. For reference I'm using git bash. To add the make command to git bash I needed to add it directly to the bin folder of gits mingw, but it is looking program files x86 / mingw, which also contains conio.h
Do I need to link it to some kind of library instead. Any help in the matter would be appreciated.
gcc main.o test.o -o test -lconio
C:/Program Files (x86)/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/bin/../lib/gcc/i686-w64-mingw32/8.1.0/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -lconio
collect2.exe: error: ld returned 1 exit status
make: *** [Makefile:7: main] Error 1
main.c
#include "test.h"
int main() {
char c = inputChar();
return 0;
}
test.c
#include "test.h"
#include <conio.h>
void printChar(char casd)
{
_putch(casd);
}
void printString(const char *c) {
for (const char* s = c; *s != 0; s++) {
printChar(*s);
}
printChar('\n');
}
char inputChar() {
char c = _getch();
printChar(c);
return c;
}
test.h
void printChar(char);
void printString(const char *c);
char inputChar();
When I compile the below program it is giving me this error.
/tmp/ccwr6gsJ.o: In function 'main':
main.cL(.text+0xa): undefined reference to 'example'
collect2: error: Id returned 1 exit status
Main.c:
#include <stdio.h>
#include "includes.h"
int main()
{
int exampleInt = example();
return 0;
}
includes.h:
int example();
includes.c:
#include "includes.h"
int example()
{
int i = 3;
return i;
}
It seems to work in Visual Studio but not on GCC on Linux
This is very likely a build error, i.e. you're calling the compiler on the wrong set(s) of files, and/or not doing a linking step.
Try:
$ gcc -o myprog main.c example.c
Note that a mere #include in a C file does not in any way tell the compiler to compile more C files.
The following code compiles on other systems, but not on my Ubuntu 12.04 64bit guest in Virtualbox 4.3.10 on a Windows 7 64bit host.
hello.c
#include "header.h"
int main(int argc, char *argv[]){
int i;
for(i=0; i<argc; i++)
printf("%s\n", argv[i]);
double x;
x = testfunction();
printf("%f \n", x);
return 0;
}
hello2.c
#include "header.h"
double testfunction ()
{
int i = 1;
double j = 0;
for(i=0; i<1000000; i++)
j += sin(i/M_PI);
return j;
}
header.h
#include <math.h>
#include <stdio.h>
double testfunction();
When I attempt to compile using
gcc -lm -o hello hello.c hello2.c
I receive the error
/tmp/ccirukEU.o: In function testfunction':
hello2.c:(.text+0x33): undefined reference tosin'
collect2: ld returned 1 exit status
The error remains even if I include math.h directly in hello2.c. Calculating sin(2/M_Pi) rather than sin(i/M_Pi) removes the error, possibly because gcc then works out the sine itself rather than using the math library.
Use -lm in the end, as in:
gcc -o hello hello.c hello2.c -lm
This ensures that the linker can realize that there are dependencies missing. Using -lm in the beginning is known to raise problems, because by the time the linker looks at the math library, it hasn't looked at your code yet, so there are no dependencies unresolved.
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