Golang: How to link C objects using CGO_OFILES? - go

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.

Related

How is automatic dependency generation with GCC and GNU Make useful?

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.)

MakeFile Example

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/

include stdio makefile

I'm trying to use the sprintf() function. Therefore I have to include the stdio.h in my C project. If I compile the project without including the stdio.h in my makefile, the compiler generates the error that sprintf() is a unknown function. Including the stdio.h to the makefile generates the error that there is "no rule to make target."
The makefile template gives the options as follows:
NAME = test
CC = arm-none-eabi-gcc
LD = arm-none-eabi-ld -v
AR = arm-none-eabi-ar
AS = arm-none-eabi-as
CP = arm-none-eabi-objcopy
OD = arm-none-eabi-objdump
CFLAGS = -I./ -c -fno-common -O0 -g -mcpu=cortex-m3 -mthumb
AFLAGS = -ahls -mapcs-32 -o crt.o
ASFLAGS = -Wa,-gstabs
LFLAGS = -Tlinkerscript_rom.cmd -nostartfiles
CPFLAGS = -Obinary
ODFLAGS = -S
I hope that you can help me out, because I have no desire to rewrite every standard function.
Sven
Makefiles don't read include files. The C preprocessor reads include files, before the resulting file is compiled by the compiler. You should include the header in your C file. Just add:
#include <stdio.h>
Somewhere close to the top, before any function definitions etc.
This will show a declaration of the function to the compiler, which will remove the warning.
Just include stdio.h at the top of your c file
#include <stdio.h>
The only reason to put a .h file in your makefile is so that the files dependent upon your header will be recompiled if anything in the header is changed. Needless to say, this is most commonly with header files you have written.
If there is an error after including stdio.h, you have a broken tool chain. If you update your question to indicate your platform, we may be able to help you fix it :)

compiler directive for compiling on different platforms

I am compiling a demo project.
The project is written for windows and linux. I have written a Makefile. However, I am not sure how to specify the platform the compiler will be compiling on.
I will be compiling on Linux.
In my source file I have this:
#if defined(WIN32)
#include ...
#include ...
#elif defined(LINUX)
#include ...
#include ..
#else
#error "OS not supported"
#endif
My simple Makefile is this. And when I compile I get the error "OS not supported".
How can I add the directive so that it will compile with the #elif defined(LINUX).
LIBS_PATH = -L/usr/norton/lib
INC_PATH = -I/usr/norton/include
LIBS = -lntr
app: *.cpp *.h Makefile
g++ $(LIBS_PATH) $(INC_PATH) *.cpp -o app
Many thanks for any suggestions,
Decide which is going to be your default platform - say LINUX.
LIBS_PATH = -L/usr/norton/lib
INC_PATH = -I/usr/norton/include
LIBS = -lntr
PLATFORM = -DLINUX
CXX = g++
app: *.cpp *.h Makefile
${CXX} ${CFLAGS} ${PLATFORM} ${INC_PATH} *.cpp -o $# ${LIBS_PATH} ${LIBS}
You can use round brackets in place of braces. This uses a macro for the C++ compiler, allows you to add other flags via CFLAGS (though that is also usually set by 'make'), and adds a platform, the include path, the library path and the actual library to the compile line.
Note that your rule enforces a complete recompilation of everything every time anything changes. This is 'safe' but not necessarily efficient. Note that wild-cards are dangerous too - more so for the source than the headers. You may include that backup copy of a file in the build (old-reader.cpp - you only wanted reader.cpp in there really). More conventionally, you list the object files needed for the program so that each object file can be individually rebuilt when needed, and the results linked together. If you get your dependencies correct (a moderately big 'if'), then there's no problem. If you get them wrong, you can end up with inconsistent programs.
However, if the difference is between a 5 second recompile and a 5 minute recompile, you should probably take the 5 minute recompilation (as shown) and answer another SO question while waiting.
To compile on Linux (64-bit):
make CFLAGS="-m64"
To compile on Linux (32-bit):
make CFLAGS="-m32"
To compile on Windows 64:
make PLATFORM=-DWIN64
To compile on Windows 32:
make PLATFORM=-DWIN32
Etc.
You can add -DLINUX=1 when compiling.
Also, if you run:
echo "" | cpp -dD
You can see the list of default #define when compiling. In linux, there will always be a:
#define __linux__ 1
in the output. So if you change your LINUX by the above #define, you don't need to do anything special. Ie:
...
#elif defined(__linux__)
...
As for the Makefile itself, I would do something like:
CXX=g++
CPPFLAGS = -I/usr/norton/include
LDFLAGS = -L/usr/norton/lib -lntr
OBJ_FILES = one.o two.o
app: $(OBJ_FILES) Makefile
one.o: one.cpp one.h
two.o: two.cpp two.h
So the implicit rules are used.

Meaning of -DHAVE_CONFIG_H in makefiles

I am starting to learn about makefiles. Looking at the output I see a lot of occurrences of:
g++ -DHAVE_CONFIG_H -I ...
what is -DHAVE_CONFIG_H exactly? What is the function of this compilation option?
All that -DHAVE_CONFIG_H does is to define the pre-processor token HAVE_CONFIG_H exactly as if you had #define HAVE_CONFIG_H right at the start of each of your source files.
As to what it's used for, that depends entirely upon the rest of your source file (and everything that it includes as well). That's where you should be looking for to work out its effect.
It looks like it may mean that a header file config.h is available and should be included, in which case you'll probably find the following sequence somewhere in you source files:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
which will include the header file when you say it's available. However that's supposition on my part and by no means the exact effect, just what I would use such a preprocessor symbol for.

Resources