制作具有多个类的库,附加预先存在的 .a 库和其他依赖项

Posted

技术标签:

【中文标题】制作具有多个类的库,附加预先存在的 .a 库和其他依赖项【英文标题】:Making library with multiple classes, additional pre-existing .a library and other dependencies 【发布时间】:2017-04-28 08:23:14 【问题描述】:

我已经完成了几个类,我在一个名为“LidarPathMapping”的类中使用它们。我已经 2 天在寻找一种解决方案,以使人们可以在他的代码中包含该类并使用它。我不希望他需要包含 LidarPathMapping 依赖的其他类以及我编译用于测试我的代码的驱动程序的所有其他依赖项。我的代码还依赖于一个名为 librplidar_sdk.a 的库和另一个名为 PIGPIO 的库(它在树莓派中运行)。我希望想要使用我的代码的人只需要

#include "LidarPathMapping.h"

在他的代码中并用类似的东西编译:

g++ main.cpp -L. -lLidarPathMapping

我不介意这个人是否需要包含我正在使用的库(请参阅 make 文件),但需要包含我所做的每个类的每个对象会破坏目的。我对方法没有偏好,我只想为想要使用它的人简化事情。如果有人能告诉我用户将如何使用该库,我将不胜感激:如何包含在 .cpp 文件和 g++ 编译命令中。这是我为编译驱动程序以测试我的代码所做的 makefile:

CFLAGS=  -w -Wall

LDIR= /home/pi/Documents/code/cpp/andar/andar/include

LIBS= -lboost_iostreams -lboost_system -lboost_filesystem \
       -lrplidar_sdk -lstdc++ -lpthread -lpigpio -lrt -pthread \
       -lGL -lGLU -lglut

#DEFS = -D USE_OPEN_GL
######################### Objects ###########################

OBJS = objects/LidarPlusServo.o \
        objects/CloudManipulation.o \
        objects/RoverParameters.o \
        objects/csvReader.o \
        objects/Dstar.o \
        objects/LidarPathMapping.o \


######################### Headers ###########################

ANDARHEADERS = andar_include/LidarPlusServo.h \
               andar_include/CloudManipulation.h \
               andar_include/RoverParameters.h \
               csvReader/csvReader.hpp \
               include/Dstar.h \
               andar_include/LidarPathMapping.h \

######################### Source Files ###########################
ANDARSRC = LidarPlusServo.cpp \
               CloudManipulation.cpp \
               RoverParameters.cpp \
               csvReader/csvReader.cpp \
               Dstar.cpp \
               LidarPathMapping.cpp \


######################## Executable ##################################

#Change name here#
#If main file is called "helloWorld.cpp", write "helloWorld"

NAME = driverLidPathMap

$(NAME): $(OBJS) $(NAME).cpp
    sudo g++ -std=c++11 $(CFLAGS) -o $(NAME) $(NAME).cpp $(OBJS) \
                     $(LIBS) -L$(LDIR)

####################### Create Objects ########################
objects/LidarPlusServo.o: LidarPlusServo.cpp $(ANDARHEADERS) 
    sudo g++ -std=c++11 -c -o $@ $(CFLAGS) LidarPlusServo.cpp

objects/CloudManipulation.o: CloudManipulation.cpp $(ANDARHEADERS)
    sudo g++ -std=c++11 -c -o $@ $(CFLAGS) CloudManipulation.cpp

objects/RoverParameters.o: RoverParameters.cpp $(ANDARHEADERS)
    sudo g++ -std=c++11 -c -o $@ $(CFLAGS) RoverParameters.cpp

objects/csvReader.o: csvReader/csvReader.cpp $(ANDARHEADERS)
    sudo g++ -std=c++11 -c  -o $@ $(CFLAGS) csvReader/csvReader.cpp

objects/Dstar.o: Dstar.cpp $(ANDARHEADERS)
    sudo g++ -std=c++11 -c  -o $@ $(CFLAGS) Dstar.cpp

objects/LidarPathMapping.o: LidarPathMapping.cpp $(ANDARHEADERS)
    sudo g++ -std=c++11 -c  -o $@ $(CFLAGS) LidarPathMapping.cpp

【问题讨论】:

你想要静态库还是共享库? 共享在性能方面将是首选。如果您也能告诉我用户将如何使用该库,我将不胜感激:如何包含在 .cpp 文件和 g++ 编译命令中。谢谢。 【参考方案1】:

首先,这是一个有用的技巧。每个对象都有一个单独的规则:

objects/LidarPlusServo.o: LidarPlusServo.cpp $(ANDARHEADERS)
    sudo g++ -std=c++11 -c -o $@ $(CFLAGS) LidarPlusServo.cpp

objects/CloudManipulation.o: CloudManipulation.cpp $(ANDARHEADERS)
    sudo g++ -std=c++11 -c -o $@ $(CFLAGS) CloudManipulation.cpp

objects/RoverParameters.o: RoverParameters.cpp $(ANDARHEADERS)
    sudo g++ -std=c++11 -c -o $@ $(CFLAGS) RoverParameters.cpp

...

您正在使用自动变量$@,但您也可以使用$< 作为先决条件列表中的第一个参数:

objects/LidarPlusServo.o: LidarPlusServo.cpp $(ANDARHEADERS)
    sudo g++ -std=c++11 -c -o $@ $(CFLAGS) $<

objects/CloudManipulation.o: CloudManipulation.cpp $(ANDARHEADERS)
    sudo g++ -std=c++11 -c -o $@ $(CFLAGS) $<

objects/RoverParameters.o: RoverParameters.cpp $(ANDARHEADERS)
    sudo g++ -std=c++11 -c -o $@ $(CFLAGS) $<

...

请注意,所有这些规则都是相同的,除了目标和第一个先决条件,它们遵循一个简单的规则,objects/foo.o: foo.cpp。所以你可以用一个模式规则替换所有这些规则:

objects/%.o: %.cpp $(ANDARHEADERS)
    sudo g++ -std=c++11 -c -o $@ $(CFLAGS) $<

现在是构建和使用库。我对源文件的内部结构了解得不够多,无法确切知道需要进行哪些更改,但我将举一个简单的示例来展示该技术.

假设我有三个源文件,ant.cppbee.cppcrocket.cpp,以及它们各自的头文件,每个都包含一些类,其中一些相互依赖。现在我想将它们组合成一个共享库libInsect.so,以及一个关联的头文件Insect.h,并构建一个使用它的可执行文件bughunt

Insect.h 很简单:

#include "ant.h"
#include "bee.h"
#include "cricket.h"

现在是生成文件:

OBJECTS := ant.o bee.o cricket.o

%.o: %.cpp %.h
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -fPIC -c $< -o $@

libInsect.so: $(OBJECTS)
    $(CXX) -fPIC -shared -o $@ $^

bughunt: bughunt.cpp libInsect.so
    $(CXX) -L. $< -lInsect -o $@

【讨论】:

编译工作正常并创建了一个可执行文件,但是当我运行程序时它返回此错误消息:“加载共享库时出错::无法打开共享对象文件:否这样的文件或目录”我在与 driver.cpp 和 makefile 相同的目录中有一个 .so 文件的副本。我在 -L/path 中包含的另一个文件夹中还有一个副本,但它仍然找不到路径。我按照另一篇文章中的说明进行操作: $ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/my_library/path.so.something $ export LD_LIBRARY_PATH $ ./my_app 仍未找到 在与可执行文件位于同一目录的库中尝试一下。 (也许你已经有了,我无法从你的评论中看出。)如果这不起作用,尝试一些更简单的方法。你的系统太复杂了。尝试HelloWorld,然后使用静态库HelloWorld,然后使用共享库。 谢谢 Beta,它现在正在运行。我将库添加到 /usr/lib 文件夹,现在它工作正常。我将确保在 make install 文件中放置一个将库复制到该文件夹​​的命令。谢谢。

以上是关于制作具有多个类的库,附加预先存在的 .a 库和其他依赖项的主要内容,如果未能解决你的问题,请参考以下文章

如何将多个预先存在的 AWS 托管角色附加到策略?

电话号码规范化:任何预先存在的库?

html 演示基于预先存在的ID将数据附加到DOM元素

前端里的库和框架

检查是不是存在具有相同类的多个元素[重复]

在具有预先存在的表权限的用户之间共享 Oracle 视图