这似乎是一个常见的问题,但我无法解决这个问题。
我有一些使用makefile编译的.c代码。目标是创建一个共享对象(.so),以便我可以从R运行C代码。
这是我的makefile:
obs = R_wrapper.o G.o develop.o utilities.o
CFLAGS = -arch x86_64 -std=gnu99 -I/Library/Frameworks/R.framework/Resources/include -I/Library/Frameworks/R.framework/Resources/include/x86_64 -DNDEBUG -I/usr/local/include -fPIC -g -O3 -c
LFLAGS = -arch x86_64 -std=gnu99 -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -single_module -multiply_defined suppress -L/usr/local/lib -O3 -lgsl -lm -lgslcblas
R_wrapper : $(obs)
$gcc $(LFLAGS) $(obs) -o R_wrapper.so
R_wrapper.o : R_wrapper.c constants.h develop.h G.h
$gcc $(CFLAGS) R_wrapper.c
G.o : G.c G.h constants.h utilities.h develop.h
$gcc $(CFLAGS) G.c develop.c
develop.o : develop.c develop.h G.h constants.h
$gcc $(CFLAGS) develop.c
utilities.o : utilities.c develop.h
$gcc $(CFLAGS) utilities.c
它在我的实验室中的计算机上工作正常,但它在我的个人计算机上不起作用。造成这个问题的原因是我的R_wrapper.c开头的这两行。
#include </opt/local/include/gsl/gsl_randist.h>
#include </opt/local/include/gsl/gsl_rng.h>
我试图移动这些文件并给出不同的路径,将gal_type.h文件中的文件放在与我的R_wrapper文件相同的目录中,我试图重命名我的目录,以便路径更传统但是操作系统没有授予我将opt
重命名为usr
的权利(这可能很明显)。我没有创建makefile,也没有完全得到它。我想我需要在-I
或CFLAGS
中的某个LFLAGS
参数之后修改路径。
编辑1
我在实验室计算机上更改了R_wrapper.c
以摆脱#include <...>
中的整个路径。编辑失败,因为@Beta预测。然后,我更改了我的makefile,将-I/opt/local/include/gsl
添加到CFLAGS
。我不知道你的意思Verify that the makefile still works.
我试图在我的实验室计算机上使用我编辑的makefile进行编译,但它失败了。然后我重新编辑了我的makefile,将-I/opt/local/include/gsl
更改为-I/usr/local/include/gsl
,因为在我的实验室计算机上gsl
文件夹位于/usr/local/include/gsl
。 -I/opt/local/include/gsl
是我计算机上gsl
文件夹的位置。所以我在你的程序中被困在这里。
修改2
我将gsl
文件夹移到我的计算机上,试图从不同的路径中加入。一些有趣的事情发生了。例如,当我将gsl
文件夹放入Users/remi/Documents/Biologie/programing/C/
并写入(CFLAGS
中)
-I/Users/remi/Documents/Biologie/programing/C/
我收到此错误:
R_wrapper.c:43:10: fatal error: 'gsl_randist.h' file not found
#include <gsl_randist.h> // goal.
当我写(CFLAGS
)
Users/remi/Documents/Biologie/programing/C/gsl
我收到此错误消息:
"In file included from R_wrapper.c:43: /Users/remi/Documents/Biologie/programing/C/gsl/gsl_randist.h:22:10: fatal error:
'gsl/gsl_rng.h' file not found
#include <gsl/gsl_rng.h>"
答案 0 :(得分:4)
转移评论以回答
根据编辑2中提到的gsl/gsl_rng.h
未找到的消息判断,您应该写
#include <gsl/gsl_randist.h>
源代码中的(标题名称前面的gsl/
的路径前缀)。这是一个常见的惯例。然后,在-I
选项中指定包含gsl
子目录的目录的名称,该子目录包含gsl_*.h
标头。在编辑2中,您说您将gsl
目录放入/Users/remi/Documents/Biologie/programing/C/
,因此您可以正确使用:
-I/Users/remi/Documents/Biologie/programing/C/
您尝试在命令行上。
您应该阅读文档,如果它写了以下任何一个:
#include <gsl/gsl_randist.h>
#include "gsl/gsl_randist.h"
那么你应该在你的代码中写一下,因为(如你所发现的那样),如果不这样做,那就不行了。
一般来说,除非你真的需要,否则将路径写入
#include
语句是个坏主意;它只会导致这种问题。
我同意,但会更强烈地说明:
#include
语句中写完整的路径。如果你编写它们,它会从根本上限制代码的可移植性。您不能依赖其他人的计算机安装在与系统上安装的相同位置的计算机。如果你在开源软件中试过它,你就会被嘲笑。
警惕那些对../somedir/header.h
感到可爱的人 - 请参阅What are the benefits of a relative path such as "../include/header.h" for a header?。
我发现GNU Scientific Library手册的example program开始了:
#include <stdio.h>
#include <gsl/gsl_sf_bessel.h>
和Compiling and Linking上的部分说:
库头文件安装在自己的
gsl
目录中。您应该编写任何带有gsl/
目录前缀的预处理程序include语句,#include <gsl/gsl_math.h>
如果目录未安装在编译器的标准搜索路径上,则还需要将其位置作为命令行标志提供给预处理器。
gsl
目录的默认位置为/usr/local/include/gsl
。
答案 1 :(得分:3)
一般来说,除非你真的需要,否则将路径写入#include
语句是个坏主意;它只会导致这种问题。
在实验室计算机上,修改R_wrapper.c
:
#include <gsl_randist.h>
#include <gsl_rng.h>
构建现在应该失败。如果是这样,那么这将验证您是否没有其他版本的这些标头浮动,或链接到它们,或者其他什么。确认它失败,然后退出更改,并确认它再次有效。
然后将-I/opt/local/include/gsl
添加到CFLAGS
。 验证makefile是否仍然有效。
然后再次修改R_wrapper.c
;现在构建应该成功。
确定您希望在个人计算机上保留这些文件(gsl_randist.h
和gsl_rnd.h
)的位置,并相应地修改您的家庭版makefile上的CFLAGS
。
一旦完成所有这些工作,我们就可以向您展示如何编写一个可在两台机器上运行的makefile。
此外,您可以通过其他方式改进您的makefile规则,但我必须首先提出一个问题:
G.o : G.c G.h constants.h utilities.h develop.h
$gcc $(CFLAGS) G.c develop.c
G.o
真的需要develop.c
吗?如果是这样,那么你应该重新检查你的源文件,因为这真的是不卫生的。