如何在实践中解决项目编译中链接库的顺序
Posted
技术标签:
【中文标题】如何在实践中解决项目编译中链接库的顺序【英文标题】:How to solve in practice the order of linked libraries in compilation for a project 【发布时间】:2015-11-27 02:51:24 【问题描述】:我一直在从事一个项目,该项目使用来自许多作者(物理学)的不同来源和代码,我想将它们合并在一起并在它们之间进行交流。 问题是其中一些源代码和 makefile 会先调用链接库,然后再调用 c 文件:
$(CC) $(lflags) -o smith2demo smith2demo.o smith2.o
到目前为止,在我研究所的计算机和其他一些系统上,一切正常。我有这个 gcc 编译器:
$gcc --version
gcc (Debian 4.9.2-10) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
所以,直到我尝试在 Ubuntu 上运行我的代码时,我才注意到这个问题:
gcc (Ubuntu 4.9.3-5ubuntu1) 4.9.3
Copyright (C) 2015 Free Software Foundation, Inc.
在 ubuntu 中,我得到如下信息:
smith2.c:(.text+0x29b): undefined reference to `sincos'
我知道链接库规范及其原因,在这里回答:
GCC C++ Linker errors: Undefined reference to 'vtable for XXX', Undefined reference to 'ClassName::ClassName()'
Why does the order in which libraries are linked sometimes cause errors in GCC?
Why am I getting a gcc "undefined reference" error trying to create shared objects?
所以,我有两个问题:
为什么如果两个 gcc 都是最新版本,我在 Debian 系统中没有这个问题?
我怎样才能将此代码分发给其他人,而不告诉他们更改所有在 C 文件之前调用库的 makefile?
在我的项目中的大多数情况下,我使用一个整体 Makefile,然后我只需更改到源文件夹并在其中执行 $(MAKE)
。
有没有办法将--no-as-needed
设置为每个人的一般选项或更智能的方法?
我对 makefile 的经验很少。
【问题讨论】:
也许您应该使用更完整的构建系统,例如 cmake。很难为您提供帮助,因为需要更多信息。比如,你提到的库是系统库吗?还是它们与您的项目一起分发? @iharobcmake
在这里有什么帮助?我看不出它怎么可能。
我会非常仔细检查你在 debian 机器上没有问题。我不明白你怎么不会(除非你没有在你认为你是编译的时候编译,或者你错过了与该过程不同的其他东西)。通常不能添加标志,除非有正在使用的变量可以赋予 make 配方使用的值。出于某种原因,内置的 make 规则为此目的具有变量。一旦你了解了它们应该如何工作,就会经常告诉人们修复他们的 makefile。
@iharob OP 有 other 人制作的 makefile,他们需要与之交互。当它们被错误地写入时,cmake 将如何帮助纠正这些 makefile?它将如何允许为所有这些编译配方提供--as-needed
?
@iharob 是的,我有。虽然我通常避免使用 cmake,因为每次我研究它时,我都会对它糟糕的内部决策(在它是如何构建的)感到更加恼火。它对 other 项目的 makefile 没有帮助。它无助于为不相关的项目设置标志。它可以帮助按顺序获取主要项目的标志等,但这不是问题。
【参考方案1】:
在我的个人生活中,我使用自己的 Makefile。这是它的简单版本。
MAIN = main
HEADER_DEFINITIONS = fibo
CC = g++-4.9 -std=c++11
COMPILE = -c
EXE = $(MAIN)
OPTIMIZE = -Os
SHELL = /bin/bash
ARGS = 20
all: link
@echo "Executing..........."
@echo " > > > > > > OUTPUT < < < < < < "
@$(SHELL) -c './$(EXE) $(ARGS)'
link: compile
@echo -n "Linking............."
@$(SHELL) -c '$(CC) -o $(EXE) *.o'
compile: $(MAIN).cpp $(HEADER_DEFINITIONS).cpp
@echo -n "Compiling........."
@$(SHELL) -c '$(CC) $(OPTIMIZE) $(COMPILE) $^'
clean:
@echo "Cleaning............"
@$(SHELL) -c 'rm -f *~ *.o $(EXE)'
如果你想进一步修改和添加某些链接器标志,完全可以
编辑 2 我的个人 Makefile
#
# A simple makefile for managing build of project composed of C source files.
#
# It is likely that default C compiler is already gcc, but explicitly
# set, just to be sure
CC = gcc
# The CFLAGS variable sets compile flags for gcc:
# -g compile with debug information
# -Wall give verbose compiler warnings
# -O0 do not optimize generated code
# -std=c99 use the C99 standard language definition
# -m32 CS107 targets architecture IA32 (32-bit)
CFLAGS = -g -Wall -O0 -std=c99 -m32
# The LDFLAGS variable sets flags for linker
# -lm says to link in libm (the math library)
LDFLAGS = -lm
# In this section, you list the files that are part of the project.
# If you add/change names of source files, here is where you
# edit the Makefile.
SOURCES = demo.c vector.c map.c
OBJECTS = $(SOURCES:.c=.o)
TARGET = demo
# The first target defined in the makefile is the one
# used when make is invoked with no argument. Given the definitions
# above, this Makefile file will build the one named TARGET and
# assume that it depends on all the named OBJECTS files.
$(TARGET) : $(OBJECTS)
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
.PHONY: clean
clean:
@rm -f $(TARGET) $(OBJECTS) core
【讨论】:
这是一个相当糟糕的makefile,因为它不会让make 做任何设计要做的事情,即它无法避免在源未更改时重新编译。它还需要对项目中的每个文件进行修改(因为它没有使用模式规则)。 是的,但“基本和错误”不是很有帮助。第二个好多了。虽然使用内置的链接方法会更好。 在现实生活中,我使用自己的 python 脚本为更大的项目构建源代码,这些项目可以从元文件(.build file)
中读取构建过程的所有参数。它还可以使用正则表达式来解决重复的文件名、任何其他依赖列表,甚至从构建过程中排除某些文件。以上是关于如何在实践中解决项目编译中链接库的顺序的主要内容,如果未能解决你的问题,请参考以下文章
linux找动态链接库默认位置,linux动态链接库的加载顺序,编译时找静态库默认位置,找动态库,找静态库
linux找动态链接库默认位置,linux动态链接库的加载顺序,编译时找静态库默认位置,找动态库,找静态库
GCC 编译使用动态链接库和静态链接库--及先后顺序----及环境变量设置总结
VS远程开发(远程调试)编译报错:对‘xxx’未定义的引用(设置库依赖顺序)(已解决)pthread(项目-->属性-->链接器-->输入-->库依赖项)