creating a static library using g++ -std=c++11 using templates
Since it seems you are supporting operations on a limited number of types, the classic "Just do it in a header" answer to this problem is not necessarily the best one.
You can get the best of both worlds by explicitely exporting a symbol for each implementation, but delegate the implementation to a template within the library:
libtestlib.h:
#ifndef testlib
#define testlib
#include <vector>
using namespace std;
typedef vector<vector<double>> dtest;
typedef vector<vector<int>> itest;
void test_print(dtest&);
void test_print(itest&);
libtestlib.cpp:
#include <iostream>
#include "libtestlib.h"
using namespace std;
namespace {
template <typename testtype>
void test_print_impl(testtype &t)
{
int m=t.size();
int n=t[0].size();
for(int i=0; i<m; i++) {
for(int j=0; j<n; j++)
cout << t[i][j] << " ";
cout << endl;
}
cout << endl;
}
}
void test_print(dtest& val) {
test_print_impl(val);
}
void test_print(itest& val) {
test_print_impl(val);
}
Mind you, for a small function like this, it's probably not worth the effort, and just inlining the template code in the header is just fine. At what point does the complexity of a function and the scope of its dependencies warrant this is a bit of a judgement call.
How to write a static C++ library and link it to an executable using g++ on Windows 10?
What follows are the magical incantations you seek:
- main.cpp
#include <iostream>
extern void foo();
int main() {
std::cout << "main()" << std::endl;
foo();
}
- foo.cpp
#include <iostream>
void foo() {
std::cout << "bar" << std::endl;
}
Console commands:
$ g++ -o foo.obj -c foo.cpp
$ ar rcs foo.lib foo.obj
$ g++ main.cpp foo.lib -o main.exe
These spells conjure up the static lib foo with the executable main statically linked to it.
Create shared library from cpp files and static library with g++
ld -r file1.o file2.o file3.o -o file.o
You should probably use g++
to link, not call ld
directly. Passing .o
files to GCC will cause it to invoke the linker for you, so this works:
g++ file1.o file2.o file3.o -o file.o
You say:
but I don't know how to compile .cpp files into .o files.
You just compile with -c
(and if you want to put the object file in a shared library then also -fPIC
):
g++ -c file1.cpp -fPIC -o file1.o
but I must also provide static library to this command
No, because a command with -c
is compiling, not linking, so you can't provide libraries because they are only used when linking.
So, I want shared library with all symbols from static library (libAlgatorc.a) and from all three cpp files (file1.cpp, file2.cpp and file3.cpp)
Then you need to read the answer I already pointed you to: https://stackoverflow.com/a/2649792/981959
Maybe you should read a tutorial on building software in unix-like environments, maybe something like An Introduction to GCC so that you understand the separate steps needed and what each command does.
To compile each file:
g++ -c -fPIC file1.cpp
g++ -c -fPIC file2.cpp
g++ -c -fPIC file3.cpp
(you don't need the -o
options here, by default GCC will compile a file such as file1.cpp
into file1.o
when you use the -c
option.)
Alternatively, you can do that in one step:
g++ -c -fPIC file1.cpp file2.cpp file3.cpp
You can't use the -o
option here, because there are three different .o
files produced as output of the -c
step, so you can't specify a single output file.
To link them all into a shared library that also includes the symbols from libAlgatorc.a
:
g++ file1.o file2.o file3.o -shared -o libProject.so -Wl,--whole-archive libAlgatorc.a -Wl,--no-whole-archive
Or in a single command that will compile all three files and then link them (note there is no -c
option here):
g++ -fPIC file1.cpp file2.cpp file3.cpp -shared -o libProject.so -Wl,--whole-archive -lAlgatorc -Wl,--no-whole-archive
N.B. it is redundant to say -I /usr/local/include
or -L /usr/local/include
because those paths are always searched by default anyway.
A simpler approach is to write a makefile:
libProjects.so: file1.o file2.o file3.o
$(CXX) -shared $^ -o $@ -Wl,--whole-archive -lAlgatorc -Wl,--no-whole-archive
file1.o file2.o file3.o : CXXFLAGS+=-fPIC
This is all you need in the makefile, because Make already knows how to create file1.o
from the input file1.cpp
(and setting CXXFLAGS
for the .o
targets ensures that -fPIC
will be used when compiling those files). Since you're not confident of the right commands for doing this, I suggest relying Make to get it right for you.
Creating makefile for c++ static library with g++
You should specify where the prerequisites are. This can be done by adding this line:
VPATH = source
Also, in the rule .cpp.o
, the variable CPCC
is not defined (probably should be CXX)
Also, OPT_FLAGS
should be -O0
How to force static library to include it dependencies?
Transferring comments into an answer.
Specifying the -l
and -L
operations when compiling to object files is irrelevant. Some versions of GCC warn about arguments that won't be used because they are link-time arguments, and linking won't be used when you include the -c
flag.
The ar
command doesn't know what to do with the C compiler's -l
and -L
arguments (it might have its own uses for the flags; one version of ar
accepts but ignores -l
).
So, you have to specify the dependencies when you link with the static library. That is the way life has been since the early 70s — that aspect hasn't changed yet.
Shared libraries can be built with the dependency information, but not static libraries.
As I understand it, I need to build a shared library and link it in a static way, right?
No. You either need to build and link a shared library as a shared library, or you need to accept that using a static library means you will need to specify other libraries on the command line when you use this library. There are systems to help manage such information; pkg-config
is one such. AFAIK, you cannot link a shared library in a 'static way'.
Related Topics
Statically Linking System Libraries, Libc, Pthreads, to Aid in Debugging
Why Is Padding Added for Multiple Data Members of Structures and Not for Single Members
Linux X11 - Global Keyboard Hook
Convert Windows Filetime to Second in Unix/Linux
What Is the Proper Opengl Initialisation on Intel Hd 3000
Singleton Instance Declared as Static Variable of Getinstance Method, Is It Thread-Safe
Does "Const" Just Mean Read-Only or Something More
How to Use Sdl2 and Sdl_Image with Cmake
How to Enable _Int128 on Visual Studio
Why Isn't Malloc Filling Up Memory
Find Argc and Argv from a Library
Debugging in Linux Using Core Dumps
When Are Static and Global Variables Initialized
Linking Fortran and C++ Binaries Using Gcc
How to Render an Opengl Frame in C++ Builder