使用g++从cpp文件和静态库创建共享库

21

就像标题所说,我想从三个cpp文件和一些静态库创建共享库。

基本上我想做这个。

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

这是我的file1.cpp文件:

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

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

这是我的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 "";
    }
};

这是我的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 
    }
};

我认为我需要创建三个.o文件(file1.o file2.o file3.o),然后像这样合并它们

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

当我有file.o文件时,我认为我需要这样说:

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

但我不知道如何把.cpp文件编译成.o文件。我知道可以这样做:

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

但我还必须为此命令提供静态库,因为file1.cpp(和其他文件)继承了在/usr/local/include/TestSetIterator.hpp中定义但在/usr/local/lib/libAlgatorc.a中实现的类。由于使用了-c选项,我不能说-L /usr/local/lib -lAlgatorc

最后,我希望有这三个类的共享库,以便在主函数中将此库加载到我的程序中,并且可以从这三个类中调用方法。因此,我需要一个含有所有符号的共享库,包括静态库(libAlgatorc.a)和所有三个cpp文件(file1.cpp、file2.cpp和file3.cpp)。

我正在使用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.

1
这不是我已经指向你的问题的重复吗?https://dev59.com/MHE85IYBdhLWcg3wtV1T - Jonathan Wakely
不,没有从静态库和cpp文件构建共享库。只有从静态库构建共享库。我想要将它们结合起来。 - golobitch
基本上还是一样的。只需将.o文件添加到答案中的命令即可。关键是另一个答案展示了如何确保静态库中的所有符号最终都出现在共享库中,这正是你的问题所在。 - Jonathan Wakely
实际上,如果您阅读问题,您会发现链接器命令包括文件:some.o another.o,这完全相同。 - Jonathan Wakely
当我来到这里时,我正在寻找 g++ ./libsomething.cpp -fPIC -shared -o ./libsomething.so - Martin Thoma
1个回答

43

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

你可能应该使用g++进行链接,而不是直接调用ld。将.o文件传递给GCC会导致它为您调用链接器,因此这样处理:

g++ file1.o file2.o file3.o -o file.o

您说:

但我不知道如何将.cpp文件编译为.o文件。

您只需要使用-c进行编译(如果您想将目标文件放在共享库中,则还需要使用-fPIC):

g++ -c file1.cpp -fPIC -o file1.o
但是我还必须为这个命令提供静态库。
不行,因为使用-c参数的命令是在编译而不是链接,所以你不能提供库,因为它们只在链接时使用。
所以,我想用所有符号从静态库(libAlgatorc.a)和三个cpp文件(file1.cpp,file2.cpp和file3.cpp)中获取共享库。
那么你需要阅读我已经指向你的答案:https://dev59.com/MHE85IYBdhLWcg3wtV1T#2649792 也许你应该阅读一篇关于在类Unix环境下构建软件的教程,比如GCC入门,这样你就可以了解所需的各个步骤以及每个命令的功能。
要编译每个文件:
g++ -c -fPIC file1.cpp
g++ -c -fPIC file2.cpp
g++ -c -fPIC file3.cpp

(在这里你不需要使用-o选项,因为默认情况下GCC将在使用-c选项时将文件file1.cpp编译成file1.o。)

或者,您可以一步完成此操作:

g++ -c -fPIC file1.cpp file2.cpp file3.cpp

因为在-c步骤生成了三个不同的.o文件,所以您无法在此处使用-o选项来指定单个输出文件。

要将它们全部链接到一个共享库中,并包含来自libAlgatorc.a的符号:

g++ file1.o file2.o file3.o -shared -o libProject.so -Wl,--whole-archive libAlgatorc.a -Wl,--no-whole-archive

或者使用一个单一的命令来编译这三个文件并将它们链接起来(注意这里没有 -c 选项):

g++ -fPIC file1.cpp file2.cpp file3.cpp -shared -o libProject.so -Wl,--whole-archive -lAlgatorc -Wl,--no-whole-archive

N.B.说 -I /usr/local/include-L /usr/local/include 是多余的,因为这些路径默认情况下总是被搜索。

一个更简单的方法是编写一个 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

这就是您在makefile中所需的全部,因为Make已经知道如何从输入file1.cpp创建file1.o(并设置CXXFLAGS用于.o目标,以确保在编译这些文件时使用-fPIC)。由于您不确定正确的命令,我建议依靠Make来为您完成。


1
如果我像你一样做这个,我会得到以下内容: /usr/bin/ld: /usr/local/lib/libAlgatorc.a(ParameterSet.o): relocation R_X86_64_32 相对于`.rodata.str1.1'无法在制作共享对象时使用;请重新编译并加上 -fPIC。 /usr/local/lib/libAlgatorc.a(ParameterSet.o): 无法读取符号:坏值 collect2: 错误:ld 返回了 1 个退出状态。 - golobitch
这意味着libAlgator.ca中的对象不可重定位,因此无法在共享库中使用。您需要获取一个新版本的libAlgatorc,其中内容是使用-fPIC构建的(也许获取.so),或者您无法使其工作,并且必须将主可执行文件链接到-lAlgatorc而不是将其包含在libProject.so中。 - Jonathan Wakely
2
太棒了!那个命令 g++ -fPIC file1.cpp file2.cpp file3.cpp -shared -o libProject.so -Wl,--whole-archive -lAlgatorc -Wl,--no-whole-archive 像魔法一样运行正常!问题也在静态库中。静态库没有用-fPIC编译,但必须这样做,因为我们正在将那些符号添加到共享库中。真的是完美的答案!:) 感谢您的所有帮助! - golobitch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接