Static library cannot be found - c

Let me explain the context first. I have a header with a function declaration, a .c program with the body of the function, and the main program.
foo.h
#ifndef _FOO_H_
#define _FOO_H_
void foo();
#endif
foo.c
#include<stdio.h>
#include "include/foo.h"
void foo()
{
printf("Hello\n");
}
mainer.c
#include <stdio.h>
#include "include/foo.h"
int main()
{ foo();
return 0;
}
For the purpose of this program, both the header and the static library need to be in separate folders, so the header is on /include/foo.h and the static library generated will be on /lib/libfoo.a, and both .c programs on the main directory. The idea is to generate the object program, then the static library, then linking the static library to create the executable, and finally executing the program.
I have no problem in both creating the object program and the static library.
$ gcc -c foo.c -o foo.o
$ ar rcs lib/libfoo.a foo.o
But when I try to link the static library...
$ gcc -static mainer.c -L. -lfoo -o mainfoo
It gaves to me an error, claiming the static library can't be found
/usr/bin/ld: cannot find -lfoo
collect2: ld returned 1 exit status
It's strange, considering I asked before how to work with static libraries and headers on separate folders and in this case the static libraries were found. Any idea what I'm doing wrong?

Change -L. to -Llib as it looks like you create the .a file there.

Basically the linker is telling you that it cannot find the library foo. It normally searches in the default library directories + any you give it with the -L option. You're telling it to look in the current directory, but not in lib where libfoo.a is located, which is why it can't find it. You need to change -L. to -Llib.

I am not completely sure that I understand your directory structure, but maybe what you need is this:
gcc -static mainer.c -L./lib -lfoo -o mainfoo

Related

Creating shared library for dependent C programs for using in JNA

I am new to JNA and C, So I am facing trouble creating shared library for dependent C programs.
I already have tried with only 1 C program.
Basically my codes is like this:
file1.c
#include <stdio.h>
#include header.h
void function1(unsigned char *parm){
// --relevant code
function 2(parm)
}
header.h
#ifndef header_H
#define header_H
unsigned char name;
void function2(unsigned char*);
#endif
file2.c
#include header.h
void function2(unsigned char*) {
// relevant codes
printf (" hello");
}
I am using windows terminal for compiling and creating the shared library.
I have to use function1 () in java program through JNA/JNI.
Also as it is a project requirement, I cannot change the C files or headers.
During compilation I am able to create (.o files) for each of the prog.
gcc -c -Wall file1.c file2.c
-> When making shared library for prog1
gcc -shared -o newlib.dll file1.o
It is throwing error of undefined reference of prog2.
.c:(.text+0x16a): undefined reference to `function2()
-> When creating share library like this
gcc -shared -o newlib.dll file1.o file2.o
Its throwing error like
multiple definition of char name;
-> I don't know how to create shared library including both programs.
Can someone share some resources to look upon.
For the error multiple definition of char name
It's because both file1.c and file2.c are include header.h, so unsigned char name is defined twice.
The header file should looks like this:
#ifndef HEADER_H
#define HEADER_H
// your code
#endif // HEADER_H
I solved the above by creating shared library for file2, then creating object file of file1 by linking the created shared library. Then we can easily create share lib for file1 also using its object file.
Codes will be like
gcc -c -Wall -fPIC file2.c
gcc -shared -o libfoo.so file2.o
gcc -c -nostartfiles -Wl,--entry=function1 -L. -Wall file1.c -lfoo
gcc -shared -L. -o newLib.so file1.o -lfoo
As I don't have main function I have to use -nostartfiles flag and explicitly defining entry point.

Linker doesn't notify multiple definitions

I have two files foo.c and foo2.c which are exactly the same. If I link to both of them then the linker will throw an error complaining about multiple function definitions.
But if I first compile one file into static library and link to the other object file and the library, then the linking process completes normally. I am using gcc 5.4.0 on Ubuntu 16.04.
foo.c and foo2.c:
#include <stdio.h>
void fooxyz(void) {
printf("foo\n");
}
main.c:
#include <stdio.h>
void fooxyz(void);
int main(void) {
fooxyz();
return 1;
}
Now compile and archive foo2 into libfoo2.a:
$ gcc -c main.c foo.c foo2.c
$ ar rcs libfoo2.a foo2.o
$ gcc -o main main.o foo.o -L. -lfoo2
$ ./main
foo
Why doesn't the linker throw an error about the multiple definition of function fooxyz since it is defined in two places? Thanks.
But if I first compile one file into static library and link to the other object file and the library, then the linking process completes normally. I am using gcc 5.4.0 on Ubuntu 16.04.
That's expected.
A symbol from the library is used only if it is not defined in any of the object files being linked.

Why I got "clang: error: cannot specify -o when generating multiple output files"?

I am a newbie in C. I have two simple source code files f1.c and f2.c.
f1.c looks like:
#include <stdio.h>
#include "f.h"
void f1(void) {
// some code ...
}
function f2() in f2.c relies on f1() in f1.c.
#include <stdio.h>
#include "f.h"
void f2(void) {
f1();
}
f1.c and f2.c share a same header f.h,
void f1(void);
void f2(void);
There are no main() access, I just want to compile these two file into a .o file without linker (using -c option),
gcc -c f1.c f2.c -o f2.o
then I got,
clang: error: cannot specify -o when generating multiple output files
but when I mentioned only f2.c, it works well,
gcc -c f2.c -o f2.o
So what's the problem? Thanks!
You should look into the compilation process for C. The first stage is compiling the .c source code into .o object files. The .c files do not need to see the other .c files; they are accepting as fact what you've told them about the existence of external functions. It's not until the linker comes in that it really needs to see the function because the implementation details don't matter to your .c file, just the interface, which you've presumably given it in the header.
What you can do, if you like, is drop the -o flag specifying the output file you want to create. Just compile with
gcc -c f1.c f2.c
and it will know to create f1.o and f2.o which will be able to link against each other when the time comes that you do want to go through with the linking process.
I am curious, however, what your intentions may be for wanting to compile these without linking. I only ask as you refer to yourself as a newbie, so I am wondering if maybe there is an end goal you have in mind and perhaps aren't asking the right question.

C symbol visibility in static archives

I have files foo.c bar.c and baz.c, plus wrapper code myfn.c defining a function myfn() that uses code and data from those other files.
I would like to create something like an object file or archive, myfn.o or libmyfn.a, so that myfn() can be made available to other projects without also exporting a load of symbols from {foo,bar,baz}.o as well.
What's the right way to do that in Linux/gcc? Thanks.
Update: I've found one way of doing it. I should've emphasised originally that this was about static archives, not DSOs. Anyway, the recipe:
#define PUBLIC __attribute__ ((visibility("default"))) then mark myfn() as PUBLIC in myfn.c. Don't mark anything else PUBLIC.
Compile objects with gcc -c foo.c bar.c baz.c myfn.c -fvisibility=hidden, which marks everything as hidden except for myfn().
Create a convenience archive using ld's partial-linking switch: ld -r foo.o bar.o baz.o myfn.o -o libmyfn.a
Localise everything that wasn't PUBLIC like so: objcopy --localize-hidden libmyfn.a
Now nm says myfn is the only global symbol in libmyfn.a and subsequent linking into other programs works just fine: gcc -o main main.c -L. -lmyfn (here, the program calls myfn(); if it tried to call foo() then compilation would fail).
If I use ar instead of ld -r in step 3 then compilation fails in step 5: I guess ar hasn't linked foo etc to myfn, and no longer can once those functions are localised, whereas ld -r resolves the link before it gets localised-away.
I'd welcome any response that confirms this is the "right" way, or describes a slicker way of achieving the same.
Unfortunately, C linkage for globals is all-or-nothing, in the sense that the globals of all modules would be available in libmyfn.a's final list of external symbols.
gcc tool chain offers an extension that lets you hide symbols from outside users, while making them available to other translation units in your library:
foo.h:
void foo();
foo.c:
void foo() __attribute__ ((visibility ("hidden")));
myfn.h:
void myfn();
myfn.c:
#include <stdio.h>
#include "foo.h"
void myfn() {
printf("calling foo...\n");
foo();
printf("calling foo again...\n");
foo();
}
For portability, you would probably benefit from making a macro for __attribute__ ((visibility ("hidden"))), and placing it in a conditional compilation block conditioned on gcc.
In addition, Linux offers a utility called strip, which lets you remove some of the symbols from compiled object files. Options -N and -K let you identify individual symbols that you want to keep or remove.
Start with this to build a static library
gcc -c -O2 foo.c bar.c baz.c myfn.c
ar av libmyfunctions.a foo.o bar.o baz.o myfn.o
Compile and link with other programs like:
gcc -O2 program.c -lmyfunctions -o myprogram
Now your libmyfunctions.a will ultimately have extra stuff from the source that isn't required by the code in myfn.c But the linker should do a reasonable job of removing this when it creates the final program.
Suppose myfn.c has function myfun() which you want to use in other three files foo.c, bar.c & baz.c
Now create a shared library from code in myfn.c viz libmyf.a
Use this function call myfun() in other three files. Declare function as extern in these files. Now you can create object code of these thee files and link the libmyf.a at linking phase.
Refer to following link for using shared libraries.
http://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html

Creating libraries in C/C++ - ld can't find my library

I'm trying to learn how to create a C/C++ library in a linux environment but I'm having a problem (probably a trivial one) that online tutorials had not helped to solve.
For definiteness let's say I have a foo.c file with the following code:
//file: foo.c
#include <stdio.h>
void hello(void)
{
printf("hello!\n");
}
a foo.h:
//file: foo.h
void hello(void);
and a program that uses the function hello() from foo.c, named prog.c:
//file: prog.c
#include "foo.h"
int main(void)
{
hello();
return 0;
}
The three files are all on the same directory. Then I compiled foo.c with:
gcc -fPIC -c foo.c
and got a foo.o file. Then I used ld to create the library file:
ld -G foo.o -o libfoo.so
But when I try to compile prog.c with:
gcc -o prog prog.c -lfoo
I got an error message:
/usr/bin/ld: cannot find -lfoo
collect2: ld returned 1 exit status
I'm convinced that this is some kind of trivial path problem, but I couldn't find the solution. So my question is really if this procedure above is wrong or if I have to put the libfoo.so file in a special path.
Another question is how this changes if I'm using g++ instead of gcc.
Thanks.
EDIT:
I know I can compile both prog.c and foo.c to prog.o and foo.o an then link them to make an executable. But in my original problem I want to compile foo.c in a way that I can distribute to people who will use my functions in their own programs.
ld doesn't search the current directory by default. If you want it to do this you need to use the -L command line option, so if your library is in the current directory you need to add -L. to the last gcc call. If the library is dynamically linked you also need to add the current directory to the environment variable LD_LIBRARY_PATH (I assume you're on linux).
Of course, if your library is in any other non-standard path you need to use that instead of the current directory.
Try
gcc -o prog prog.c -lfoo -L.
The -L switch adds its argument to the set of paths that ld looks in for library files. The syntax is identical for g++.

Resources