如何在gcc中指定库路径?

Sav*_*rio 3 c gcc

我正在使用OpenCV调用编写程序,我想编译它并生成可执行文件.我已经阅读了gcc教程,但我仍然想知道如何链接我正在使用的OpenCV库.我的命令和相关输出如下:

$ gcc -I/home/savio/opencv-3.0.0/include/opencv -L/home/savio/opencv-3.0.0/cmake_binary_dir/lib \
>     -lopencv_core -lopencv_highgui -lopencv_imgproc imagefilter.c -o imagefilter
/tmp/ccDUEgAk.o: nella funzione "cvDecRefData":
imagefilter.c:(.text+0xa6a): riferimento non definito a "cvFree_"
imagefilter.c:(.text+0xaf2): riferimento non definito a "cvFree_"
/tmp/ccDUEgAk.o: nella funzione "cvGetRow":
imagefilter.c:(.text+0xc08): riferimento non definito a "cvGetRows"
/tmp/ccDUEgAk.o: nella funzione "cvGetCol":
imagefilter.c:(.text+0xc36): riferimento non definito a "cvGetCols"
/tmp/ccDUEgAk.o: nella funzione "cvReleaseMatND":
imagefilter.c:(.text+0xc50): riferimento non definito a "cvReleaseMat"
/tmp/ccDUEgAk.o: nella funzione "cvSubS":
imagefilter.c:(.text+0xdac): riferimento non definito a "cvAddS"
/tmp/ccDUEgAk.o: nella funzione "cvCloneSeq":
imagefilter.c:(.text+0xde5): riferimento non definito a "cvSeqSlice"
/tmp/ccDUEgAk.o: nella funzione "cvSetNew":
imagefilter.c:(.text+0xe52): riferimento non definito a "cvSetAdd"
/tmp/ccDUEgAk.o: nella funzione "cvGetSetElem":
imagefilter.c:(.text+0xefa): riferimento non definito a "cvGetSeqElem"
/tmp/ccDUEgAk.o: nella funzione "cvReadIntByName":
imagefilter.c:(.text+0xfa9): riferimento non definito a "cvGetFileNodeByName"
/tmp/ccDUEgAk.o: nella funzione "cvReadRealByName":
imagefilter.c:(.text+0x1053): riferimento non definito a "cvGetFileNodeByName"
/tmp/ccDUEgAk.o: nella funzione "cvReadStringByName":
imagefilter.c:(.text+0x10e6): riferimento non definito a "cvGetFileNodeByName"
/tmp/ccDUEgAk.o: nella funzione "cvReadByName":
imagefilter.c:(.text+0x1126): riferimento non definito a "cvGetFileNodeByName"
imagefilter.c:(.text+0x113c): riferimento non definito a "cvRead"
/tmp/ccDUEgAk.o: nella funzione "cvContourPerimeter":
imagefilter.c:(.text+0x1170): riferimento non definito a "cvArcLength"
/tmp/ccDUEgAk.o: nella funzione "cvCalcHist":
imagefilter.c:(.text+0x11b2): riferimento non definito a "cvCalcArrHist"
/tmp/ccDUEgAk.o: nella funzione "cvEllipseBox":
imagefilter.c:(.text+0x127e): riferimento non definito a "cvEllipse"
/tmp/ccDUEgAk.o: nella funzione "cvFont":
imagefilter.c:(.text+0x12c8): riferimento non definito a "cvInitFont"
/tmp/ccDUEgAk.o: nella funzione "main":
imagefilter.c:(.text+0x1396): riferimento non definito a "cvLoadImage"
imagefilter.c:(.text+0x13af): riferimento non definito a "cvGetSize"
imagefilter.c:(.text+0x13c1): riferimento non definito a "cvCreateImage"
imagefilter.c:(.text+0x13ed): riferimento non definito a "cvSmooth"
imagefilter.c:(.text+0x1403): riferimento non definito a "cvSaveImage"
imagefilter.c:(.text+0x141b): riferimento non definito a "cvReleaseImage"
imagefilter.c:(.text+0x1427): riferimento non definito a "cvReleaseImage"
collect2: error: ld returned 1 exit status
$
Run Code Online (Sandbox Code Playgroud)

我该如何正确指定库?


我运行下面的命令.它编译和链接但不能正确运行:

$ gcc imagefilter.c -o imagefilter -I/home/savio/opencv-3.0.0/include/opencv \
>     -L/home/savio/opencv-3.0.0/cmake_binary_dir/lib \
>     -lopencv_imgcodecs -lopencv_imgproc -lopencv_highgui -lopencv_core
$ ./imagefilter lena_noise.BMP
./imagefilter: error while loading shared libraries: libopencv_imgcodecs.so.3.0: cannot open shared object file: No such file or directory
$
Run Code Online (Sandbox Code Playgroud)

我还缺少什么?

Ere*_*ith 7

将-L和-l移动到命令行的末尾:

gcc imagefilter.c -o imagefilter -I/home/savio/opencv-3.0.0/include/opencv -L/home/savio/opencv-3.0.0/cmake_binary_dir/lib -lopencv_core -lopencv_highgui -lopencv_imgproc 
Run Code Online (Sandbox Code Playgroud)

  • 指定库名的`-l` 选项应该出现在目标文件名之后。指定库目录的`-L` 选项应该出现在存储在目录中的库的`-l` 选项之前。 (2认同)

Jon*_*ler 6

链接

对于链接,请确保在库(-lxxx选项)之前指定目标文件(或源文件)。并确保-L给定库的-l选项出现在使用它的选项之前。库的顺序很重要;按顺序列出库,以便库在后面列出的库中列出较早的参考代码。(在设计库集时,避免库之间的循环引用;它们是一种瘟疫。)

$ gcc imagefilter.c -o imagefilter -I/home/savio/opencv-3.0.0/include/opencv \
>     -L/home/savio/opencv-3.0.0/cmake_binary_dir/lib \
>     -lopencv_imgcodecs -lopencv_imgproc -lopencv_highgui -lopencv_core
Run Code Online (Sandbox Code Playgroud)

跑步

编译器/链接器和运行时系统都需要能够找到共享对象。您可以使用该-L选项告诉链接器在哪里可以找到库。您可以通过多种方式告诉运行时(动态加载器)在哪里可以找到库:

  1. 在某些系统上,您可以-R向命令行添加一个选项来指定在运行时可以找到库的位置:

    $ gcc imagefilter.c -o imagefilter -I/home/savio/opencv-3.0.0/include/opencv \
    >     -L/home/savio/opencv-3.0.0/cmake_binary_dir/lib \
    >     -R/home/savio/opencv-3.0.0/cmake_binary_dir/lib \
    >     -lopencv_imgcodecs -lopencv_imgproc -lopencv_highgui -lopencv_core
    
    Run Code Online (Sandbox Code Playgroud)

    并非所有系统都支持此选项。如果你的没有,你必须继续前进。

    此选项的缺点是您指定的位置嵌入在二进制文件中。如果客户机器上的库不在同一位置,则不会找到该库。因此,某人主目录下的路径仅适用于其计算机上的该用户——不适用于一般人群。OTOH,如果软件默认安装在,例如/opt/packagename/lib,那么指定 with-R可能是合适的。

  2. 将目录添加到LD_LIBRARY_PATH环境变量(或其等效项;例如,DYLD_LIBRARY_PATH在 Mac OS X 或SHLIB_PATHHP-UX IIRC 上)。

    LD_LIBRARY_PATH=/home/savio/opencv-3.0.0/cmake_binary_dir/lib:$LD_LIBRARY_PATH \
    ./imagefilter
    
    Run Code Online (Sandbox Code Playgroud)

    或者:

    export LD_LIBRARY_PATH=/home/savio/opencv-3.0.0/cmake_binary_dir/lib:$LD_LIBRARY_PATH
    ./imagefilter
    
    Run Code Online (Sandbox Code Playgroud)

    第一个符号在程序运行期间设置环境变量。例如,如果您需要比较库的两个版本的行为,它会很有用。第二个符号设置会话的环境变量。您可以将其包含在您的.profile或等效中,以便它适用于每个会话。

    有些系统也有LD_RUN_PATH环境变量。并且有些具有环境变量的 32 位和 64 位变体。

    这对用户和安装人员来说都是繁琐的;您如何确保为使用您代码的每个人设置了环境变量?然后运行真实程序的环境设置 shell 脚本可以在这里提供帮助。

  3. 将该目录添加到配置文件中,该文件指定动态加载程序要搜索的已知目录列表。不用说,这是特定于平台的——文件名、格式、位置(通常在/etc某处)和用于编辑它的机制。该文件可能是/etc/ld.so.conf. 可能有一个程序可以正确编辑配置文件。

  4. 将库安装在无论如何都会被搜索的位置(无需重新配置动态加载程序)。这可能是/usr/lib,或者可能是/usr/local/lib其他一些相关目录。


Dan*_*Dan 5

我的 IDE 处理该过程的方式是将 -L 标记放在前面,将 -l 标记放在末尾。所有 -l 标记都需要位于目标之后,以便编译器知道在搜索之前需要解析哪些符号。

gcc -L/path/to/library -o target_here -lfirst -lsecond -lthird ...
Run Code Online (Sandbox Code Playgroud)