这是我在这里的第一个问题,我希望以正确的方式完成所有事情。
我是一个相当新的 Ubuntu 用户,如果可能的话,我需要一些有关特定 Makefile 的帮助。我下载了 QEMU 2.1.0,目前正在为自定义版本更改一些源代码文件。特别是我有一个如下所示的 sd.c 文件:
[...]
#include "hw/mydistribution.h"
[...]
Nac = poisson_distribution(Nac_mean);
以及一个 mydistribution.h 文件,例如,我使用 GSL 库中的函数定义 poisson_distribution():
#include <math.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
[...]
unsigned int poisson_distribution(double expected_value) {
const gsl_rng_type * T;
gsl_rng * r;
unsigned int k;
gsl_rng_env_setup();
T = gsl_rng_default;
r = gsl_rng_alloc (T);
k = gsl_ran_poisson (r, expected_value);
gsl_rng_free (r);
return k;
}
现在,我知道如果我将上述所有部分放在同一个文件中 [例如 myfile.c],我可以使用以下命令从终端进行编译:
gcc myfile.c -o myfile -lgsl -lgslcblas -lm
并且它有效,因为我试过了。但是如何要求 QEMU Makefile 执行此操作?老实说,这个 Makefile 似乎对我的入门级来说太复杂了。我在 Google 上搜索了有关 makefile 的信息,阅读后,我认为在 QEMU Makefile 中找到类似以下内容的内容:
LDLIBS := -lgsl -lgslcblas -lm
[...]
$(CC) -o $@ $^ $(LDLIBS)
但在搜索真正的 QEMU Makefile 实现时,我发现了 rules.mak 文件,其中:
%.o: %.c
$(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $<," CC $(TARGET_DIR)$@")
也许这是需要调整的行。问题是:如何调整?我尝试将此行编辑为:
%.o: %.c
$(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) $($@-cflags) -c -o $@ $< -lgsl -lgslcblas -lm," CC $(TARGET_DIR)$@")
但它不起作用,我收到以下错误
ubuntu@ubuntu:~/Desktop/qemu-2.1.0$ make
GEN config-host.h
GEN trace/generated-tracers.h
GEN trace/generated-tracers.c
GEN arm-softmmu/config-target.h
LINK arm-softmmu/qemu-system-arm
../hw/sd/sd.o: In function `poisson_distribution':
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1630: undefined reference to `gsl_rng_env_setup'
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1632: undefined reference to `gsl_rng_default'
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1633: undefined reference to `gsl_rng_alloc'
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1641: undefined reference to `gsl_ran_poisson'
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1646: undefined reference to `gsl_rng_free'
../hw/sd/sd.o: In function `weibull_distribution':
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1676: undefined reference to `gsl_rng_env_setup'
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1678: undefined reference to `gsl_rng_default'
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1679: undefined reference to `gsl_rng_alloc'
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1687: undefined reference to `gsl_ran_weibull'
/home/ubuntu/Desktop/qemu-2.1.0/include/hw/mycard.h:1692: undefined reference to `gsl_rng_free'
collect2: error: ld returned 1 exit status
make[1]: *** [qemu-system-arm] Error 1
make: *** [subdir-arm-softmmu] Error 2
毕竟我认为这不是一个完美的解决方案,因为其他文件不需要 GSL 库,也不需要将 -lgsl -lgslcblas -lm 应用于每个 .c 文件。我想创建一个新的 Makefile,其中所有其他文件继续像原始 Makefile 一样进行编译,但当涉及到 sd.c 时,我希望它像前面所说的那样进行编译,以避免未定义的引用
在此先感谢那些为我提供精确建议以帮助我解决此问题的人
答案1
在此通配符行上方:
%.o: %.c
为特定文件添加特定规则:
myfile.o: myfile.c
gcc -c -o $@ $< -lgsl -lgslcblas -lm
答案2
我想经过几天的怀疑、研究、手册等等,我终于解决了我的问题,我想与你分享我的努力
在steeldriver发表评论后,我开始更加密切地关注链接阶段。我找到的解决方案是在模拟librt部分之前将以下几行添加到配置文件中:
##########################################
# Do we need libgsl0-dev
cat > $TMPC << EOF
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
int main(void) { return (int) gsl_ran_weibull_pdf (11, 10, 5); }
EOF
if compile_prog "" "" ; then
:
elif compile_prog "" "-lgsl -lgslcblas" ; then
LIBS="-lgsl -lgslcblas $LIBS"
libs_qga="-lgsl -lgslcblas $libs_qga"
else
error_exit "libgsl0-dev check failed"
fi
gsl_ran_weibull_pdf (11, 10, 5) 的目的是验证 libgsl0-dev 是否存在。如果我们有它,那么当我们找到 -lgsl -lgslcblas 时,我们就可以正确解释它们,否则用户将被告知此库不存在
现在当我输入:ubuntu@ubuntu:~/Desktop/qemu-2.1.0$ make
不再有未定义的引用:
GEN config-host.h
GEN trace/generated-tracers.h
GEN trace/generated-tracers.c
CC hw/sd/sd.o
GEN arm-softmmu/config-target.h
LINK arm-softmmu/qemu-system-arm
GEN arm-linux-user/config-target.h
我相信这个解决方案可以进一步完善,我愿意接受任何新的建议。但我承认,找到这个结果已经让我非常高兴
特别感谢@muru 和@steeldriver 的支持