【问题标题】:What is the proper way to create library files with a Makefile? [C]使用 Makefile 创建库文件的正确方法是什么? [C]
【发布时间】:2013-05-11 22:57:13
【问题描述】:

我正在为一个简单的 shell 系统制作我的第一个 Makefile。我需要制作库文件,但由于某种原因,库部分无法正常工作。在错误消息中,它说库文件不存在(显然)。

我是否遗漏了可以解决此问题的明显内容?另外,有没有其他方法可以让这个 Makefile 更有效率?

# Beginning of Makefile

OBJS = obj/shutil.o obj/parser.o obj/sshell.o obj/history.o obj/hash_table.o obj/variables.o
HEADER_FILES = include/shell.h include/parser.h include/history.h include/hash_table.h include/variables.h
EXECUTABLE = sshell
LIBS = lib/libshell.so lib/libparser.so lib/libhistory.so lib/libhash_table.so lib/libvariables.so
LIBCFLAGS = $(CFLAGS) -D_REENTRANT -fPIC
CFLAGS = -Wall
CC = gcc
# End of configuration options

#What needs to be built to make all files and dependencies
all: $(EXECUTABLE)

#Create the main executable
$(EXECUTABLE): $(OBJS) $(LIBS)
    $(CC) -o $(EXECUTABLE) obj/sshell.o -Llib -lparser -lshell -lhistory -lhash_table -lvariables

#Create the library files
$(LIBS): $(OBJS)
    $(CC) $(LIBCFLAGS) -shared -o $(LIBS) $(OBJS)

#Recursively build object files
obj/%.o: src/%.c
    $(CC) $(CFLAGS) -I./include/ -c $< -o $@

#Define dependencies for objects based on header files
#We are overly conservative here, parser.o should depend on parser.h only
$(OBJS) : $(HEADER_FILES)

clean:
    -rm -f $(EXECUTABLE) obj/*.o lib/*.so lib/*.a
    -rm -f .sshell_history.txt

run: $(EXECUTABLE)
    (export LD_LIBRARY_PATH=lib; ./$(EXECUTABLE))

# End of Makefile

谢谢! -百合银行

编辑:

在我尝试更改它之前,这是我对库文件的看法。

$(LIBS): $(OBJS)
    $(CC) -shared -o lib/libparser.a obj/parser.o
    $(CC) -shared -o lib/libshell.a obj/shutil.o
    $(CC) -shared -o lib/libhistory.a obj/history.o
    $(CC) -shared -o lib/libhash_table.a obj/hash_table.o
    $(CC) -shared -o lib/libvariables.a obj/variables.o

这样做的问题是它编译每个文件五次,这根本没有效率。所以我想做的就是一口气做完。

编辑2:

#Create the library files
lib/libparser.so: obj/parser.o
    $(CC) $(LIBFLAGS) -shared lib/libparser.a -o $@

lib/libshell.so: obj/shutil.o
    $(CC) $(LIBFLAGS) -shared lib/libshell.a -o $@

lib/libhistory.so: obj/history.o
    $(CC) $(LIBFLAGS) -shared lib/libhistory.a -o $@

lib/libhash_table.so: obj/hash_table.o
    $(CC) $(LIBFLAGS) -shared lib/libhash_table.a -o $@

lib/variables.so: obj/variables.o
    $(CC) $(LIBFLAGS) -shared lib/libvariables.a -o $@

不幸的是,这是我得到的错误:

make: *** No rule to make target `lib/libvariables.so', needed by `sshell'.  Stop.

想法?

编辑3:

#Create the library files
lib/libparser.so: obj/parser.o
    $(CC) $(LIBFLAGS) -shared $^ -o lib/libparser.a

lib/libshell.so: obj/shutil.o
    $(CC) $(LIBFLAGS) -shared $^ -o lib/libshell.a

lib/libhistory.so: obj/history.o
    $(CC) $(LIBFLAGS) -shared $^ -o lib/libhistory.a

lib/libhash_table.so: obj/hash_table.o
    $(CC) $(LIBFLAGS) -shared $^ -o lib/libhash_table.a

lib/libvariables.so: obj/variables.o
    $(CC) $(LIBFLAGS) -shared $^ -o lib/libvariables.a

这可行,但我还有什么需要改变的吗?谢谢

【问题讨论】:

  • 在您的编辑中,您告诉 make 在更新目标文件之一时重新编译所有库。每个库都需要一个目标。
  • 是的,我听取了您的建议,并尝试了一些方法,但没有成功。我将用我现在拥有的内容再次对其进行编辑。谢谢
  • 你有 lib/variables.so 而不是 lib/libvariables.so
  • 尴尬,对不起。这是我现在遇到的错误:gcc: lib/libvariables.a: No such file or directory gcc: no input files
  • 你有静态库 lib/libvariables.a 吗?我希望您必须将 lib/libvariables.a 替换为 obj/variables.o。甚至更好 $^

标签: c unix makefile


【解决方案1】:

每个库都需要一组目标文件。并且 -o 标志只接受一个参数,即输出文件,您正在尝试输出所有库文件,而这些库文件不能通过一次 gcc 调用来完成。

您需要执行以下操作:

lib/libshell.so: obj/sshell.o
    $(CC) $(LIBFLAGS) -shared obj/sshell.o -o lib/libshell.so

lib/libparser.so: obj/parser.o
    $(CC) $(LIBFLAGS) -shared obj/parser.o -o lib/libparser.so

对于每个库。

【讨论】:

    【解决方案2】:

    这一行完全错误:

    $(LIBS): $(OBJS)
            $(CC) $(LIBCFLAGS) -shared -o $(LIBS) $(OBJS)
    

    如果您展开所有变量,此行将如下所示(为清楚起见添加换行符):

    lib/libshell.so lib/libparser.so lib/libhistory.so lib/libhash_table.so lib/libvariables.so: \
                obj/shutil.o obj/parser.o   obj/sshell.o obj/history.o obj/hash_table.o obj/variables.o
            gcc -Wall -D_REENTRANT -fPIC -shared -o lib/libshell.so lib/libparser.so lib/libhistory.so \
                lib/libhash_table.so lib/libvariables.so obj/shutil.o obj/parser.o obj/sshell.o obj/history.o \
                obj/hash_table.o obj/variables.o
    

    应该很清楚,这是非常不正确的。这太不对了,我什至无法真正说出你想要完成的事情。您真的要为每个.o 文件创建一个共享库,其中每个共享库都包含一个.o?如果是这样,您为什么要尝试将 .o 文件和共享库链接到一个可执行文件中?

    如果您在更高层次上解释您真正想做的事情,我们可以提供帮助。

    【讨论】:

    • 在我想我应该更清楚之前用我所拥有的内容编辑我的主要帖子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-27
    • 2012-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-08
    相关资源
    最近更新 更多