我正在开发一个依赖于C库的现有程序,实际上是一个相当古老的程序,只有一个Makefile
和一个README
文件,它有一些修改指令makefile在不同的系统上成功编译。我的任务是清理程序的构建过程,因此它可以移植而不会破坏makefile等,所以这意味着确保C库是可移植的。
例如,MacOS
的最新版本需要做的一件事就是正确定义SIZEOF_VOID_P
,因为如果未定义则默认为4
,这自然会导致64位系统出现可怕的段错误。我刚刚在Makefile中将其定义为8,但显然现在我已经为32位系统打破了它。
我的想法最初只是写一个C文件的输出有一些#ifdef
s吐出适当的定义,如果他们错过了输出到现有makefile的前置,但它似乎有点hacky。标准配置脚本似乎无论如何都会自己完成所有这些,所以我想为什么不使用它们。我读到可以使用autoconf
生成配置脚本,但我不想删除现有的makefile(我担心这可能会导致比它解决的更多问题)。我只是想为它们添加一些适当的定义。
这有什么好处吗?
答案 0 :(得分:1)
如果不能选择autoconf
,cmake
或类似程序,您可以执行与您自己的想法类似的操作。
CC=gcc
.PHONY: all
all: main
pre-build:
$(CC) constants.c -o constants
$(eval SIZEOF_VOID_P = $(shell ./constants "SIZEOF_VOID_P"))
$(eval FOOBAR = $(shell ./constants "FOOBAR"))
main: pre-build
@echo $(SIZEOF_VOID_P) $(FOOBAR)
程序constants
属于
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ALL CHECKS AND BALANCES OMITTED!
int main(int argc, char **argv){
if(argc != 2){
fprintf(stderr,"Usage: %s constant_to_test\n",argv[0]);
exit(EXIT_FAILURE);
}
// good for a couple of constants but should be changed
// to a proper parser if you have more than a dozen or so
if(strncmp(argv[1], "SIZEOF_VOID_P", 13 ) == 0){
printf("%zu\n",sizeof(void *));
}
else if (strncmp(argv[1], "FOOBAR", 6) == 0){
printf("%d\n",42);
}
// ...
else {
fprintf(stderr,"Constant %s unknown\n",argv[1]);
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
到目前为止,它不是最优雅的解决方案,但如果您需要的只是一些常量,它的效果很好。另一方面:对于更复杂的事情,它会很快变得非常讨厌,例如:找到正确编译器的路径并使用正确的参数调用它,找到一些库的路径并检查它们是否是正确的,等等等等。
答案 1 :(得分:0)
我不想丢弃现有的makefile(我担心它可能会导致比它解决的更多问题)。我只是想为它们添加一些适当的定义。
这有什么好处吗?
如果您准备假设GNU make,那么您可以依赖其include
指令将外部文件中的Makefile片段包含到现有的Makefile中。您可以修改现有的Makefile,在顶部或顶部附近添加一个或多个include
指令,代替需要调整以适应构建环境的部分。然后编写一个程序来分析系统并将相应的Make变量定义输出到相应的文件中。 include
指令不是POSIX make
的标准功能,但它可能不是一个可行的选项。
或者,可以在命令行上指定make
变量定义。例如,
make all SIZEOF_VOID_P=8
原则上,您可以通过以这种方式提供定义的包装脚本调用make
来设置所需的所有make变量。这样的脚本可能会动态确定所需的值,或者您可以通过单独的配置程序生成脚本。无论哪种方式,您可能需要修改现有的Makefile以抑制(重新)定义所涉及的变量。