How to Create a Static Library with G++

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



Leave a reply



Submit