我正在尝试编译一个示例 LLVM 程序。链接器步骤使用此命令。
llvm-config-3.2 --ldflags --libs
Run Code Online (Sandbox Code Playgroud)
这会产生以下命令。
g++ -o bin/Debug/test-llvm obj/Debug/main.o -L/usr/lib/llvm-3.2/lib -lpthread -lffi -ldl -lm (a boat load of LLVM libraries here)
Run Code Online (Sandbox Code Playgroud)
但是,它无法链接。我收到这样的错误。
undefined reference to ffi_type_float
Run Code Online (Sandbox Code Playgroud)
所以,我在最后添加了-lffi和。-ldl
g++ -o bin/Debug/test-llvm obj/Debug/main.o -L/usr/lib/llvm-3.2/lib -lpthread -lffi -ldl -lm (a boat load of LLVM libraries here) -lffi -ldl
Run Code Online (Sandbox Code Playgroud)
所以,是的,它们在命令中出现两次......但它是这样工作的。为什么?它们在前面的论点中被明确引用。
我在构建用C++编码的可执行文件时遇到了一个奇怪的问题,它使用的C++库本身依赖于C库.我使用gcc和使用g ++的所有其他源模块编译了构成C库的C模块.C和C++库都是静态库.
当我在C++源代码中包含来自C库的头文件时,我将其包装在extern"C"中:
extern "C"
{
#include <c-library-header.h>
}
Run Code Online (Sandbox Code Playgroud)
现在奇怪的是链接时得到"未定义的引用"错误,但这些错误取决于我列出库的顺序:
我本以为在g ++命令行中出现静态库的顺序是完全无关紧要的.有人有任何线索吗?
我在我的系统上安装了gfortran,libgfortran.a可以找到该文件/usr/lib/gcc/x86_64-linux-gnu/4.6/.使用nm我确保函数_gfortran_compare_string在那里定义:
$ nm /usr/lib/gcc/x86_64-linux-gnu/4.6/libgfortran.a | grep _gfortran_compare_string
Run Code Online (Sandbox Code Playgroud)
返回
0000000000000000 T _gfortran_compare_string
0000000000000000 T _gfortran_compare_string_char4
Run Code Online (Sandbox Code Playgroud)
但是,我的CUDA-C程序的链接器会抛出错误:
/usr/local/cuda-6.0/bin/nvcc --cudart static -L/usr/lib/gcc/x86_64-linux-gnu/4.6 -L/home/chung/lapack-3.5.0 -link -o "pQP" ./src/pQP.o -lgfortran -llapacke -llapack -lcublas -lblas -lcurand
nvcc warning : The 'compute_10' and 'sm_10' architectures are deprecated, and may be removed in a future release.
/home/chung/lapack-3.5.0/liblapack.a(ilaenv.o): In function `ilaenv_':
ilaenv.f:(.text+0x81): undefined reference to `_gfortran_compare_string'
Run Code Online (Sandbox Code Playgroud)
以及另一个错误,再次与libgfortran有关:
/home/chung/lapack-3.5.0/liblapack.a(xerbla.o): In function `xerbla_':
xerbla.f:(.text+0x49): undefined reference to `_gfortran_st_write'
xerbla.f:(.text+0x54): undefined reference to `_gfortran_string_len_trim' …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 Boost::Test 为该库创建一个 C 库和一个 C++ 测试程序。我在这个问题中发布的代码是我的代码的简化,它显示了完全相同的问题。请帮忙!
这是目录结构。 childlib是我正在尝试创建的库,并且test是测试程序。
> tree
.
`-- src
|-- main
| |-- c
| | `-- childlib.c
| |-- childlib.h
| `-- makefile
`-- test
|-- cpp
| `-- test.cpp
`-- makefile
5 directories, 5 files
Run Code Online (Sandbox Code Playgroud)
我可以childlib成功地制作成一个静态库:
> cd src/main
> make
gcc -c -fPIC -o c/childlib.o c/childlib.c
ar rcs libchildlib.a c/childlib.o
ranlib libchildlib.a
Run Code Online (Sandbox Code Playgroud)
但是我无法通过链接来制作我的测试程序:
> cd ../test/
> make
g++ -I. -I../main -Imy_boost_install_dir/include -c -std=c++11 -o cpp/test.o cpp/test.cpp …Run Code Online (Sandbox Code Playgroud) 我在练习32的学习C艰难的方法编译时遇到了很糟糕的时间.
我已经从创建者的GitHub仓库中逐字复制了代码,甚至克隆在一个新的存储库中.我已经浏览过其他存储库,除了Ubuntu之外还尝试了我的MacOSX等等.我似乎没有做任何事情就可以编译.
我使用的是Ubuntu 12.04(见下文).
这是我的文件结构(注意 - 这是我直接从练习32中包含文件时的文件结构.显然,当我克隆git存储库时,我得到更多文件.我使用diff来确保我的所有文件,包括我的make文件,在我的削减版本中完全类似于git存储库):
$ pwd
/usr/local/me/code/C/liblcthw
$ ls
bin LICENSE Makefile README.md src tests
$ ls tests/
list_tests.c minunit.h runtests.sh
$ ls src/lcthw/
dbg.h list.c list.h
Run Code Online (Sandbox Code Playgroud)
这是我的make命令.
$ make
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG -fPIC -c -o src/lcthw/list.o src/lcthw/list.c
ar rcs build/liblcthw.a src/lcthw/list.o
ranlib build/liblcthw.a
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG build/liblcthw.a tests/list_tests.c -o tests/list_tests
tests/list_tests.c: In function ‘main’:
tests/list_tests.c:111:1: warning: parameter ‘argc’ set but not used …Run Code Online (Sandbox Code Playgroud) 我有2个库:test.1和test.2.两个库都包含单个全局extern"C" void f();函数,具有不同的实现(仅cout用于测试).
我做了以下测试:
测试1动态链接:
如果我添加libtest.1.so,然后libtest.2.so在可执行文件的生成文件,然后调用f();中main,libtest.1.so->f()被调用.
如果我更改makefile中的顺序,libtest.2.so->f()则调用
测试2静态链接:
静态库完全相同
测试3动态加载
手动加载库时,一切都按预期工作.
我预计多个定义会出错,这显然不会发生.
此外,这不会打破单一定义规则,因为情况不同.
它也不是一个依赖地狱(不是它与此有关),也不是任何链接惨败..
那么,这是什么呢?未定义的行为?未指明的行为?或者它确实取决于链接顺序?
有没有办法轻松检测到这种情况?
相关问题:
dlopen与链接开销
动态链接和动态加载之间的区别
使用-Bsymbolic函数是否存在缺点?
为什么库链接的顺序有时会导致GCC错误?
将两个共享库与一些相同的符号链接起来
编辑我做了两个测试,证实了这个UB:
我添加了第二个函数void g()中test.1,而不是在test.2.
使用动态链接和.so库,同样的事情 - f以相同的方式调用,g也是可执行的(如预期的那样).
但是使用静态链接现在改变了一些事情:如果test.1是之前 test.2,没有错误,test.1则会调用两个函数.
但是当订单更改时,会出现"多个定义"错误.
很明显,"不需要诊断"(参见@MarkB的答案),但有时候发生错误是"奇怪的",有时候 - 它没有.
无论如何,答案很清楚,并解释了上面的一切 - UB.
c c++ dynamic-linking multiple-definition-error static-linking
最近,我正在做一个项目,其中一些 C++ 子例程被 Fortran 脚本调用(Fortran 求解器打算具有一些数据后处理功能,该功能来自用 C++ 开发的库)。以下过程重播错误产生过程。在这里,我使用非常简单的 Fortran 和 C++ 脚本进行简单明了的演示。
一个简单的 Fortran 主程序调用 CXX 子程序: CXX 子程序 - sub1.cxx:
#include <stdio.h>
using namespace :: std;
extern "C" void func_c_();
void func_c_()
{
printf("%d\n", 100);
}
Run Code Online (Sandbox Code Playgroud)
Fortran 主程序 - sub2.f90:
program func_fortran
implicit none
call func_c()
end program func_fortran
Run Code Online (Sandbox Code Playgroud)
编译它们:
g++ -c sub1.cxx
gfortran -o test sub2.f90 sub1.o
Run Code Online (Sandbox Code Playgroud)
我们得到可执行文件 - 测试。到目前为止,没有问题。
然后我们将 sub1.cxx 替换为 sub1.1.cxx。看起来像:
#include <iostream>
using namespace :: std;
extern "C" void func_c_();
void func_c_()
{
cout …Run Code Online (Sandbox Code Playgroud) 在我们的项目中,我们决定在项目中使用最新的 fmt 版本(6.2.0),并主要使用 printf 功能,因为我们广泛使用 printf 进行日志记录。
我使用 fmt 包中包含的 CMakeLists.txt 在 Linux 机器上构建了 libfmt.a。在我的过程中,我将 libfmt include 目录包含在 target_link_libraries 中。在代码中我只使用了#include<fmt/printf.h>. 现在,当我编译代码时,代码被编译,但在链接时,我收到错误:还有更多错误,但以下是第一个,我相信如果这个问题得到解决,其余的将自动解决
abc.cpp:(.text._ZN3fmt2V68internal8groupingIcEESsNS1_10locale_refE[_ZN3fmt2v68internal8groupingIcEESsNS1_10locale_refE]+0X20): 未定义引用 `std::string fmt::v6::internal::grouping_impl(fmt::v6::internal:: locale_ref)'
我做了一些分析,发现这个函数的定义存在于format-inl.h中。我尝试将其包含在我的代码中,但仍然存在相同的链接问题。
现在,当我在代码中定义宏FMT_HEADER_ONLY时,链接起作用了。
我的问题是:当我链接库 libfmt.a 时,它无法找到该函数。为什么?我不想使用仅标题版本。
请让我知道如何解决这个问题。
我想在linux上编译一些我知道在OSX上编译的代码,但是我遇到了一些问题.
所有文件都有名为.h的头文件,所有文件都在同一目录下.我这样编译:
gcc *.c -std=c99 -lpthread
Run Code Online (Sandbox Code Playgroud)
虽然这段代码在OSX上编译,但我在Ubuntu安装上遇到了一堆奇怪的链接器错误.我错过了一些编译器选项吗?它是一个默认的Ubuntu服务器安装,带有附加软件包gcc并build-essential已安装.
In file included from errorLogger.h:24:0,
from configParser.h:17,
from configParser.c:9:
signalHandling.h:24:18: error: unknown type name ‘sigset_t’
configParser.c: In function ‘parseConfigFile’:
configParser.c:114:5: warning: implicit declaration of function ‘getline’ [-Wimplicit-function-declaration]
In file included from errorLogger.h:24:0,
from global.h:18,
from connection.h:19,
from connection.c:10:
signalHandling.h:24:18: error: unknown type name ‘sigset_t’
connection.c: In function ‘createConnectionQueue’:
connection.c:189:28: warning: assignment makes integer from pointer without a cast [enabled by default]
In file included from errorLogger.h:24:0,
from database.h:16,
from …Run Code Online (Sandbox Code Playgroud) 我觉得我在这里错过了一些非常简单的东西。我想玩一下 clang,所以作为一个起点,我遵循了这个视频中的代码示例,大约 3:40。代码如下:
#include "clang-c/Index.h" // Note: These two lines were
#include <stdio.h> // omitted from the video slides
int main(int argc, char *argv[])
{
CXIndex Index = clang_createIndex(0, 0);
CXTranslationUnit TU = clang_parseTranslationUnit(Index, 0, argv, argc, 0, 0, CXTranslationUnit_None);
for (unsigned I = 0, N = clang_getNumDiagnostics(TU); I != N; ++I)
{
CXDiagnostic Diag = clang_getDiagnostic(TU, I);
CXString String = clang_formatDiagnostic(Diag, clang_defaultDiagnosticDisplayOptions());
fprintf(stderr, "%s\n", clang_getCString(String));
clang_disposeString(String);
}
clang_disposeTranslationUnit(TU);
clang_disposeIndex(Index);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在视频中,他没有声明他省略了这两个#include指令。我想我在上面的例子中正确填写了这些。他还省略了文件的编译和链接方式,这是我遇到问题的部分。按照 …