21

Just like title says, I want to create shared library from three cpp files and with some static library.

Basicly I want to do this

g++ libProject.so file1.cpp file2.cpp file3.cpp -I /usr/local/include -L /usr/local/lib -lAlgatorc 

This is my file1.cpp:

#include <iostream>
#include <TestSetIterator.hpp>

class SortingTestSetIterator : public TestSetIterator {
public: 
    TestCase *get_current(){
         //TODO: implement method
         return nullptr; 
    }
};

This is my file2.cpp

#include<iostream>
#include<TestCase.hpp>
#include<Entity.hpp>
#include<ParameterSet.hpp>

class SortingTestCase : public TestCase {
public: 
    std::string print() { 
         //TODO: implement method
        return "";
    }
};

And this is my file3.cpp

#include <iostream>
#include <AbsAlgorithm.hpp>
#include "SortingTestCase.cpp"
class SortingAbsAlgorithm : public AbsAlgorithm {
private: 
    SortingTestCase Sorting_test_case;
public:
    bool init (TestCase &test) {
         //TODO: implement method
         return true; 
    }

    void run() {
         //TODO: Implement method 
    }

    void done() {
         //TODO: Implement method 
    }
};

I think that I need to create three .o files (file1.o file2.o file3.o) and then combine them like this

ld -r file1.o file2.o file3.o -o file.o

When I have file.o I suppose that then I need to say this:

g++ -shared -o libProject.so file.o

but I don't know how to compile .cpp files into .o files. I know I can do it like this

g++ -std=gnu++11 -o file1.o -fPIC -c file1.cpp -I /usr/local/include

but I must also provide static library to this command, because file1.cpp (and other files) inherits class that is defined in /usr/local/include/TestSetIterator.hpp but is implemented in /usr/local/lib/libAlgatorc.a Because of -c I can't say -L /usr/local/lib -lAlgatorc

At the end, I want shared library of this three classes so that in main function I can load this library into my program and that I can call methods from this three classes. 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)

I am using Ubuntu 12.04 x64.

> g++ --version
g++ (Ubuntu 4.8.1-2ubuntu1~12.04) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
golobitch
  • 1,466
  • 3
  • 19
  • 38
  • 1
    Isn't this a dup of the question I already pointed you to? http://stackoverflow.com/questions/2649735/how-to-link-static-library-into-dynamic-library-in-gcc – Jonathan Wakely Jul 21 '15 at 14:22
  • No. There isn't shared library build from static library and cpp files. There is shared library build only from static library. I want this both combined. – golobitch Jul 21 '15 at 14:26
  • It's still basically the same. Just add the `.o` files to the command in that answer. The point is that the other answer shows how to ensure all symbols from a static library end up in a shared library, which is exactly your problem. – Jonathan Wakely Jul 21 '15 at 14:32
  • In fact it's _exactly_ the same, if you read the question you will see the linker command includes the files: `some.o another.o` – Jonathan Wakely Jul 21 '15 at 14:54
  • When I came here, I was looking for `g++ ./libsomething.cpp -fPIC -shared -o ./libsomething.so` – Martin Thoma Feb 18 '20 at 18:44

1 Answers1

43

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.

Community
  • 1
  • 1
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • 1
    If I do this like you did I get this: /usr/bin/ld: /usr/local/lib/libAlgatorc.a(ParameterSet.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC /usr/local/lib/libAlgatorc.a(ParameterSet.o): could not read symbols: Bad value collect2: error: ld returned 1 exit status – golobitch Jul 21 '15 at 14:37
  • That means the objects in `libAlgator.ca` are not relocatable and so can't be used in a shared library. You either need to get a new version of `libAlgatorc` where the contents are built with `-fPIC` (maybe get a `.so` intead) or you can't make this work, and will have to link your main executable to `-lAlgatorc` instead of including it in `libProject.so` – Jonathan Wakely Jul 21 '15 at 14:43
  • 2
    Much better! That command `g++ -fPIC file1.cpp file2.cpp file3.cpp -shared -o libProject.so -Wl,--whole-archive -lAlgatorc -Wl,--no-whole-archive`is working like a charm! Problem was also in static lib. static lib is not compiled with -fPIC but it must be, because we are adding those symbols to shared library. Perfect answer really! :) Thank you for all your help! – golobitch Jul 21 '15 at 14:56