I have simple C code that uses some functions of libavcodec in FFmpeg. I try to compile the code with GCC (on Windows using MinGW) as follows:
gcc -o mycode mycode.c
But I get a lot of errors like "undefined reference to av_free". I know that these functions are defined in the libraries of FFmpeg. I do access files like avcodec.lib and libavcodec.dll.a, but I don't know how to use them with GCC so that I can compile and make my file. How can I solve this problem?
Try something like:
gcc -o mycode mycode.c -L C:\path\to\avcodec -lavcodec
I don't have Windows, so I cannot test it myself.
The point is that you need to tell gcc that some functions are in avcodec.lib / .dll. After the -L you tell where the .a / .dll is, then you must tell the linker to actually consider the avcodec.lib / .dll, that corresponds to -lavcodec.
Related
I want to create a static library libmylib.a from mylib.c/.h and link it to a project to use this library in bootloader code using the arm-none-eabi-gcc cross compiler in ubuntu 20.04 LTS.
I have an electronic engineering background, so I'm kind of new in this compiler and linker stuff.
What I know:
I've been searching about this, and found out that '.a' are just packed '.o' files, and that's it. You can do it using ar in linux. I don't know how to manage the dependencies for this '.a' file, for example, or how to link it to the project.
What I want to know:
I really want to understand how it works, to compile and generate the bin, elf or hex files using these static libraries for arm using the arm-none-eabi-gcc cross compiler (found some for linux), but I don't know how to search for this properly, how to learn it in a linear way. If you guys could help me on this I would be really grateful.
First you create your library objects. Let us say that you have a foo function written in foo.c, then you do:
arm-none-eabi-gcc -c foo.c
The -c options tells the compiler to stop after assembling and no go further.
Then you need to create the .a file
arm-none-eabi-ar -rc libfoo.a foo.o
this command creates a static library called libfoo.a
At the end you compile your main with:
arm-none-eabi-gcc -L. -lfoo main.c -o main
Note that in -l flag we don put "lib" and ".a", those are automagically added. The -L. flag tells gcc to look into the current folder for library files.
I am trying to compile a program which uses GSL, in fact I am already able to compile it successfully on my local machine using
g++ -o program program.c prog0.o -L/usr/local/lib -lgsl -lgslcblas -lm
My problem is that I need to compile this program on a work machine in a shared system, but I know the program will not compile with an up to date version of GSL, so I need to install and use an older version.
I did this on my own system using the default installation, so the relevant files are located in /usr/local/lib on my local machine, and the compilation works for me with the above command.
But since the work machine is in a shared system, I cannot mess with the default directories, so I installed the correct GSL version on the work machine in my directory under /home/myname/gsl/.
So on the work machine the folder /home/myname/gsl/lib contains the same relevant files as the folder /usr/local/lib on my machine.
Now I did various attempts to try and tell g++ to use this custom installation folder, which I thought would come down to
g++ -o program program.c prog0.o -L/home/myname/gsl/lib -lgsl -lgslcblas -lm
but no success. No matter what I did g++ always used the GSL version installed on the shared system, even using just
g++ -o program program.c prog0.o
I only started programming C/C++ not long ago and only know the very basics of how to compile programs, so this linking thing is still always confusing me..
But as far as I can tell -L/dir/ should tell g++ to use the library in /dir/ and -lgsl -lgslcblas are the files which it should look for in that library... ?
But it seems g++ doesn't care what library I tell it here, it always seems to use whatever is in the PATH of the shared work system, which seems to include this up-to-date version of GSL that I cannot use. But I also cannot change the PATH since I only have access to my own subdirectories on the work system..
So how do I tell g++ to ignore the default version of GSL and use the one I installed manually at /home/myname/gsl/ ?
I figured out the answer, it is actually simple. The problem was just my lack of understanding proper usage of outside libraries and trying to fix the compilation command was the wrong approach.
In the code in program.c, gsl was included with
#include <gsl/gsl_blas.h>
and so on. Of course, the "<>" directly tell the compiler to look in known include directories, where the up-to-date GSL is installed on the shared system.. So the way to use a custom version was just to instead use
#include "/home/myname/gsl/lib/gsl_blas.h"
and so on, directly specifying that I want to use my custom installation.
I then compiled with
g++ -o program program.c prog0.o /home/myname/gsl/lib/libgsl.so /home/myname/gsl/lib/libgslcblas.so -lm
and it compiles successfully.
(This brought up some other unclarities for me, but at least this specific problem is solved.)
I have downloaded and installed the ffmpeg library. I want to use it for reading the separate frames of different videos and manipulate them. For that I tried to follow some tutorial from here: http://dranger.com/ffmpeg/tutorial01.html
But I can't compile my cpp file since I get the following compilation:
Undefined symbols for architecture x86_64:
"av_register_all()", referenced from:
_main in cc9zyUBe.o
_main in ccRz35d4.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
When I was installing ffmpeg library, I used arch=x86_64 option in ./configure step.
I use OS X Mountain Lion 10.8.2 and gcc 4.2 compiler.
Does somebody have any clue what can be the reason of this error?
Thanks in advance.
UPDATE:
I've already tried many different install options, with static libraries, shared libraries, with/without --arch=x86_64 option. Also installed it with homebrew, result remains the same. Library isn't recognized. But ffmpeg binary works pretty well, when I use it as a command-line tool.
Finally I have managed to compile my program which uses ffmpeg library.
For some reason I still couldn't compile it using gcc compiler, but I could do it with g++ compiler.
When the static libraries are installed, all the dependencies must be specified explicitly, and the order of linking of these libraries is also important. So here is the compilation code which finally compiled my program:
g++ readVideo.cc -o readVideo $(pkg-config --libs --cflags libavformat)
pkg-config here is a utility which prints all the flags and libraries that are needed to properly link the specified libavformat library.
Also it's worth of mentioning, that the source file was renamed from readVideo.C to readVideo.cc, and that #include statements have been encompassed using extern "C" as follows:
extern "C" {
#include <libavformat/avformat.h>
}
It is needed because ffmpeg is a C project and program will not compile with C++ compiler if you don't explicitly state that it is C library.
And if you don't want to bother with pkg-config to include all dependencies for ffmpeg libraries, you can install ffmpeg with shared libraries instead of static ones. Then it will compile by simpler call:
g++ readVideo.cc -o readVideo -lavformat
To install shared libraries, you need to add these 2 options to ./configure program when installing ffmpeg:
--disable-static --enable-shared
Hope it helps somebody some time ...
The error means that you aren't linking to the ffmpeg libraries. Simply including the header files is not enough. You need to also link to the actual library files. On Windows they have .lib extension, on Linux usually .a extension, not sure about Mac.
I am trying to link a C++ module using GCC, essentially like this:
gcc -c hello.c
g++ -c world.cpp
gcc -ohello -lstdc++ hello.o world.o
Note that I use -lstdc++ to link the C++ module in, so that I can use gcc instead of g++. The problem is that I'm getting the error:
undefined reference to `operator new(unsigned long)'
(Assuming that world.cpp contains at least one call to new.)
This error is fixed if I put -lstdc++ at the end of the linker line, like this:
gcc -ohello hello.o world.o -lstdc++
I am aware that this question has been asked many times here, but I have a special requirement. I am not directly calling GCC. I am using a build system for a different programming language (Mercury) which is calling GCC on my behalf, and I can't easily modify the way it calls GCC (though I can specify additional libraries using the LDFLAGS environment variable). So I have two additional requirements:
I cannot use g++ to link (only gcc) -- that is why I am doing the -lstdc++ trick above rather than simply linking with g++).
I don't think that I can control the order of the linker commands -- Mercury will put the .o files on the command-line after any libraries.
I understand the basic reason why the order is important, but what is baffling me is why did this break now? I just updated to Ubuntu 11.10 / GCC 4.6.1. I have been successfully compiling this program for years using precisely the above technique (putting -lstdc++ first). Only now has this error come up. An unrelated program of mine links against OpenGL using -lgl and that too broke when I upgraded and I had to move -lgl to the end of the command-line. I'm probably going to discover that dozens of my programs no longer compile. Why did this change? Is there something wrong with my new system or is that the way it is now? Note that these are ordinary shared libraries, not statically linked.
Is there anything I can do to make GCC go back to the old way, where the order of libraries doesn't matter? Is there any other way I can convince GCC to link libstdc++ properly without moving it after the .o files on the command-line?
If Mercury puts object files after libraries, Mercury is broken. Libraries belong after object files - always. You may sometimes get away with the reverse order, but not reliably. (Static libraries must go after the object files that reference symbols in the static library. Sometimes, a linker will note the symbols defined by a shared library even when none of the symbols are used; sometimes, the linker will only note the shared library symbols if the shared library provides at least one symbol.)
I'm having a problem with my compiler telling me there is an 'undefined reference to' a function I want to use in a library. Let me share some info on the problem:
I'm cross compiling with gcc for C.
I am calling a library function which is accessed through an included header which includes another header, which contains the prototype.
I have included the headers directory using -I and i'm sure it's being found.
I'm first creating the .o files then linking them in a separate command.
So my thought is it might be the order in which I include the library files, but i'm not sure what is the correct way to order them. I tried with including the headers folder both before and after the .o file.
Some suggests would be great, and maybe and explanation of how the linker does its thing.
Thanks!
Response to answers
there is no .a library file, just .h and .c in the library, so -l isn't appropriate
my understanding of a library file is that it is just a collection of header and source files, but maybe it's a collection of .o files created from the source?!
there is no library object file being created, maybe there should be?? Yes seems I don't understand the difference between includes and libraries...i'll work on that :-)
Thanks for all the responses! I learned a lot about libraries. I'd like to put all the responses as the accepted answer :-)
Headers provide function declarations and function definitions. To allow the linker find the function's implementation (and get rid of the undefined reference) you need to ask the compiler driver (gcc) to link the specific library where the function resides using the -l flag. For instance, -lm will link the math library. A function's manual page typically specifies what library, if any, must be specified to find the function.
If the linker can't find a specified library you can add a library search path using the -L switch (for example, -L/usr/local/lib). You can also permanently affect the library path through the LIBRARY_PATH environment variable.
Here are some additional details to help you debug your problem. By convention the names of library files are prefixed with lib and (in their static form) have a .a extension. Thus, the statically linked version of the system's default math library (the one you link with -lm) typically resides in /usr/lib/libm.a. To see what symbols a given library defines you can run nm --defined-only on the library file. On my system, running the command on libm.a gives me output like the following.
e_atan2.o:
00000000 T atan2
e_asinf.o:
00000000 T asinf
e_asin.o:
00000000 T asin
To see the library path that your compiler uses and which libraries it loads by default you can invoke gcc with the -v option. Again on my system this gives the following output.
GNU assembler version 2.15 [FreeBSD] 2004-05-23 (i386-obrien-freebsd)
using BFD version 2.15 [FreeBSD] 2004-05-23
/usr/bin/ld -V -dynamic-linker /libexec/ld-elf.so.1 /usr/lib/crt1.o
/usr/lib/crti.o /usr/lib/crtbegin.o -L/usr/lib /var/tmp//ccIxJczl.o -lgcc -lc
-lgcc /usr/lib/crtend.o /usr/lib/crtn.o
It sounds like you are not compiling the .c file in the library to produce a .o file. The linker would look for the prototype's implementation in the .o file produced by compiling the library
Does your build process compile the library .c file?
Why do you call it a "library" if it's actually just source code?
I fear you mixed the library and header concepts.
Let's say you have a library libmylib.a that contains the function myfunc() and a corresponding header mylib.h that defines its prototype. In your source file myapp.c you include the header, either directly or including another header that includes it. For example:
/* myapp.h
** Here I will include and define my stuff
*/
...
#include "mylib.h"
...
your source file looks like:
/* myapp.c
** Here is my real code
*/
...
#include "myapp.h"
...
/* Here I can use the function */
myfunc(3,"XYZ");
Now you can compile it to obtain myapp.o:
gcc -c -I../mylib/includes myapp.c
Note that the -I just tells gcc where the headers files are, they have nothing to do with the library itself!
Now you can link your application with the real library:
gcc -o myapp -L../mylib/libs myapp.o -lmylib
Note that the -L switch tells gcc where the library is, and the -l tells it to link your code to the library.
If you don't do this last step, you may encounter the problem you described.
There might be other more complex cases but from your question, I hope this would be enough to solve your problem.
Post your makefile, and the library function you are trying to call. Even simple gcc makefiles usually have a line like this:
LIBFLAGS =-lc -lpthread -lrt -lstdc++ -lShared -L../shared
In this case, it means link the standard C library, among others
I guess you have to add the path where the linker can find the libraray. In gcc/ld you can do this with -L and libraray with -l.
-Ldir, --library-path=dir
Search directory dir before standard
search directories (this option must
precede the -l option that searches
that directory).
-larch, --library=archive
Include the archive file arch in the
list of files to link.
Response to answers - there is no .a library file, just .h and .c in the library, so -l isn't approriate
Then you may have to create the libraray first?
gcc -c mylib.c -o mylib.o
ar rcs libmylib.a mylib.o
I have encountered this problem when building a program with a new version of gcc. The problem was fixed by calling gcc with the -std=gnu89 option. Apparently this was due to inline function declarations. I have found this solution at https://gcc.gnu.org/gcc-5/porting_to.html