Not Getting .a File From Compiling Static Library C++ (Linux Kernel) [duplicate] - c++

This question already has answers here:
How does "make" app know default target to build if no target is specified?
(4 answers)
Closed 2 years ago.
I am trying to compile a static library of the sorts:
foo.c
foo.h
My makefile looks like:
foo.o: foo.c
cc -c foo.c
libfoo.a: foo.o
ar -rv libfoo.a foo.o
I just call make from the directory.
It compiles the .c file and gives a .o file, however, I don't get a .a file. Although, I can run the exact commands sequentially and get the .a file.
I'm sure it's something simple I'm messing up. I've looked all over but the examples aren't really helping as they're much more intricate than my circumstance.

Just calling make without parameters will by default use the first goal, which is foo.o. Since that does not depend on libfoo.a (and why should it of course), the second recipe is never triggered.
The result is a .o file but no .a file.
From https://www.gnu.org/software/make/manual/html_node/Goals.html
By default, the goal is the first target in the makefile
If for any reason you are forced to use make as just make, then reorder the parts in your makefile, to ensure that the first target is the one you need.
Alernatively, as described on the same page a few lines later
You can manage the selection of the default goal from within your makefile using the .DEFAULT_GOAL variable (see Other Special Variables).

Related

Why do we need object files? [duplicate]

This question already has answers here:
What is the purpose of creating object files separately and then linking them together in a Makefile?
(4 answers)
Difference between compiling with object and source files
(2 answers)
Is there any benefit to passing all source files at once to a compiler?
(3 answers)
Closed 1 year ago.
Why do we need object files? I've tried linking multiple files by using the command g++ -o main.exe main.cpp (other files).cpp, and it works. However, from tutorials online, it needs the files to be turned into *.o files first by using the command g++ -c main.cpp (other files).cpp, and use g++ -o main.exe main.o (other files).o to link the files together. If we can just do the same thing with g++ -o main.exe main.cpp (other files).cpp, why do we need to turn files into *.o first?
TL;DR version:
You don’t need to create the object files. It’s fine to directly compile into an executable.
Long version:
You do not need to explicitly create the object files here. However, do note that the compiler does create these object files as intermediate files for each source file. Once, the compiler has all the object files available, the linker comes into play and matches definitions of each function with an implementation (amongst other things). The linker finally creates the executable and deletes the object files since you didn’t ask for them.
However, you can ask the compiler to store these intermediate files using the command as stated in your question.
As mentioned in the comments, it’s almost always good practice to compile only the source files that have changed in the last development cycle. This necessitates that you have object files available for the unchanged source files. I simply wanted to state that directly compiling is legal.

Undefined reference when trying to use external library

I am trying to incorporate a C library into some Rcpp code.
I can use the C library in a C++ program easily. I 'make' the C library, which creates the .a and .dll files in the /lib folder. I can then use the package by including the header in the program and running something like this from command line:
cc myfile.cpp -o myfile -Ipath.to.header path.to.lib.a -lz
This essentially tells the compiler to take the .cpp program, include headers from -I, and to link to two libraries.
Getting this to work with Rcpp shouldn't be overly difficult if I understand makevars correctly (which I unfortunately don't seem to).
I add the library to a folder in my package, and in src I add a makevars and makevars.win that look like this:
PKG_CFLAGS=
# specify header location
PKG_CPPFLAGS=-Ipath.to.lib/include
# specify libs to link to
PKG_LIBS=path.to.lib/lib/file.a -lz
# make library
path.to.lib/lib/file.a:
cd path.to.lib;$(MAKE)
This correctly 'makes' the .a and .dll files for the library, however none of the Rcpp magic runs (i.e. in the build I never see the g++ system call that compiles the files in src), so "no Dll was created".
I am fairly certain this is a problem in my makevars target that makes the library. When I remove that portion from the makevars, and 'make' the library from the command line myself before building the package, I get the proper g++ calls with my -I and -l statements, but I get errors about undefined references.
I notice that the -l statements are only included in the final g++ call where the final .dll is made, but isn't included in the earlier g++ calls where the files with the library headers are compiled.
So I have two problems:
How do I fix my makevars so that it 'makes' the library, but doesn't stop Rcpp from compiling the files in src?
How do I deal with the undefined references? The library is clearly not header-only, so I am guessing it needs the -l statement in the earlier g++ calls, but that may not even be possible.
The best approach is to avoid complicated src/Makevars file altogether.
One easy-ish approach around this: use configure to build your static library, then once you actually build just refer to it in src/Makevars.
I use that scheme in Rblpapi (where we copy an externally supplied library in) and in nloptr where we download nlopt sources and build it 'when needed' (ie when no libnlopt is on the system).

GNU make ignores Implicit rules

I'm trying to compile some C++ sources with GNU make using implicit rules, here's the content of my Makefile:
%.o: %.cpp
g++ -o $# $<
and the output of make
make: *** No targets. Stop.
Running make -d isn't very helping (I don't post the output which is quite verbose other than apparently useless). The folder is not empty.
You told Make how to build .o files, but you didn't tell it:
to build any .o files;
which .o files to build;
what to do with those .o files afterwards.
The rule doesn't mean that, when invoked without arguments, all .cpp files in the current directory or something will be compiled.
This one rule is just not enough.
You told make how to create arbitrary .o files from corresponding .cpp files, but you didn't tell it which files to create.
Analogy: I tell you, that, say, to make USB sticks, you'll need plastic, memory chips and a USB-A plug (now you know how to create any USB stick). But I don't say which USB sticks to create. This is exactly, what's happening here.
To solve your issue, you can say to make to create (for example) "asdf.o" by invoking make asdf.o, and it'll gladly do so, by using g++ -o asdf.o asdf.cpp.
You can also add an (de facto standard) all target, like so:
all: asdf.o fdsa.o [you get it]
And since the first target is the default, calling make is equivalent to calling make all, which in turn requires "asdf.o" and "fdsa.o", which will be created as described above.

Make G++ use my lib automatically

I have an already built library made of this files:
A bunch of headers.
A .so file (libmylib.so).
I want to compile a c++ program (sample.cpp), where I included the headers, and where I need to use the library. This is what I've done, and it's working:
Put the headers in usr/local/include.
Put the .so file in usr/local/lib.
Compile the program in this way: g++ sample.cpp -lmylib.
My question is: why is it not working if I omit -lmylib from the last line?
Is there a way to install the library such that I don't need to put it every time in the g++ command?
Thank you.
What libs are used by default depends on some setting in the compiler/linker,
but it´s not "every lib in usr/local/lib" or any directory, just some specific names
(or even just a single one). Call g++ -v or g++ -dumpspecs to list it (and more stuff)
So, either rebuild your compiler with your own lib list, or specify it manually everytime.

C++ linking to libraries with makefile (newbe)

I'm trying to understand how to use non standard libraries in my C++ projects.
I have a few questions.
Lets say I want to use POCO library. So I downloaded it and build it using make (static build). Now I have bunch of .o files and .h files.
There is a Path.h file and a Path.o file in different directories.
Now I want to use this module in my code. So i include the file using #include "Poco/Path.h". Do I have to modify makefile and add Path.o to my target ?
What happens when I use standard library ? Are those available only in header files ? I know that template code cannot be precompiled. What about the rest ?
Besides the .h and .o files, you will probably also have one or more libXXX.a and/or libXXX.so files. These are the actual library files that your application should link against.
To use the library, you include the relevant headers in your source file, and you change your makefile to tell the linker that it should also link your application to the XXX library.
The typical linker-command for that is -lXXX and the linker will look for both libXXX.a and libXXX.so and use whichever seems most appropriate.
The standard library is not really different from external libraries, except that you don't have to specify it explicitly to the linker.
Your question seems to imply that you already have a makefile for your own code. If that's the case, then yes, you should modify the rule for your executable in that makefile. As Bart van Ingen Schenau points out, the POCO makefile probably assembled the objects files into libraries such as Poco/Libraries/libPoco.a, so you should use them instead of trying to pick out the object files you need. For instance, if right now your rule reads:
foo: foo.o bar.o
g++ -lSomeLibrary $^ -o $#
you should change it to
foo: foo.o bar.o
g++ -lSomeLibrary -LPoco/Libraries -lPoco $^ -o $#
(The second part of your question, "What happens... What about the rest?" is unclear to me.)
Note: It's a bad idea to #include "Poco/Path.h". This makes your code dependent on a directory structure, something it should not care about. It is much better to #include "Path.h" and tell the compiler where to find it: g++ -c -IPoco ....