main.c: simple 'driver' program to call the 'sayHello()' function in the hello module. Note that since main.c does not call any standard I/O
library functions, it should not have #include stdio.h
hello.h: provides the prototype for the sayHello() function; don't forget
the include guard
hello.c: implements the sayHello() function. This is the only file that has
#include stdio.h
Here is my Makefile: (w/o the 'pack' part)
hello: hello.o main.o
gcc main.o hello.o -o hello
main.o: main.c hello.h
gcc -c main.c -o main.o
hello.o: hello.c hello.h
gcc -c hello.c -o hello.o
test: hello
./hello
clean:
rm -f *.o hello
My hello.c file is:
#include<stdio.h>
#include "main.c"
int main()
{
sayHello();
return 0;
}
My hello.h file is:
void sayHello(void);
My main.c file is:
#include "hello.h"
void sayHello(void)
{
puts("Hello,World!");
return;
}
I did a test with this and it displayed "Hello, World!". But when I ran it again just in case, there were errors. Any ideas what could have happened?
hello.c and hello.h are some kind of library. hello.h provides sayHello() function to the world and this function is implemented in hello.c. That means that hello.c must have following include:
#include "hello.h"
and
#include <stdio.h>
main.c should only have:
#include "hello.h"
I think "guard" should be a function prototype in hello.h:
void sayHello(void);
You seem to be asking several questions without realizing it.
Let's look at it one by one. Your assignment is to make a project, separate the program which calls a function and the implementation of the function into separate pieces of source code. That's why you have the restriction on #include and the specification of the include file. You're also asked to generate a Makefile to compile the various source code files into a single program and provide basic facilities like compressing source code into a zip file or removing the object files. The assignment is meant to acquaint you with modular and automated compilation and separation of functions into distinct pieces.
If you want to learn about programming the best thing you can do is invest some effort into looking at simple make files and compilation. I could give you the answer but won't until you've tried for a while. You'll learn more from failed attempts than peeking at the answers.
In short, you have to first create the source code, figure out how to separate the sayHello function and the main function into two different source files and export the function definition through the include file. The second problem you have is the design of the make file, which your assignment pretty much specifies, all you have to do is learn about the make file configuration language and re-write the human worded specification into the make format. You'll benefit from searching for "makefile tutorial" and reading the first handful of results. ... I'm assuming you want to learn all of this and not just get the answers for no work. Although make files can be tricky, the good news is that at this level they're pretty trivial.
PS Try looking here: http://mrbook.org/tutorials/make/
Related
I found many ways online to use the -M-type flags for GCC (or G++) to automatically generate dependencies in your Makefile. All approaches seem similar, I implemented this one.
All arguments I could find in favor are along the lines of: It helps you in that you don't have to manage dependencies manually.
I don't see why.
Consider the following files:
main.c
#include "foo.h"
int main() { foo(); return 0; }
foo.h
void foo();
foo.c
#include "foo.h"
void foo() { ... }
I would say that main.c depends on foo. However, when I run make main.o, foo is not built. The dependency file main.d contains (which explains why foo has not been built):
main.o: main.c foo.h
foo.h:
Now if I were to create an executable (e.g. app: ; $(CC) -o app main.c, with or without auto-dependency generation flags), I would still have to manually specify that it depends on foo.o.
So my question is: how does the auto-dependency generation save me any work if I still have to specify the dependency on foo.o?
No, main.c does not depend on foo. To be more exact main.c does not depend on anything but the text editor. It's the main.o that depends on main.c and foo.h as those files are required to compile main.o. Your final binary should depend on main.o and foo.o to be linked together, but it needs to be explicitly stated - neither make nor linker will find out what files you want to build together.
What this autodependency gives you is the notation that when foo.h changes, main.o will need to be recompiled (as this is included from main.c) even though main.c itself did not have any changes.
"I would say that main.c depends on foo."
Not quite; main.o depends on foo.h, and app depends on foo.o.
Automatic dependency generation can take care of that first dependency; the compiler finds #include "foo.h" in main.c and takes note of it.
The second dependency you must take care of. Neither the compiler nor Make can deduce it. (Bear in mind that not every header file has a corresponding source file with a matching name.)
I am trying to learn the make command but I am having a little trouble with the way headers are being used
I got prg1.c
#include <stdio.h>
main()
{
printf("Hello World\n");
print();
}
and the prg2.c
#include <stdio.h>
print()
{
printf("Hello World from prg2\n");
}
and here is the make file
objects = prg1.o prg2.o
exe : $(objects)
cc -o exe $(objects)
prg1.o : prg1.c
cc -c prg1.c
prg2.o : prg2.c
cc -c prg2.c
This works perfectly. But if I don't include stdio.h in both file and then I have to compile it using the make, how am I supposed to write the makefile?
If you don't include <stdio.h>, then you can do one of two things:
supply a correct declaration for printf yourself:
int printf(const char *fmt, ...);
There is almost never any reason to do such a thing.
If your compiler is GCC, use the -include compiler option to force the inclusion of "stdio.h":
prg1.o: prg1.c
gcc -c -include stdio.h prg1.c
This is completely hokey; don't do it.
Note that the make utility has nothing to do with ensuring that the correct header material is included in C translation units. make is a utility which runs shell commands in response to some files not existing or having modification stamps older than other files.
I have a simple C file, which compiles. I am now trying to add to it an outside header file located at
../../myotherdir/tbt/include
Here is my C file:
/* Hello World program */
#include<stdio.h>
#include "app.h"
main()
{
printf("Hello World");
}
Here is my makefile:
headerdir = ../../mytree2/tlk/include
hello: hello.c **app.h**
gcc -I$(headerdir) hello.c -o hello
How do I get make to search for the headerfiles in myotherdir/tbt/include and add them to my project?
I updated the makefile as suggested by Mureinik. Thanks it worked. Now I get a different error stating that I do not have a rule to make app.h.
I found my error I think. I should not have added app.h as a prerequisite. I highlighted it in bold above. After removing that line, I got other errors, but it seems my make file works. Thanks Mureinik.
gcc -o hello.o -I$(headerdir) hello.c
You don't need to specify VPATH like that.
you can just change headerdir to include more header files. Eg.
headerdir = ../../myotherdir/tbt/include ../path/to/next/header/dir ../etc/etc
You can use the -I argument to set the location of additional headers:
hello: hello.c app.h
gcc -I${headerdir} hello.c -o hello
I'm pulling my hair out because of this.
All I want to do is link a .o (C object file) with a Go package so the Go package can call the C functions.
There does not appear to be any documentation on CGO_OFILES parameter of cgo, which appears to be what I need after much Internet searching.
I've tried putting this at the top of the Go file:
/*
#cgo CGO_OFILES: doc-capi-tesseract.o
#include <stdlib.h>
#include "doc-capi-tesseract.h"
*/
import "C"
But that gives me the error invalid #cgo verb: #cgo CGO_OFILES: doc-capi-tesseract.o. Then I read somewhere that a makefile can be used, so I made this probably incorrect makefile:
include $(GOROOT)/src/Make.inc
TARG=tesseract
CGOFILES=tesseract.go
CGO_OFILES=doc-capi-tesseract.o
include $(GOROOT)/src/Make.pkg
%.o: %.cpp
$(HOST_CC) $(CGO_CFLAGS_$(GOARCH)) -g -O2 -fPIC -o $# -c $^
But I have no idea then what to do with that file. Nothing happens if I run make or make myfile or go build makefile. No idea how to use it.
Could someone please explain to me how to link a Go file to a C object file?
You could use SWIG because it gives you more versatility. I just learnt myself to use it with C++ (example) but the process is 99% similar with C. You can choose between static and dynamic linking, both approaches will work.
You can force CGO to link statically (example, see especially the mentioned github repo!) by defining correct flags.
Example to #2:
// #cgo CFLAGS: -Isrc/include
// Where doc-capi-tesseract.h is!
// #cgo LDFLAGS: doc-capi-tesseract.a
// #include "doc-capi-tesseract.h"
import "C"
Use .syso istead of .o extension.
go build now automatically links every .syso files found in derectory into your binary.
actually I was compiling with multiple files. Following are the files:
file main.c -->
#include <stdio.h>
void foo3(void)
{
printf("INSIDE foo3 function\n");
}
int main()
{
foo1();
foo2();
foo3();
}
file 1.c -->
#include <stdio.h>
void foo1(void)
{
printf("INSIDE foo1 function\n");
}
file 2.c-->
#include <stdio.h>
void foo2(void)
{
printf("INSIDE foo2 function\n");
}
Now I compiled using gcc as follows-->
gcc 1.c 2.c main.c -o main
following was the output -->
INSIDE foo1 function
INSIDE foo2 function
INSIDE foo3 function
My doubt is how could main() call foo1() and foo2() when they are not declared in main.c. But now if I change main.c as follows ( writing the definition of foo3() after main()) like this:
edited main.c -->
#include <stdio.h>
int main()
{
foo1();
foo2();
foo3();
}
void foo3(void)
{
printf("INSIDE foo3 function\n");
}
and then if I compile I get this error:
main.c:9:6: warning: conflicting types for ‘foo3’ [enabled by default]
void foo3(void)
^
main.c:6:2: note: previous implicit declaration of ‘foo3’ was here
foo3();
^
why was this error not shown earlier in case of foo1() and foo2() . Thankyou in advance.
My doubt is how could main() call foo1() and foo2() when they are not declared in main.c
Because the GCC compiler defaults to the old ANSI C (aka as C89) language, where undeclared functions are permitted and defaults to giving int result.
Try to invoke the compiler as e.g.
gcc -std=c99 -Wall -g -c main.c
or (if you want to compile all files at once)
gcc -std=c99 -Wall -g 1.c 2.c main.c -o main
You could ask for link time interprocedural optimizations with gcc -flto instead of gcc using a recent GCC, e.g. GCC 4.9 in september 2014.
This would want a C99 conforming source code where all functions should be declared.
The -Wall asks for (almost) all warnings. The -g option produces a debuggable object code (or executable for the last command compiling all files at once).
In your edited main.c when foo3 first occurrence (inside main) is encountered, the compiler guesses that it is a function returning int. When the compiler sees the definition of foo3 it rightly complains.
You could use the -Wstrict-prototypes warning option to gcc (but it is implied by -Wall which I always recommend using).
At link time, the type (and signature) of C functions does not matter. The linker just uses name to do its job (but C++ use name mangling). Of course, calling a function with the incorrect arguments or result is undefined behavior.
The good conventional practice is to have a common header file declaring all the used and public functions and types (and constants) and include that header file in your source files (this avoids to have to copy and paste these declarations several times). So you whould have a new header file myheader.h like
// file myheader.h
#ifndef MY_HEADER_INCLUDED
#define MY_HEADER_INCLUDED
void foo1(void);
void foo2(void);
void foo3(void);
#endif /*MY_HEADER_INCLUDED*/
and you would add #include "myheader.h" in all your source files (after the #include <stdio.h> directive there). Notice the include guard trick with MY_HEADER_INCLUDED.
In practice, header files usually contain comments explaining the API of your program.
Learn also about GNU make. It will ease the building of your multi-source code files programs (you just compile and build by running make). See this and that examples of Makefile. Understand that C preprocessing is the first phase of C compilation.