Compile & link static library calling winapi under cygwin - c

I have a project in C which I am porting to from unix/linux to Windows/Cygwin (using autotools).
I need to call some winapi functions. These functions require inclusion of some windows headers. But when I specify those includes a lot of errors caused by redefinition of some structs or functions are raised.
So I decided to create a static library where all winapi function will be called to avoid these errors. But i have some difficulties getting it work.
For now the static library contains only one call of winapi function GetAdaptersAddresses and looks like this:
#include <windows.h>
#include <winsock2.h>
#include <iphlpapi.h>
void win_if_scan(void)
{
ULONG size = 10 * sizeof(IP_ADAPTER_ADDRESSES);
IP_ADAPTER_ADDRESSES *addresses = (IP_ADAPTER_ADDRESSES *)malloc(size);
GetAdaptersAddresses(AF_INET,
GAA_FLAG_INCLUDE_ALL_INTERFACES |
GAA_FLAG_INCLUDE_PREFIX |
GAA_FLAG_SKIP_DNS_SERVER,
NULL,
addresses,
&size);
}
and I am compiling the library libwin.a like this:
gcc libwin.c -liphlpapi -o libwin.o
ar crv libwin.a libwin.o
From the project I call the win_if_scan function (and I include header for the libwin). But I got error: undefined reference to WinMain, full message is:
$ make > /dev/null
/usr/lib/gcc/x86_64-pc-cygwin/4.9.2/../../../../lib/libcygwin.a(libcmain.o): In function `main':
/usr/src/debug/cygwin-1.7.33-1/winsup/cygwin/lib/libcmain.c:39: undefined reference to `WinMain'
/usr/src/debug/cygwin-1.7.33-1/winsup/cygwin/lib/libcmain.c:39:(.text.startup+0x7e): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `WinMain'
collect2: error: ld returned 1 exit status
make[1]: *** [libwin.o] Error 1
make: *** [all] Error 2
I don't understand what is happening here. It is a library, why it requires main function? When I tried to add:
int main(void) { return 0; }
or
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { return 0; }
it indeed says multiple definition of main as expected.
How to get this work?
Or is there a better way how to handle redefinition errors between cygwin & windows headers?

First step is to generate only object file from libwin as I mentioned in the comment.
Second, the specification of the library -liphlpapi must go where the project is linked together, not where the object file is generated. Which makes sense since no linkage is done there.
So the library archive is created by following commands:
gcc -c libwin.c -o libwin.o
ar crv libwin.a libwin.o
and the project is linked together like this:
$(exedir)/bin: $(bin-dep)
$(CC) $(LDFLAGS) -o $# $^ ../libwin/libwin.a $(LIBS) -liphlpapi
which is a Makefile rule, where you can see where I added the ../libwin/libwin.a and -liphlpapi
This is still a work in progress, so sorry for not very nice or systematic solution, but the idea is there.
Important thing to have on mind is also location of the -liphlpapi in the Makefile rule as mentioned a here

Related

Different behavior of undefined reference error on linux gcc during linking with object file vs static library

I have following two source codes and want to link them.
// test.c
#include <stdio.h>
void lib2();
void lib1(){
lib2();
return 0;
}
// main.c
#include <stdio.h>
int main() {
return 0;
}
I've used gcc -c main.c and gcc -c test.c to generate objects files
$ ls *.o
main.o test.o
and I've used ar rcs test.a test.o command to generate static library(test.a) from object file test.o
Then, I tried to build executable by linking main.o with test.a or test.o. As far as I know, a static library file(.a extension) is a kind of simple collection of object files(.o). so I expected both would give same result: error or success. but it didn't.
Linking with the object file gives undefined reference error.
$ gcc -o main main.o test.o
/usr/bin/ld: test.o: in function `lib1':
test.c:(.text+0xe): undefined reference to `lib2'
collect2: error: ld returned 1 exit status
$
but linking with the static library doesn't give any error and success on compilation.
$ gcc -o main main.o test.a
$
Why is this happening? and how can I get undefined reference errors even when linking with static libraries?
If your code contains a function call expression then the language standard requires a function definition exists. (See C11 6.9/3). If you don't provide a definition then it is undefined behaviour with no diagnostic required .
The rule was written this way so that implementation vendors aren't forced to perform analysis to determine if a function is ever called or not; for example in your library scenario the compiler isn't forced to dig around in the library if none of the rest of the code contains anything that references that library.
It's totally up to the implementation what to do, and in your case it decides to give an error in one case and not the other. To avoid this, you can provide definitions for all the functions you call.
You might be able to modify the behaviour in the first case by using linker options such as elimination of unused code sections. Another thing you can do is call lib1() from main() -- this is still not guaranteed to produce an error but is more likely to.
Force the linker to do some work use -flto option and the error will go away.
ld does not search libraries for objects which are not used it only searches for symbols used in object files. Imagine that you have a library where some functions require defined callbacks. If you do not have them in every program you link against the library even if you do not use those functions.
I expected both would give same result: error or success. but it didn't.
Your expectation is incorrect. A good explanation of the difference between .o and .a with respect to linking is here.

C compiler gcc gives linker command failed error [duplicate]

I'm getting the following error and can't for the life of me figure out what I'm doing wrong.
$ gcc main.c -o main
Undefined symbols:
"_wtf", referenced from:
_main in ccu2Qr2V.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
main.c:
#include <stdio.h>
#include "wtf.h"
main(){
wtf();
}
wtf.h:
void wtf();
wtf.c:
void wtf(){
printf("I never see the light of day.");
}
Now, if I include the entire function in the header file instead of just the signature, it complies fine so I know wtf.h is being included. Why doesn't the compiler see wtf.c? Or am I missing something?
Regards.
You need to link wtf with your main. Easiest way to compile it together - gcc will link 'em for you, like this:
gcc main.c wtf.c -o main
Longer way (separate compilation of wtf):
gcc -c wtf.c
gcc main.c wtf.o -o main
Even longer (separate compilation and linking)
gcc -c wtf.c
gcc -c main.c
gcc main.o wtf.o -o main
Instead of last gcc call you can run ld directly with the same effect.
You are missing the fact that merely including a header doesn't tell the compiler anything about where the actual implementation (the definitions) of the things declared in the header are.
They could be in a C file next to the one doing the include, they could come from a pre-compiled static link library, or a dynamic library loaded by the system linker when reading your executable, or they could come at run-time user programmer-controlled explicit dynamic loading (the dlopen() family of function in Linux, for instance).
C is not like Java, there is no implicit rule that just because a C file includes a certain header, the compiler should also do something to "magically" find the implementation of the things declared in the header. You need to tell it.

undefined reference to `printb'

In my header interface.h I have a function,
extern void printb(char *, unsigned short, char *);
Which is called in main.c as follows,
printb(" available", EXTRACT_16BITS(ptr), LLDP_CAP_BITS);
And I have included the the heder file in my main.c as follows.
#include "interface.h"
However, when I try to compile, I get the error stating the following,
undefined reference to 'printb' collect2: ld returned 1 exit status
I tried to do some research on this and came up empty handed. any help to solve this issue is greatly appreciated :)
Thank you :)
Firstly,You need to find out where the definition of function printb() is. If it is in some other static library ,then you need to link to that lib while compiling. For example, if your printb function is in printb library, then compile your source as below.
gcc -o prog main.c -l printb
If your printb function is in another standalone printb.c file, then compile your code as
gcc -o prog main.c printb.c
Either of these should work for you.

C Linking Error: undefined reference to 'main'

I have read the other answers on this topic, and unfortunately they have not helped me. I am attempting to link several c programs together, and I am getting an error in response:
$ gcc -o runexp.o scd.o data_proc.o -lm -fopenmp
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
make: * [runexp] Error 1
I have exactly one main function and it is in runexp. The form is
int main(void) {
...;
return 0;
}
Any thoughts on why I might get this error? Thanks!
You should provide output file name after -o option. In your case runexp.o is treated as output file name, not input object file and thus your main function is undefined.
You're not including the C file that contains main() when compiling, so the linker isn't seeing it.
You need to add it:
$ gcc -o runexp runexp.c scd.o data_proc.o -lm -fopenmp
You are overwriting your object file runexp.o by running this command :
gcc -o runexp.o scd.o data_proc.o -lm -fopenmp
In fact, the -o is for the output file.
You need to run :
gcc -o runexp.out runexp.o scd.o data_proc.o -lm -fopenmp
runexp.out will be you binary file.
Generally you compile most .c files in the following way:
gcc foo.c -o foo. It might vary depending on what #includes you used or if you have any external .h files. Generally, when you have a C file, it looks somewhat like the following:
#include <stdio.h>
/* any other includes, prototypes, struct delcarations... */
int main(){
*/ code */
}
When I get an 'undefined reference to main', it usually means that I have a .c file that does not have int main() in the file. If you first learned java, this is an understandable manner of confusion since in Java, your code usually looks like the following:
//any import statements you have
public class Foo{
int main(){}
}
I would advise looking to see if you have int main() at the top.

Undefined symbols error when using a header file

I'm getting the following error and can't for the life of me figure out what I'm doing wrong.
$ gcc main.c -o main
Undefined symbols:
"_wtf", referenced from:
_main in ccu2Qr2V.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
main.c:
#include <stdio.h>
#include "wtf.h"
main(){
wtf();
}
wtf.h:
void wtf();
wtf.c:
void wtf(){
printf("I never see the light of day.");
}
Now, if I include the entire function in the header file instead of just the signature, it complies fine so I know wtf.h is being included. Why doesn't the compiler see wtf.c? Or am I missing something?
Regards.
You need to link wtf with your main. Easiest way to compile it together - gcc will link 'em for you, like this:
gcc main.c wtf.c -o main
Longer way (separate compilation of wtf):
gcc -c wtf.c
gcc main.c wtf.o -o main
Even longer (separate compilation and linking)
gcc -c wtf.c
gcc -c main.c
gcc main.o wtf.o -o main
Instead of last gcc call you can run ld directly with the same effect.
You are missing the fact that merely including a header doesn't tell the compiler anything about where the actual implementation (the definitions) of the things declared in the header are.
They could be in a C file next to the one doing the include, they could come from a pre-compiled static link library, or a dynamic library loaded by the system linker when reading your executable, or they could come at run-time user programmer-controlled explicit dynamic loading (the dlopen() family of function in Linux, for instance).
C is not like Java, there is no implicit rule that just because a C file includes a certain header, the compiler should also do something to "magically" find the implementation of the things declared in the header. You need to tell it.

Resources