using "ar" put .o files into static library - macos

The platform is mac osx, and the library's platform is arm64.
I have a static library which name is arm64.a.
Using ar -x arm64.a, I got some .o files.
And then I used ar rcs libarm64.a *.o, trying put all .o files into libarm64.a.
However, arm64.a and libarm64.a is not the same size.
libarm64.a is smaller than arm64.a.
I also tried to link libarm64.a, and linker complained undefined reference xxx.
Have I done wrong somewhere?

Related

Link multiple object files in gfortran

I have "library" folder with multiple object (.o) files. These files contain subroutines which are not changing from project to project. Each new project uses some of those object files, but not all of them.
Could you please tell me is there any way to tell gfortran to look up that folder for necessary .o files?
I've tried -I and -L options, but no way. When I write .o names directly, it works:gfortran main.for ./library/obj1.o ./library/obj2.o but I have many of .o files and write all of them waste time.
I could write gfortran main.for ./*.o but then main program will be linked with all .o files, but it needs only some of them.
I hoped that something like gfortran main.for -L./library/ will work, but it doesn't.
I use OS X with gcc version 5.1.0.
And I'm pretty sure that I should use makefile for such case
You are confusing object files with static libraries. An object file
is not a static library and the gfortran linker - which is simply
the GNU system linker, invoked by gfortran - will not treat it as such.
You need a static library and you are trying to use object files in lieu.
The linker recognizes an object file by the extension .o. It recognizes
a static library by the extension .a, and it expects the contents of an .a file
to have the form of a static library, not the format of an object file. (So you
cannot make an object file into a static library just by renaming it).
The linker will link into your program every object file that appears on its
commandline, whether or not it is needed. It does not expect you to mention
object files if you don't want them linked. The linker options -L and -l for
locating libraries have no application to object files.
A static library is a fairly simple archive containing some number of
object files, plus a house-keeping header and typically an index of the
public symbols defined in the contained object files.
When the linker encounters a static library on its commandline, it does not
link the entire contents of the library (unless you expressly tell it to). It inspects
the contained object files to determine which, if any, of them contain
definitions for symbols that are as yet undefined at that point in the linkage
of the program. If any object file in the library is found to provide any
of the missing definitions, then that object file is extracted from the library
and linked into the program. Object files in the library that provide no
missing definitions are not linked. Libraries on the commandline are sequentially
inspected in this way until either all the symbols referred to by the program
have definitions in linked object files or there are no more libraries.
If as you say the object files that you are trying to use as libraries are stable
resources that you never have to build for your projects, then you can just make a static
library out of them and link that library with your per-project programs.
To make a static library from object files, use the ar tool.
See man ar.
When you have made your library, say, libsubs.a, and have decided it shall reside
in some directory, /path/to/subs, then you link it with a program by adding
-L/path/to/subs -lsubs
to the commandline in which your program is linked. This will cause the linker
to search for a library called libsubs.a in directory /path/to/subs.
So if you are compiling and linking in a single step, use it like:
gfortran -o myprog myprog.f90 -L/path/to/subs -lsubs
And if you are compiling and linking in distinct steps, use it like:
gfortran -c -o myprog_1st_file.o myprog_1st_file.f90
gfortran -c -o myprog_2nd_file.o myprog_2nd_file.f90
gfortran -o myprog myprog_1st_file.o myprog_2nd_file.o -L/path/to/subs -lsubs
This is how you are supposed to use a set of object file resources of which
different subsets will be required for linkage with different programs: you put
them in a library and link the library.

dev cpp win32 the program can't start because sqlite3.dll is missing

I am using dev c++ IDE which used ming gcc(i am not sure of it)
I wanted to use sqlite3 in my win32 c application
I downloaded sqlite3.dll and sqlite3.dev and used dlltool to create a .a file like libsqlite3.a and pasted in the lib folder of dev cpp and added this path in the project options -> parameters
i copied the header file sqlite3.h into the include folder(which i got from another website - http://www.opensource.apple.com/source/SQLite/SQLite-74/derived_source/sqlite3.h)
i executed the program and got the message 'the program can't start because sqlite3.dll is missing in your computer'
so i copied the sqlite3.dll into my working directory and then it worked
BUT
How to make the sqlite.* static while compiling?
I mean i thought by including the libsqlite3.a, the final exe will not be dependent of any external dll's.
So i want to know how to compile in a way that i will not be needing a dll and by doing so it makes my windows program standalone.
do i have a create a .lib file instead of .a file?
EDIT after answers and comments:
Besides, the devpak is working fine... yet i wanted to know how to include files to project or to create .a files so i am trying this way because if some components do not provide devpak then this will be the way we need to compile.. isn't it?
EDIT to show what i have done after the answer by CL and the two comments
This is how i have added the sqlite.c to project list
Here is the compile log
Compiler: Default compiler
Building Makefile:
"C:\Users\jayapalc\Documents\test-sqlite\Makefile.win"
Executing make...
make.exe -f "C:\Users\jayapalc\Documents\test-sqlite\Makefile.win" all
g++.exe -c sqlite3.c -o sqlite3.o -I"lib/gcc/mingw32/3.4.2/include"
-I"include/c++/3.4.2/backward" -I"include/c++/3.4.2/mingw32" -I"include/c++/3.4.2" -I"include"
sqlite3.c: In function `void strftimeFunc(sqlite3_context*, int,
sqlite3_value**)':
sqlite3.c:14727: error: invalid conversion from void*' tochar*'
The files i got in sqlite.org/sqlite-amalgamation-3071502.zip are
shell.c, sqlite3.h, sqlite3.c, sqlite3ext.h and i saw in other discussions that shell.c is not needed...
Besides, people were talking about gcc and g++... .
Apart from updating Dev-C++ itself, try this to compile sqlite.c as a C file:
Go to Project >> Project Options >> Files.
Find the C file we're talking about. Untick "Compile file as C++".
This should inform Dev-C++ that it should invoke gcc.exe, and not g++.exe.
If you don't want to compile sqlite yourself by adding it to your project, you can try passing the -static flag to GCC/G++ to force it to link libsqlite.a statically.
Just include the sqlite3.c file in your project.
You need only this filed, and it must be compiled as C, not C++.
Apparently, Dev-C++ does not allow mixing C and C++ source files in one project.
Instead, you could try to compile sqlite3.c as C and then include the generated .o file into the C++ project (on the Linker page).

Building a Shared Library but linking against a Static One

I have an Autogen Makefile.am that I'm trying to use to build a test program for a shared library. To build my test binary, I want to continue building the shared library as target but I want the test program to be linked statically. I've spent the last few hours trying to craft my Makefile.am to get it to do this.
I've tried explicitly changing the LDADD line to use the .a version of the library and get a file not found error even though I can see this library is getting built.
I try to add the .libs directory to my link path via LDFLAGS and still it can't find it.
I tried moving my library sources to my test SOURCES list and this won't work because executable object files are built differently than those for static libraries.
I even tried replicating a lib_LIBRARIES entry for the .a version (so there's both a lib_LTLIBRARIES and a lib_LIBRARIES) and replicate all the LDFLAGS, SOURCES, dir and HEADERS for the shared version as part of the static version (replacing la with a of the form _a_SOURCES = _la_SOURCES. Still that doesn't work because now it can't figure out what to build.
My configure.ac file is using the default LT_INIT which should give me both static and dynamic libraries and as I said it is apprently building both even if the libtool can't see the .a file.
Please, anyone know how to do this?
As #Brett Hale mentions in his comment, you should tell Makefile.am that you want the program to be statically linked.
To achieve this you must append -static to your LDFLAGS.
Changing the LDFLAGS for a specific binary is achieved by changing binary_LDFLAGS (where binary is the name of the binary you want to build).
so something like this should do the trick:
binary_LDFLAGS = $(AM_LDFLAGS) -static

glibc version used while building .a file

Is there a way to find out from .a file what version of glibc is expected or was used when building the .a?
It's not a meaningful question about an ar file or a .o file. All they record is naked symbol names. When you make a shared object or an executable, the linker gives you symbols references like time##GLIBC_2.2.5 for the undefined symbols.

linker woes - undefined reference

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

Resources