从外部目录链接到库

Linking with a library from external directory

本文关键字:链接 从外部      更新时间:2023-10-16

编辑:我已经根据答案用我所做的更改更新了我的问题我正试图链接到我写的一个小库,以了解如何用C++完成这项工作,但运气不好。G++正在向undefined reference抱怨。

我要链接的库的根目录在目录~/code/gklib/cxx/中。该目录的结构如下:

~/code/gklib/cxx/
|
|`-> gk.{hh,cc}
|`-> libgk.o
|
 `-> lib/
     |
     `-> libgk.a

我用-c标志编译了gk.cc,然后用ar rvsc lib/libgk.a libgk.o将生成的对象文件转换为.a文件。

此库的客户端位于文件夹~/code/cpp中。在这个目录中,我再次将some_stuff.cc编译为一个对象文件,然后我尝试用以下命令链接到它:

$ cxx some_stuff.o -L../gklib/cxx/lib -lgk -o some_stuff

我得到这个错误:

some_stuff.o: In function `main':
some_stuff.cc:(.text+0x49): undefined reference to `void GK::algorithms::insertionSort<int, 5ul>(int*)'
collect2: error: ld returned 1 exit status

这些是这些文件的内容:

~/code/cpp/some_stuff.cc

#include <cstdlib>
#include <iostream>
#include <gk.hh>
using namespace std;
int main(int argc, char **argv) {
  int i = -1;
  int arr[5] = { 3, 4, 2, 1, 5 };
  const size_t len = sizeof(arr)/sizeof(int);
  GK::algorithms::insertionSort<int, len>(arr);
  while(++i < 5)
    cout << arr[i] << " ";
  cout << endl;
  exit(EXIT_SUCCESS);
}

~/code/gklib/cx/gk.cc

#include "gk.hh"
template<class T, size_t len>
void GK::algorithms::insertionSort(T arr[len]){
  // insertion sort
}

~/code/gklb/cxx/gk.hh

#pragma once
#include <cstdlib>
#define NAMESPACE(ns) namespace ns {
#define END_NAMESPACE(ns) }
NAMESPACE(GK)
NAMESPACE(algorithms)
template<class T, size_t len>
extern void insertionSort(T arr[len]);
END_NAMESPACE(algorithms)
END_NAMESPACE(GK)

我在命令上尝试了很多变体,但都没有结果。互联网上到处都是教程和论坛,上面有对我不起作用的说明。当所有东西都在一个文件中时,这段代码运行得很完美。我该如何解决这个问题?提前谢谢。

我认为它更像是:

cxx some_stuff.o -L$HOME/gklib/cxx/lib -B../gklib/cxx/lib -lgklib -o some_stuff

-lgklib,而不是-Igklib-I选项指定包含文件夹)

但是你必须用libgklib.a 重新命名你的gklib.a

也许你甚至可以删除-B../gklib/cxx/lib,只需尝试一下:)

我看到了几个问题:按顺序:

  • 如果这是您的确切命令行,则-L选项不会指向上面显示的结构(没有路径中的cxx)。

  • 我不知道你为什么用-B。这告诉编译器在哪里查找库等。通常,这只是当您想要测试编译器的某些部分时修改。

  • 我看不出你指定在哪里链接图书馆因为图书馆不尊重通常的命名约定(libname.a),您必须直接指定它(与指定对象的方式相同文件),并且不使用-L选项。或者,您命名它是libgk.a或类似的东西,并将-lgk添加到命令行,对象文件之后。

  • 最后,错误消息指的是模板。这通常是因为模板位于源文件中,而不是标头中。这个标准要求实现在触发模板的实例化。g++(和几乎所有其他编译器)的工作原理是,如果不可见,他们认为模板将在另一个翻译单元中实例化,并从外部输出引用。但是如果实现在源中,将不会有实例化,并且您将得到一个链接器错误。(您也找不到实例化的汇编程序任何地方,因为模板还没有实例化。)您应该在底部包含源代码您的头,而不是单独编译它。

在这个和这个问题的帮助下,我解决了这个问题。问题在于void insertionSort(T *)是一个模板函数,模板函数只能在头文件中实现。原因是,编译器需要达到的定义,才能为每次调用创建一个新函数,并将不同的类型作为模板的参数。我已经将此函数的定义移动到gk.h,这导致了成功的编译和链接。