我正在研究一个现有的程序,它依赖于一个C库,一个相当古老的C,它有一个Makefile
和一个README
文件,它有一些修改Mag文件的指令,以便在不同的系统上成功编译。我的任务是清理程序的构建过程,这样就可以在不攻击makefile等的情况下进行移植,这意味着确保C库是可移植的。
例如,在最新版本的MacOS
上需要做的一件事是正确定义SIZEOF_VOID_P
,因为如果未定义,则默认为4
,这自然会在64位系统上导致可怕的segfaults。我刚刚在Makefile中将其定义为8,但显然现在我已经为32位系统断开了它。
我的想法最初只是写一个C文件,它的输出有一些#ifdef
s,如果他们缺少一个输出到现有的MaCfile文件的预置,就吐出适当的定义,但是它看起来有点古怪。无论如何,标准配置脚本似乎都是自己完成的,所以我想为什么不使用它们。我读到,可以用autoconf
生成配置脚本,但我不想废掉现有的生成文件(我担心它可能会导致比它解决的更多的问题)。我只想给它们加上一些适当的定义。
有什么好的原因吗?
最佳答案
如果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)
因为这个程序
#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);
}
它不是最优雅的解决方案,但如果您只需要一些常量,它就可以很好地工作。另一方面:对于更复杂的事情,例如:找到正确编译器的路径并用正确的参数调用它,找到某些库的路径并检查它们是否正确,等等,它会很快变得相当糟糕。